1

敵のスプライトが変数の終了位置に到達した後もずっと振動しています。なにが問題ですか?なぜ振動しているのですか?さらに、変数 next_position が true になることはありません。しかし、なぜ?敵のスプライトが現在の終了位置に到達した後、新しいランダムな終了位置に移動するようにします。

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)

正確に行うことになっています。コードの残りの部分から、スプライトの位置が敵の位置であるかどうかを確認しています。線が実際に行うことは、反対方向のベクトルの内積を計算することであり、ベクトルがゼロでない限りゼロにはなりません。したがって、理論的にはこれは実際に機能する可能性がありますが、位置が敵の位置と正確に等しい場合に限られます。

ただし、スプライトを単位時間あたり一定の距離だけ移動させているため、実際には敵に到達せずにオーバーシュートします。自分自身を見つけると、反対側に移動し、元の場所に戻り、再びオーバーシュートします。これが続き、あなたが説明する振動をもたらします。

さて、実装したい動作は通常、ピタゴラスの定理を使用して 2 つのオブジェクト (スプライトと敵) 間の距離を計算し、距離が特定のしきい値を下回ったときにオブジェクトの到着を受け入れることです(簡単だがエラーが発生しやすい)、またはオブジェクトがこの特定の更新を移動できる距離よりも短い(あなたの場合、正規化されたベクトル時間で移動するため100f * delta、この距離は に等しい100f * delta)。

私の説明がお役に立てば幸いです。もちろん、ご不明な点はお気軽にお尋ねください。

編集(コメントへの応答):

作成しているベクトルは、x 方向と y 方向の両方でlimitオフセットされた位置であるため、比較的無意味です。max_distanceそのようなものは必要ありません。ただし、他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 に答える