检测对象是否将在2D空间中发生碰撞

时间:2012-03-19 16:32:51

标签: c# trigonometry angle

我一直试图为小行星游戏制作人工智能,但已经卡住了。游戏中的其他所有内容都已设置好(即小行星创建并沿着随机方向行进,碰撞检测,船只和子弹。)人工智能每150毫秒循环一次,只能告诉船向左转,向右转,向上移动并射击

以下是我目前使用的代码片段:

                // Convert points to positive
                float asteroid_x = Math.Abs(asteroid.X);
                float asteroid_y = Math.Abs(asteroid.Y);

                float ship_x = Math.Abs(ship.X);
                float ship_y = Math.Abs(ship.Y);

                // Calculate difference in X and Y using positive values
                float dx = asteroid_x - ship_x;
                float dy = asteroid_y - ship_y;

                // Get velocities of asteroid
                float vx = asteroid.VX;
                float vy = asteroid.VY;

使用这些变量(dx,dy,vx,vy)我需要计算小行星是否会撞到船上。我一直在尝试使用三角函数,但它一直认为它不会被击中。我一直试图使用的方程是:

            float equation1a = (dy / vy) - (dx / vx);
            float equation1 = ((dy / dx) - (vy / vx));

我当时一直在尝试使用IF语句来确定它是否会被击中但是我不确定如何正确地进行它。在这个IF声明之后,我想进入AI转向并射击小行星或逃避它。

感谢您的帮助。

编辑:船舶或小行星的X和Y值也可以为负值,船舶从原点(0,0)开始。

EDIT2:现在进一步了解并提出这个问题:

// Determine if asteroid will collide
int turns_ahead = 100;
bool collision = false;
int least_turns = 500;
for (int i = 0; i < turns_ahead; i++)
{
    PointF asteroid_pos_next = NextPosition(new PointF(asteroid.X, asteroid.Y), new PointF(asteroid.VX, asteroid.VY), i);

    if (asteroid.CollidesWith(asteroid_pos_next.X, asteroid_pos_next.Y, ship.R))
    {
        collision = true;
    }
}

下一个职位是用这个功能解决的:

    // -----------------------------------------------------------------
    // Function to find position of object in X turns (turns_ahead)
    // -----------------------------------------------------------------
    private static PointF NextPosition(PointF current_pos, PointF velocity, int turns_ahead)
    {
        float next_x_pos = current_pos.X + (velocity.X * turns_ahead);

        float next_y_pos = current_pos.Y + (velocity.Y * turns_ahead);

        // IFs to deal with screen wrap-around
        if (next_x_pos < -Form1.maxX)
        {
            next_x_pos = Form1.maxX;
            if (next_y_pos < 0)
                next_y_pos += Form1.maxY;
            else
                next_y_pos -= Form1.maxY;
        }
        else if (next_x_pos > Form1.maxX)
        {
            next_x_pos = -Form1.maxX;
            if (next_y_pos < 0)
                next_y_pos += Form1.maxY;
            else
                next_y_pos -= Form1.maxY;
        }

        if (next_y_pos < -Form1.maxY)
        {
            next_y_pos = Form1.maxY;
            if (next_x_pos < 0)
                next_x_pos += Form1.maxX;
            else
                next_x_pos -= Form1.maxX;
        }
        else if (next_y_pos > Form1.maxY)
        {
            next_y_pos = -Form1.maxY;
            if (next_x_pos < 0)
                next_x_pos += Form1.maxX;
            else
                next_x_pos -= Form1.maxX;
        }

        PointF next_pos = new PointF(next_x_pos, next_y_pos);

        return next_pos;
    }

collidesWith是小行星类的一个函数,用于检测子弹/船是否撞到了小行星。我不确定我的下一个位置函数是否正确,虽然小行星确实绕过X / Y值似乎卡在maxX / maxY值?

3 个答案:

答案 0 :(得分:0)

这里没有足够的上下文,需要真正看到更多代码。我正在研究的非常高级的概念是两个步骤 - 1.移动小行星对象(在不同的线程上移动用户/ AI移动船),2。检查小行星的位置与每次运动(事件处理程序)中船舶的位置(用于碰撞)。另外 - 你提到'打击它',你是否试图预测碰撞发生之前?如果是这样,你需要考虑小行星和船的先前/最近的运动来“预测”他们未来的运动。

答案 1 :(得分:0)

考虑以下事项:在任何时刻,你都有小行星和船的位置及其速度。然后,在时间t(150ms的间隔),小行星的位置将是

asteroid_x + asteroid.vx * t
asteroid_y + asteroid.vy * t

并且船的位置将是

ship_x + ship.vx * t
ship_y + ship.vy * t

所以你可以迭代t(0到100)并检查小行星和船是否在任何时间彼此之间的某个距离(例如它们的半径之和) - 这意味着碰撞。

P.S。距离由

给出
sqrt( (asteroid_x - ship_x)^2 + (astroid_y - ship_y)^2 )

我建议你阅读更多关于碰撞检测的内容

答案 2 :(得分:0)

想象一下你的物体在三个维度上的运动,其中第三个是时间;如果这些3D线在一起足够接近(小于它们的半径之和,假设物体都是圆圈),它们最终会发生碰撞。

这两条3D线可以由点(x,y,0)和方向矢量(vx,vy,1)定义;然后,您可以应用众所周知的几何体来找到两条“倾斜”3D线之间的最近距离;我不知道它,但here's an article给出了

  

D = | c·(a×b)| / | a×b |

其中小写变量是向量,c是位置之间的差异, a b 是两个方向向量。

请注意,如果对象在过去的中碰撞当前轨迹,则会产生误报;我不知道如何解决这个问题,但即使你把它留在里面也可能不会干扰你的AI。也许有一种方法可以测试“绝对分开”,或者也许该公式中分子的符号是有意义的。