1

我的敌人精灵在到达可变端点后一直在振动。怎么了?为什么会振动?此外,变量 next_position 永远不会为真。但为什么?我希望敌人精灵在到达当前端点后移动到一个新的随机端点。

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D enemy;
    Vector2 position, endposition;
    bool next_position = false;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferWidth = 1280;
        graphics.PreferredBackBufferHeight = 720;
    }

    protected override void Initialize()
    {          
        base.Initialize();
    }

    protected override void LoadContent()
    {         
        spriteBatch = new SpriteBatch(GraphicsDevice);
        enemy = Content.Load<Texture2D>("zombie");
        Random randomstart = new Random();
        position = new Vector2(randomstart.Next(100, 200), randomstart.Next(100, 200));
        endposition = new Vector2(randomstart.Next(100, 600), randomstart.Next(100, 400));
    }

    protected override void Update(GameTime gameTime)
    {
        float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;         
        Random random = new Random();
        position.X += 5 * delta;
        position.Y += 3 * delta;

        if (next_position == true)
        {
          endposition = new Vector2(random.Next(100, 600), random.Next(100, 400));
          next_position = false;
        }

        if (Vector2.Dot(endposition - position, endposition - position) > 0 || Vector2.Dot(endposition - position, endposition - position) < 0) 
        {
          Vector2 enemyDirection = Vector2.Normalize(endposition - position) * 100f;
          position += enemyDirection * delta;
        }
        else
        {
            next_position = true;
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(enemy, position, Color.White);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
4

2 回答 2

4

我对这条线有点困惑

if (Vector2.Dot(endposition - position, endposition - position) > 0 || Vector2.Dot(endposition - position, endposition - position) < 0)

应该完全正确。从代码的其余部分中,您试图用它来实现的是检查精灵的位置是否是敌人的位置。这条线实际上做的是计算相反方向的向量的点积,除非向量为零,否则它永远不会为零。所以理论上这可能真的有效,但前提是位置精确地等于敌人的位置。

但是,您在单位时间内将精灵移动了固定距离,因此它实际上并没有到达敌人,而是超过了它。发现自己然后在另一边它向后移动,它来自哪里,并再次越过它。这继续并导致您描述的振动。

现在,您想要实现的行为的方式通常是使用毕达哥拉斯定理计算两个对象(精灵和敌人)之间的距离,然后在距离低于某个阈值时接受对象的到达(容易但容易出错),或者比对象可以通过这个特定更新的距离短(在你的情况下,因为你移动了一个归一化的向量 times 100f * delta,这个距离等于100f * delta)。

我希望我的解释是有帮助的。当然,请随时要求澄清。

编辑(回复评论):

您创建的limit向量相对没有意义,因为它只是max_distance在 x 和 y 方向上偏移的位置。没有必要这样做。但是,另一个if()包含几乎您想要的代码,请查看:

// first you calculate the distance we can move this update
float max_distance = 100f * delta;

// now, we compare the actual distance to the end position to that maximum
// if the actual distance is larger, then we are not there yet
// otherwise, (if the actual distance is smaller) we will overshoot the target,
// thus we are in fact there! (=close enough to continue)
// (note: we compare the distances squared to avoid a square root,
//  which makes this check much faster, which is good practice,
//  in case we ever scale this up to more objects)
if ((position - endposition).LengthSquared() > max_distance * max_distance)
{
    /* we are not yet there, continue moving! */
}
else
{
    /* we are there! */
}

这真的很简单,不需要其他检查。让我知道这是否适合您!

于 2012-12-09T00:36:29.170 回答
0

现在好多了,但并不完美。敌方精灵不再振动,但如果到达结束位置,它总是会向右下方移动一些像素。为什么它总是向右移动一些像素?其余的工作正常。

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D enemy;
    Vector2 position, endposition;
    bool next_position = false;
    int count_nextposition;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferWidth = 1280;
        graphics.PreferredBackBufferHeight = 720;
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        enemy = Content.Load<Texture2D>("zombie");
        Random randomstart = new Random();
        position = new Vector2(randomstart.Next(100, 200), randomstart.Next(100, 200));
        endposition = new Vector2(randomstart.Next(100, 600), randomstart.Next(100, 400));
        count_nextposition = randomstart.Next(90, 121);
    }

    protected override void Update(GameTime gameTime)
    {
        float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;
        count_nextposition -= 1;
        Random random = new Random();
        position.X += 5 * delta;
        position.Y += 3 * delta;

        if (count_nextposition <= 0)
        {
        if (next_position == true)
        {
            endposition = new Vector2(random.Next(100, 600), random.Next(100, 400));
            next_position = false;
        }
        float max_distance = 100f * delta;
        if ((position - endposition).LengthSquared() > max_distance * max_distance)
        {
           Vector2 enemyDirection = Vector2.Normalize(endposition - position) * 100f;
           position += enemyDirection * delta;
        }
        else
        {

            next_position = true;
            count_nextposition = random.Next(90, 121);
        }
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(enemy, position, Color.White);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
于 2012-12-09T19:31:26.643 回答