zoukankan      html  css  js  c++  java
  • 5:《地牢守卫者》代码分析:EnemyController


      紧接着Enemy将要查看EnemyController,EnemyController继承自AIController。

      一个典型方法让敌人找到玩家

      

    var Pawn Enemy;

      event Tick(float DeltaTime)

      {

        local PlayerController PC;

        if(Enemy==none) 

       {

        Foreach LocalPlayerControllers(class'PlayerController',pC)

        {

          if(PC.Pawn!=none)

          Enemy=PC.Pawn;

        }
       }

      }

    在foreach中如果找不到玩家的pawn,可以让敌人暂时停下

    pawn.Acceleration.x=0;

    Pawn.Acceleration.y=0;

    有一个官方函数PawnDied(Pawn inpawn),旨在表述pawn死了的执行动作

    function PawnDied(pawn inpawn)

    {

      if(inpawn==pawn)

      Enemy=none;

      super.PawnDied(inpawn);

    }

    下来是重点,寻路一直是个有难度的地方。这里提到两个函数

    1.MoveTo (vector NewDestination, optional Actor ViewFocus, optional float DestinationOff)

    该函数在没有寻路的情况下可以让pawn走到一个坐标位置

    2.MoveToward((Actor NewTarget, optional Actor ViewFocus, optional float DestinationOffset)

    可以让一个pawn走向一个Actor。

    因此最简单的一种方法是在controller中写一个状态

    var actor Enemy;

    auto state Follow
    {
    Begin:
    Enemy=GetALocalPlayerController().Pawn;
    MoveToward(Enemy,Enemy,128);
    goto 'Begin'; //因为MoveToward只能执行一次,用该方法循环执行
    }

    下来这个环节是重要的寻路算法,同时使用了MoveToward和MoveTo两个函数,前者是当寻路成立时可以直接到达目标Actor,后者是在寻路不成立时让该pawn暂时先行前进到临时TempDest目标点。

    自动进入Idle然后获取Player.

    auto state Idle
    {
    event SeePlayer(pawn inpawn) //参数是看见的pawn
    {
    local pawn Player;
    if((Player=GetALocalPlayerController().pawn)!=none)
    { super.SeePlayer(Player);
    Enemy=Player;
    Gotostate('Follow');}
    }
    Begin:
    }

    获取了Enemy将进行寻路

    state Follow
    {
    ignores SeePlayer;
    //该函数寻路看能否找到目标点
    function bool FindNavMeshPath()
    {
    // Clear cache and constraints (ignore recycling for the moment)
    NavigationHandle.PathConstraintList = none;
    NavigationHandle.PathGoalList = none;

    // Create constraints
    class'NavMeshPath_Toward'.static.TowardGoal( NavigationHandle,Enemy ); //寻找Enemy
    class'NavMeshGoal_At'.static.AtActor( NavigationHandle, Enemy,32 );

    // Find path
    return NavigationHandle.FindPath();
    }

    Begin:
    if(NavigationHandle.ActorReachable(Enemy)) //无障碍物,最好的情况就是能找到
    {
    MoveToward( Enemy,Enemy ); //直接走向敌人 AAAAAAAAAAaaaaAAAAAAAA
    }

    else if(FindNavMeshPath) //如果有障碍,在寻路状态,则进入临时目标点
    {
    NavigationHandle.SetFinalDestination(Enemy.Location); //敌人位置

    // move to the first node on the path
    if( NavigationHandle.GetNextMoveLocation( TempDest, Pawn.GetCollisionRadius()) )
    {
    MoveTo( TempDest, Enemy ); //先找到临时节点,Enemy是最重要找的对象
    }
    }

    else //最糟的结果是找不到,可能玩家已经死了。也就没必要再找了
    {
    GotoState('Idle');
    }

    Goto 'Begin'; //保持了更新查找
    }


    《求生之路》中有些敌人是在场景中Idle的状态,而有些敌人一生成就会朝玩家涌过来。只要在Idle中不用seePlayer而是直接遍历将会生成涌向玩家的敌人。
    在前面的AAAAAAAAAAaaaaAAAAAAAA标记地方修改进入Attacking状态攻击敌人

    MoveToward(Enemy,Enemy,300);

    if(VSize(Enemy.Location-Location)<500)

    GotoState('Attacking');

     以下是攻击状态

    state Attacking
    {
    function NotifyTakeHit(Controller InstigatedBy, vector HitLocation, int Damage, class<DamageType> damageType, vector Momentum)
    {
    PopState();
    super.NotifyTakeHit(InstigatedBy, HitLocation, Damage, damageType, Momentum);
    }

    event BeginState(Name PreviousStateName)
    {
    super.BeginState(PreviousStateName);
    AntEnemy(pawn).StartedAttack();
    }

    event EndState(Name PreviousStateName)
    {
    super.EndState(PreviousStateName);
    AntEnemy(pawn).EndedAttack();
    }

    }

    攻击状态结束

    如果受到伤害将进入受伤状态,在子类中将实现受伤动画播放,在这期间体制所有的latent函数,以及固定敌人角色的位置。这边是硬直的前身。

    state Hurt
    {
    StopLatentExecution(); //停止所有的行为state

    Pawn.Acceleration.X=0;
    Pawn.Acceleration.Y=0;
    Pawn.Acceleration.Z=0;

    //播放受伤动画
    PopState();
    }




     

  • 相关阅读:
    两个栈实现队列
    重建二叉树
    最大的K个数
    堆排序
    Android 强制竖屏
    屏蔽输入框的焦点
    Android 全屏显示的方法(不包含状态栏)
    android 布局之scrollview
    clean之后R文件消失
    thinkphp
  • 原文地址:https://www.cnblogs.com/NEOCSL/p/2367763.html
Copyright © 2011-2022 走看看