• 10UEC++吃豆人[吃超级豆子和改变游戏状态]


    当玩家吃掉超级豆子,就会让所有的敌人变虚弱。

    我们打开游戏模式类。添加函数

    1. //将所有敌人变虚弱
    2. void SetEnermiesVolunerable();

    定义这个函数

    1. void APacmanGameModeBase::SetEnermiesVolunerable()
    2. {
    3. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    4. {
    5. (*Iter)->SetVulnerable();
    6. }
    7. }

    然后打开玩家类

    完善吃豆子逻辑

    1. //发生重叠,就会调用这个函数
    2. void APacdotPlayer::OnPacmanBeginOverlay(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
    3. {
    4. if (OtherActor->IsA(APacdot::StaticClass()))
    5. {
    6. //当前的豆子
    7. APacdot* CurrentPacdot = Cast(OtherActor);
    8. //判断是否是超级豆子
    9. if (CurrentPacdot->bIsSuperPacdot)
    10. {
    11. //让所有的敌人变虚弱
    12. ModeBaseRef->SetEnermiesVolunerable();
    13. }
    14. OtherActor->Destroy();
    15. //更新一下豆子的数量
    16. ModeBaseRef->SetPacdotNum(ModeBaseRef->GetPacdotNum()-1);
    17. }
    18. }

    ===========================

    完善一下游戏状态逻辑

    只有当游戏在游玩状态,我们才可以控制角色

    1. void APacdotPlayer::MoveX(float value)
    2. {
    3. //用if包裹起来
    4. if (ModeBaseRef->GetCurrentState() == EGameState::EPlay)
    5. {
    6. Vlocity.X = value;
    7. Vlocity.Y = 0;
    8. //character自带的函数,我们把向量喂给他就可以了
    9. AddMovementInput(Vlocity);
    10. if (value > 0)
    11. {
    12. SetActorRotation(FRotator(0, 0, 0));
    13. }
    14. else if (value < 0)
    15. {
    16. SetActorRotation(FRotator(0, -180, 0));
    17. }
    18. }
    19. }
    1. void APacdotPlayer::MoveY(float value)
    2. {
    3. if包裹起来
    4. if (ModeBaseRef->GetCurrentState() == EGameState::EPlay)
    5. {
    6. Vlocity.X = 0;
    7. Vlocity.Y = value;
    8. AddMovementInput(Vlocity);
    9. if (value > 0)
    10. {
    11. SetActorRotation(FRotator(0, 90, 0));
    12. }
    13. else if (value < 0)
    14. {
    15. SetActorRotation(FRotator(0, -90, 0));
    16. }
    17. }
    18. }
    1. //发生重叠,就会调用这个函数
    2. void APacdotPlayer::OnPacmanBeginOverlay(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
    3. {
    4. if包裹起来
    5. if (ModeBaseRef->GetCurrentState() == EGameState::EPlay)
    6. {
    7. if (OtherActor->IsA(APacdot::StaticClass()))
    8. {
    9. //当前的豆子
    10. APacdot* CurrentPacdot = Cast(OtherActor);
    11. //判断是否是超级豆子
    12. if (CurrentPacdot->bIsSuperPacdot)
    13. {
    14. //让所有的敌人变虚弱
    15. ModeBaseRef->SetEnermiesVolunerable();
    16. }
    17. OtherActor->Destroy();
    18. //更新一下豆子的数量
    19. ModeBaseRef->SetPacdotNum(ModeBaseRef->GetPacdotNum());
    20. }
    21. }
    22. }

    =============================

    实现重新游戏

    打开游戏模式类,定义重启游戏函数

    1. void APacmanGameModeBase::ReStartGame()
    2. {
    3. GetWorld()->GetFirstLocalPlayerFromController()->ConsoleCommand(TEXT("RestartLevel"));
    4. }

    定义暂停游戏函数

    1. void APacmanGameModeBase::PauseGame()
    2. {
    3. if (GetCurrentState() == EGameState::EPlay)
    4. {
    5. SetCurrentState(EGameState::EPause);
    6. }
    7. else if (GetCurrentState() == EGameState::EPause)
    8. {
    9. SetCurrentState(EGameState::EPlay);
    10. }
    11. }

    现在定义一下改变状态函数

    1. void APacmanGameModeBase::SetCurrentState(EGameState value)
    2. {
    3. CurrentState = value;
    4. switch (CurrentState)
    5. {
    6. case EGameState::EMenu:
    7. break;
    8. case EGameState::EPlay:
    9. //改变敌人的移动
    10. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    11. {
    12. (*Iter)->SetMovement(true);
    13. }
    14. //改变玩家的移动
    15. Cast< APacdotPlayer>(GetWorld()->GetFirstPlayerController()->GetPawn())->SetMovement(true);
    16. break;
    17. case EGameState::EPause:
    18. //改变敌人的移动,并清除计时器
    19. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    20. {
    21. (*Iter)->SetMovement(false);
    22. GetWorldTimerManager().ClearAllTimersForObject(*Iter);
    23. }
    24. //改变玩家的移动
    25. Cast< APacdotPlayer>(GetWorld()->GetFirstPlayerController()->GetPawn())->SetMovement(false);
    26. break;
    27. case EGameState::EWin:
    28. //销毁所有敌人
    29. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    30. {
    31. (*Iter)->Destroy();
    32. }
    33. break;
    34. case EGameState::EGameOver:
    35. //改变敌人的移动并清除计时器
    36. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    37. {
    38. (*Iter)->SetMovement(false);
    39. GetWorldTimerManager().ClearAllTimersForObject(*Iter);
    40. }
    41. //改变玩家的移动
    42. Cast< APacdotPlayer>(GetWorld()->GetFirstPlayerController()->GetPawn())->SetMovement(false);
    43. break;
    44. default:
    45. break;
    46. }
    47. }

    =======================

    打开游戏模式类,声明保存和还原计时器函数

    1. //记录所有敌人计时器
    2. void RecordEnermiesTimer();
    3. //还原所有敌人计时器
    4. void RestoreEnermiesTimer();

    再声明一个私有容器属性,存放每个敌人计时器剩余时间

    1. //每个敌人计时器剩余时间
    2. TArray<float> EnermisRemainingTime;

    定义RecordEnermiesTimer()函数

    1. //用来记录计时器剩余时间
    2. void APacmanGameModeBase::RecordEnermiesTimer()
    3. {
    4. //清空容器
    5. EnermisRemainingTime.Empty();
    6. //遍历场景中的敌人
    7. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    8. {
    9. //正常状态
    10. if ((*Iter)->bIsVulnerable == false && (*Iter)->bIsDeath == false)
    11. {
    12. EnermisRemainingTime.Add(-1);
    13. }
    14. //虚弱状态
    15. if ((*Iter)->bIsVulnerable == true && (*Iter)->bIsDeath == false)
    16. {
    17. //存储计时器
    18. float VulnerableRemainingTime = GetWorldTimerManager().GetTimerRemaining((*Iter)->VulnerableTimerHandle);
    19. EnermisRemainingTime.Add(VulnerableRemainingTime);
    20. }
    21. //死亡状态
    22. if ((*Iter)->bIsDeath == true)
    23. {
    24. //存储计时器
    25. float DeathRemainingTime = GetWorldTimerManager().GetTimerRemaining((*Iter)->DeathTimerHandle);
    26. EnermisRemainingTime.Add(DeathRemainingTime);
    27. }
    28. }
    29. }

    定义恢复计时器函数

    1. //回复计时器
    2. void APacmanGameModeBase::RestoreEnermiesTimer()
    3. {
    4. for (auto Iter(Enermis.CreateIterator()); Iter; ++Iter)
    5. {
    6. //虚弱状态
    7. if ((*Iter)->bIsVulnerable == true && (*Iter)->bIsDeath == false)
    8. {
    9. (*Iter)->SetVulnerable(true, EnermisRemainingTime[Iter.GetIndex()]);
    10. }
    11. //死亡状态
    12. if ((*Iter)->bIsDeath == true)
    13. {
    14. (*Iter)->SetDeath(true, EnermisRemainingTime[Iter.GetIndex()]);
    15. }
    16. }
    17. }

    此时我们完善一下pause()暂停函数

    1. void APacmanGameModeBase::PauseGame()
    2. {
    3. if (GetCurrentState() == EGameState::EPlay)
    4. {
    5. //暂停之后,记录剩余时间
    6. RecordEnermiesTimer();
    7. SetCurrentState(EGameState::EPause);
    8. }
    9. else if (GetCurrentState() == EGameState::EPause)
    10. {
    11. //暂停之后,恢复剩余时间
    12. RestoreEnermiesTimer();
    13. SetCurrentState(EGameState::EPlay);
    14. }
    15. }

  • 相关阅读:
    【ASP.NET Core】MVC 控制器的模型绑定(宏观篇)
    解决Unity打包时,Android SDK 报错问题
    [附源码]Python计算机毕业设计Django的酒店预订系统设计与实现
    MFC图形函数学习03——画直线段函数
    “秋天第一只大闸蟹”背后,看见京东一体化供应链
    Python双线性插值和双三次插值
    Java学习笔记6.1.3 字节流 - 字节流缓冲区与缓冲字节流
    TensorFlow和Pytorch两种机器学习框架的比较及优缺点
    安装Python
    Nginx ngx_http_auth_request_module模块鉴权【下】携带账号密码登录
  • 原文地址:https://blog.csdn.net/zhang2362167998/article/details/127424180