计算包裹平面上两点之间的角度(线)

时间:2010-10-05 23:20:05

标签: math 2d trigonometry

好的,所以我有一个512x512的游戏区域,-32变为512 xy

现在我需要计算两个实体之间的角度,我有以下代码作为一种解决方法,它在大多数当时工作,但有时仍然会失败:

Shooter.getAngle = function(a, b) {
    var ax = a.x;
    var bx = b.x;
    if (a.x < this.width / 4 && b.x > this.width - this.width / 4) {
        ax += this.width;

    } else if (a.x > this.width - this.width / 4 && b.x < this.width / 4) {
        bx += this.width;
    }

    var ay = a.y;
    var by = b.y;
    if (a.y < this.height / 4 && b.x > this.height - this.height / 4) {
        ay += this.height;

    } else if (a.y > this.height - this.height / 4 && b.y < this.height / 4) {
        by += this.height;
    }
    return this.wrapAngle(Math.atan2(ax - bx, ay - by) + Math.PI);
};

我无法弄清楚如何将a投射到b上,以便正确地计算包裹。

如果有人能提供帮助,那就太棒了,因为从他们的目标中飞出远离的导弹并不是那么有趣。

为了澄清,如果玩家向右移动,导弹应该跟随他越过场边到左侧,正如另一个玩家所做的那样。

编辑:

这是一个测试版本,示例显示它正确包装,但在某些情况下它不需要包装它:

function getAngle(a, b) {
    var tx = a.x - b.x;
    var ty = a.y - b.y;

    // actual area goes from -16 to 512 due to the border space that's out of screen
    tx = ((tx + 16) % (480 + 32)) - 16;
    ty = ((ty + 16) % (480 + 32)) - 16;
    var r = Math.atan2(ty, tx) * (180 / Math.PI);

    // example
    // |> b                    a >|
    // a.x = 460
    // b.x = 60

    // missile should go over the right border
    // tx = 400 
    // r = 0
    // missile goes right, OK

    // example2
    // |< a                    b <|
    // a.x = 60
    // b.x = 460

    // missile should go over the left border
    // tx = -400 
    // r = 180
    // missile goes left, OK


    // example3
    // |     a  >>>>  b                  |
    // a.x = 60
    // b.x = 280

    // missile should go right
    // tx = -220
    // r = 180
    // missile goes left, WRONG

    // example4
    // |     b  <<<<  a                  |
    // a.x = 280
    // b.x = 60

    // missile should go left
    // tx = 220
    // r = 0
    // missile goes right, WRONG

    console.log(ty, tx);
    console.log(r);
}

function Point(x, y) {
    this.x = x;
    this.y = y;
}

getAngle(new Point(460, 240), new Point(60, 240));
getAngle(new Point(60, 240), new Point(460, 240));
getAngle(new Point(60, 240), new Point(280, 240));
getAngle(new Point(280, 240), new Point(60, 240));

似乎唯一能让它工作的方法是检查a.x < width * 0.25b.x > width * 0.75等情况,但这样的错误,至少在我上面发布的版本中:/

2 个答案:

答案 0 :(得分:5)

我会使用这种方法:使用目标作为坐标系的中心(并正确包裹导弹的坐标),然后计算角度。所以,伪代码应该是这样的(EDIT2:更正的代码,类似的问题也导致了测试中的问题):

// missile.x/y = missile's coordinates
// target.x/y = target's coordinates
temp.x = missile.x - target.x;
temp.y = missile.y - target.y;

// The wrapping code - feel free to adjust,
// from the comments it seems you handle this
// a bit differently
while (temp.x < -240)
  temp.x += 480
while (temp.y < -240)
  temp.y += 480
while (temp.x > 240)
  temp.x -= 480
while (temp.y > 240)
  temp.y -= 480

// Now you can calculate the angle your missile must go,
// it has to fly across the line from temp.x/y to (0,0)
编辑:我看过视频了,我觉得代码中有一些错误,但我不知道在哪里。使用数学函数和角度可能有点棘手,因为通常数学坐标的Y轴向上,屏幕坐标的Y轴向下。

现在最好的方法可能是开始一些单位测试,如下所示:

// Create a function that returns the angle a missile must
// fly and cares about all the dirty details with wrapping etc.
MissileAngle(missile.x, missile.y, target.x, target.y)
// Now create some tests for it, f.e.:
MissileAngle(missile top left corner, target bottom right corner)
  Expected Result: Northwest
MissileAngle(missile bottom right corner, target top left corner)
  Expected Result: Southeast

注意我没有在这里使用坐标,因为它在很大程度上取决于您正在使用的坐标系统,这实际上可能有助于您更好地了解问题(当然,希望能帮助您解决问题,至少它是一种快速的方法来检查它是否正常工作而不必玩实际的游戏,这是更耗时的。)

答案 1 :(得分:0)

只是提出明显的建议:不应该是Math.atan2(ay-by,ax-bx)吗?如果这只是你帖子中的拼写错误而道歉,但我当然可以看到导致你的导弹出现奇怪的行为。

编辑补充:没关系,我刚看到你的评论。

相关问题