3

早上到地球各个表面上的人们。

问题:如何从箭头键获得方向角度。

序言:在基本的自上而下游戏中移动的标准方法是在更新方法中添加 x 和/或 y,具体取决于方向。

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

这对于 4 向运动来说是优雅的(我相信),因为无论按下什么组合键,运动的方向都是一致的。例如,按 up-down-left 将向左移动,因为 up 和 down 抵消了。但是在对角线移动时,步数会太大。如果速度为 20,则向左移动每秒将向左移动 20,向上每秒将向上移动 20。但是向左上方移动每秒会移动 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

使用二维向量。像这样的东西:

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 回答