简体   繁体   English

所有方向的8向一致移动速度,如何从方向键获得移动角度?

[英]8-direction consistent movement speed in all directions, how to get angle of movement from direction keys?

Top of the morning to ye people on various surfaces of earth. 对于地球各种表面上的人们来说,清晨。

The problem: How to get the angle of direction from the arrow keys. 问题:如何从箭头键获取方向角。

Preamble: The standard way to move in a basic top-down game is to add to x and/or y from within an update method, depending on the direction. 序言:在基本的自上而下游戏中移动的标准方法是在更新方法中添加到x和/或y,具体取决于方向。

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

This is elegant for 4-direction movement (I believe) because no matter what key combinations are pressed, the direction of movement will be consistent. 这对于4向运动来说是优雅的(我相信),因为无论按下哪种按键组合,运动方向都是一致的。 Eg pressing up-down-left will move left, as up and down cancel out. 例如,向上 - 向下按下将向左移动,因为上下取消。 But when moving diagonally, the steps will be too large. 但是当沿对角线移动时,步数会太大。 If speed is 20, moving left will move left by 20 per second, up will move up by 20 per second. 如果速度为20,向左移动将向左移动每秒20,向上移动将每秒向上移动20。 But moving up-left will move by a little over 28.24 per second. 但向左上移动将略微超过每秒28.24。

The solution here is to use cos and sin to get the new x and y, which is easy once you know the angle: 这里的解决方案是使用cos和sin来获取新的x和y,一旦你知道角度就很容易:

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

But, for me at least, this raises a new problem: what's the angle? 但是,至少对我来说,这提出了一个新问题:角度是什么? In my KeyListener I'm currently setting/clearing booleans for each arrow key. 在我的KeyListener中,我正在为每个箭头键设置/清除布尔值。 I can use a bulky set of if statements: 我可以使用一组庞大的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

For the life of me, I cannot find a sexy way to get the movement angle from what direction keys are pressed down. 对于我的生活,我找不到一种性感的方式来获得从按下键的方向移动角度。 It strikes me like this should be a common problem, game design 101, but intense googling hasn't led me to anything (made harder by the fact that it's difficult to put the problem into words). 这让我觉得这应该是一个常见的问题,游戏设计101,但是激烈的谷歌搜索并没有让我做任何事情(由于难以将问题转化为文字而变得更加困难)。 In all instances of examples, either they just retained the diagonal-is-faster functionality (as with my first snippet), or know the angle ahead of time (ie. move towards the mouse), or are 2D side scrollers. 在所有示例实例中,要么他们只保留对角线更快的功能(与我的第一个片段一样),要么提前知道角度(即向鼠标移动),或者是2D侧滚动器。

Surely there's a sexy mathy way (or something) to work it out in a few lines? 当然有一种性感的肮脏方式(或者某种东西)可以用几行来解决它? Or am I approaching this completely wrong? 或者我接近这个完全错误?

Edit: Post-answer code (as posted by korona below): 编辑:回答后代码(由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;
}

Use a 2-dimensional vector. 使用二维向量。 Something like this: 像这样的东西:

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;

I assume there's a suitable 2D vector class available for you. 我假设有一个合适的2D矢量类可供您使用。 If not, normalizing a vector is as easy as dividing all of its components by its length, as such: 如果不是,将矢量归一化就像将其所有分量除以其长度一样容易,如下:

length = sqrt(this.x * this.x + this.y * this.y);
this.x /= length;
this.y /= length;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM