XNA - Pong Clone - 击中墙壁时反射球?

Jun*_*208 4 c# math xna collision-detection

创建 2D Pong Clone 时,我试图让球从 UI 的顶部和底部“墙”反弹。这是我的 Game.cs

public void CheckBallPosition()
{
    if (ball.Position.Y == 0 || ball.Position.Y >= graphics.PreferredBackBufferHeight)
        ball.Move(true);
    else
        ball.Move(false);

    if (ball.Position.X < 0 || ball.Position.X >= graphics.PreferredBackBufferWidth)
        ball.Reset();
}
Run Code Online (Sandbox Code Playgroud)

目前我在 Ball.cs 中使用它

    public void Move(bool IsCollidingWithWall)
    {
        if (IsCollidingWithWall)
        {
            Vector2 normal = new Vector2(0, 1);
            Direction = Vector2.Reflect(Direction,normal);
            this.Position += Direction;
            Console.WriteLine("WALL COLLISION");
        }
        else
            this.Position += Direction;
    }
Run Code Online (Sandbox Code Playgroud)

它有效,但我使用的是手动输入的法线,我想知道如何计算屏幕顶部和底部的法线?

Blu*_*eft 5

嗯,这就是我将如何处理它

public void CheckBallPositionAndMove()
{
    if (ball.Position.Y <= 0 || ball.Position.Y >= graphics.PreferredBackBufferHeight)
        ball.HandleWallCollision();

    ball.Move();

    if (ball.Position.X < 0 || ball.Position.X >= graphics.PreferredBackBufferWidth)
        ball.Reset();
}

//In Ball.cs:
private void HandleWallCollision(Vector2 normal)
{
    Direction.Y *= -1; //Reflection about either normal is the same as multiplying y-vector by -1
}

private void Move()
{
    this.Position += Direction;
}
Run Code Online (Sandbox Code Playgroud)

但是请注意,使用这种“离散”碰撞检测,您要等到球移过屏幕顶部/底部后才能检测碰撞;“在”帧之间发生的碰撞可能会明显关闭,尤其是在球快速移动的情况下。尤其是一个问题,如果你正在使用此碰撞检测方法来检测碰撞桨,因为如果球移动速度不够快,这是可能的球通过桨向右移动!

这个问题的解决方案是使用所谓的连续碰撞检测。CCD 通常比离散碰撞检测复杂得多;幸运的是,pong 很简单,所以做 CCD 只会稍微复杂一些。但是,您仍然需要扎实掌握高中代​​数才能解方程。

如果您仍然感兴趣,本讲座中有关于 CCD 的很好解释,而这篇 GameDev 文章更深入一些。在 SO 上也有很多 与此相关的问题