3

地球のさまざまな表面にいるあなたがたの人々への朝の頂上。

問題:矢印キーから方向の角度を取得する方法。

前文:基本的なトップダウンゲームで移動する標準的な方法は、方向に応じて、更新メソッド内からxおよび/またはyに追加することです。

if (moveUp)     playerY -= delta * speed;
if (moveDown)   playerY += delta * speed;
if (moveLeft)   playerX -= delta * speed;
if (moveRight)  playerX += delta * speed;

どのキーの組み合わせを押しても、移動方向が一定になるため、これは4方向の移動に適しています(私は信じています)。たとえば、上下左右を押すと、上下がキャンセルされるため、左に移動します。ただし、斜めに移動すると、ステップが大きくなりすぎます。速度が20の場合、左に移動すると1秒あたり20ずつ左に移動し、上に移動すると1秒あたり20ずつ上に移動します。ただし、左上に移動すると、1秒あたり28.24強移動します。

ここでの解決策は、cosとsinを使用して新しいxとyを取得することです。これは、角度がわかれば簡単です。

playerX += Math.cos(Math.toRadians(angle)) * delta * speed;
playerY -= Math.sin(Math.toRadians(angle)) * delta * speed; //y is inverted

しかし、少なくとも私にとっては、これは新しい問題を引き起こします:角度は何ですか?KeyListenerで、現在、各矢印キーのブール値を設定/クリアしています。かさばるifステートメントのセットを使用できます。

if (moveUp)     angle = 90;
if (moveDown)   angle = 270;
if (moveRight)  angle = 0;
if (moveLeft)   angle = 180;
if (moveUp && moveLeft)     angle = 135;
if (moveUp && moveRight)    angle = 45;
if (moveDown && moveLeft)   angle = 225;
if (moveDown && moveRight)  angle = 315;
//...etc... for all combinations

私の人生では、キーを押した方向から移動角度を取得するセクシーな方法を見つけることができません。これは一般的な問題であるゲームデザイン101であるように私は思いますが、激しいグーグルは私を何にも導きませんでした(問題を言葉で表現するのが難しいという事実によって難しくなりました)。例のすべての例で、(最初のスニペットのように)対角線が高速な機能を保持しているか、事前に角度を知っている(つまり、マウスに向かって移動する)か、2D横スクロールです。

確かに、数行でそれを解決するためのセクシーなマシーな方法(または何か)がありますか?それとも私はこれに完全に間違ってアプローチしていますか?

編集:回答後のコード(以下のkoronaによって投稿されたとおり):

double x=0, y=0;
if (moveLeft) x -= 1;
if (moveRight) x += 1;
if (moveUp) y -= 1;
if (moveDown) y += 1;

double length = Math.sqrt(x * x + y * y);
if (length != 0) {
    x /= length;
    y /= length;

    x *= delta*speed;
    y *= delta*speed;

    playerX += x;
    playerY += y;
}
4

1 に答える 1

9

2次元ベクトルを使用します。このようなもの:

movement = new Vector2D();

if (moveLeft) movement.x += 1;
if (moveRight) movement.x -= 1;
if (moveUp) movement.y -= 1;
if (moveDown) movement.y += 1;

movement.normalize();   // Caps the movement vector at a length of one, even when it's at an odd angle
movement *= desiredMovementSpeed * frameDeltaTime;  // Plug in suitable values here
// FIXME: Do some collision detection here, probably
playerX += movement.x;
playerY += movement.y;

適切な2Dベクトルクラスが利用できると思います。そうでない場合、ベクトルの正規化は、そのすべてのコンポーネントをその長さで割るのと同じくらい簡単です。

length = sqrt(this.x * this.x + this.y * this.y);
this.x /= length;
this.y /= length;
于 2012-06-17T23:05:31.113 に答える