徘徊&追逐AI代码无法正常工作

时间:2014-04-18 02:53:55

标签: c# xna artificial-intelligence behavior

将一个敌人的AI系统放在一个敌人身上,当玩家不在敌人的距离内时,它应该闲着四处闲逛,当玩家在敌人距离内时,它应该启动追逐行为并追逐玩家直到玩家设法退出敌人的追逐半径。

目前敌人能够自由地想知道当玩家进入敌人附近时敌人会继续游荡而不是追逐玩家。

有人帮我解决了这个问题吗?

代码如下。

public enum AIState
    {
        Chasing,           
        Wander
    }

    private float maxSpeed;
    private float maxRotation;
    private float chaseDistance; 
    private float hysteresis;

    private Texture2D texture;
    private Vector2 drawingOrigin;
    private Vector2 position;
    public AIState aiState = AIState.Wander;
    private float orientation;

    private Random random = new Random();
    private Rectangle viewportbounds;
    public Rectangle boundingBox;
    public Vector2 playerPosition;

    private Vector2 heading;


    public Virtual_Aliens(Rectangle pos, Rectangle b)
    {


        position = new Vector2(300, 400);

        boundingBox = new Rectangle(pos.X, pos.Y, pos.Width, pos.Height);

        viewportbounds = new Rectangle(b.X, b.Y, b.Width, b.Height);

        orientation = 0.0f;

        heading = new Vector2(0, 0);

        maxSpeed = 2.0f;

        maxRotation = 0.20f;

        hysteresis = 15.0f;

        chaseDistance = 250.0f;

        Thread.Sleep(200);

        random = new Random();

    }

    public void LoadContent(ContentManager Content)
    {
        texture = Content.Load<Texture2D>("images/asteroid");
    }

    private Vector2 OrientationAsVector(float orien)
    {
        Vector2 orienAsVect;

        orienAsVect.X = (float)Math.Cos(orien);
        orienAsVect.Y = (float)Math.Sin(orien);

        return orienAsVect;
    }

    Vector2 wanderPosition = new Vector2();

    public void Wander()
    {
        // the max +/- the agent will wander from its current position
        float wanderLimits = 0.5f;

        // this defines what proportion of its maxRotation speed the agent will turn
        float turnFactor = 0.15f;

        // randomly define a new position
        wanderPosition.X += MathHelper.Lerp(-wanderLimits, wanderLimits, (float)random.NextDouble());
        wanderPosition.Y += MathHelper.Lerp(-wanderLimits, wanderLimits, (float)random.NextDouble());

        if (wanderPosition != Vector2.Zero)
        {
            wanderPosition.Normalize();
        }

        orientation = TurnToFace(wanderPosition, orientation, turnFactor * maxRotation);

        heading = OrientationAsVector(orientation);

        position += heading * 0.5f * maxSpeed;

        WrapForViewport();
    }

    private void WrapForViewport()
    {
        if (position.X < 0)
        {
            position.X = viewportbounds.Width;
        }
        else if (position.X > viewportbounds.Width)
        {
            position.X = 0;
        }

        if (position.Y < 0)
        {
            position.Y = viewportbounds.Height;
        }
        else if (position.Y > viewportbounds.Height)
        {
            position.Y = 0;
        }
    }

    private float WrapAngle(float radian)
    {
        while (radian < -MathHelper.Pi)
        {
            radian += MathHelper.TwoPi;
        }
        while (radian > MathHelper.Pi)
        {
            radian -= MathHelper.TwoPi;
        }
        return radian;
    }

    private float TurnToFace(Vector2 steering, float currentOrientation, float turnSpeed)
    {
        float newOrientation;
        float desiredOrientation;
        float orientationDifference;

        float x = steering.X;
        float y = steering.Y;

        // the desiredOrientation is given by the steering vector
        desiredOrientation = (float)Math.Atan2(y, x);

        // find the difference between the orientation we need to be
        // and our current Orientation
        orientationDifference = desiredOrientation - currentOrientation;

        // now using WrapAngle to get result from -Pi to Pi 
        // ( -180 degrees to 180 degrees )
        orientationDifference = WrapAngle(orientationDifference);

        // clamp that between -turnSpeed and turnSpeed.
        orientationDifference = MathHelper.Clamp(orientationDifference, -turnSpeed, turnSpeed);

        // the closest we can get to our target is currentAngle + orientationDifference.
        // return that, using WrapAngle again.
        newOrientation = WrapAngle(currentOrientation + orientationDifference);

        return newOrientation;
    }

    public void Update(GameTime gameTime)
    {            
        if (aiState == AIState.Wander)
        {
            chaseDistance -= hysteresis / 2;
        }

        else if (aiState == AIState.Chasing)
        {
            chaseDistance += hysteresis / 2;    
        }

        float distanceFromPlayer = Vector2.Distance(position, playerPosition);

        if (distanceFromPlayer > chaseDistance)
        {     
            aiState = AIState.Wander;
        }
        else
        {
            aiState = AIState.Chasing;
        }

        float currentSpeed;

        if (aiState == AIState.Chasing)
        {
            orientation = TurnToFace(playerPosition, orientation, maxRotation);
            currentSpeed = maxSpeed;
        }
        else if (aiState == AIState.Wander)
        {
            Wander();
        }
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        boundingBox.X = (int)position.X;
        boundingBox.Y = (int)position.Y;

        drawingOrigin = new Vector2(texture.Width / 2, texture.Height / 2);

        spriteBatch.Draw(texture, boundingBox, null, Color.White, orientation, drawingOrigin, SpriteEffects.None, 0.0f);
    }

    public Vector2 PlayerPosition
    {
        set
        {
            playerPosition = value;
        }
        get
        {
            return playerPosition;
        }
    }

1 个答案:

答案 0 :(得分:0)

您可以使用以下方式与玩家保持距离:

float distanceFromPlayer = Vector2.Distance(position, playerPosition);

但是你实际上从未在你的班级中设置变量playerPosition。如果敌人在距离点(0,0)的追逐范围内有效,他们将会追逐你的玩家,否则他们就会四处游荡。

我建议你做两件事之一来解决这个问题。

首先,您可以更改Update方法的参数,以获取玩家位置的Vector2。

第二种方法(我个人会选择的方法)是添加一个类型为Player的新字段(类变量),然后添加到Virtual_Aliens&#39;构造函数传递给播放器类的实例。这样,只要你引用playerPosition,你就能说出player.Position(或者你的位置字段已命名)。

相关问题