0

我是 XNA 的初学者,我正在尝试制作乒乓球游戏。
我已经能够制作乒乓球游戏,但所有代码都在一个类中。所以我想尝试添加一点 OOP,我已经为球和一个垫子做了一个类。

球运动完美,但我似乎无法让球从垫子上反弹。

这些是我使用的代码:
移动垫
Game1.cs

#region left
    if (_KBS.IsKeyDown(Keys.W) || _KBS.IsKeyDown(Keys.Z))
        Left.MoveUp();
    else if (_KBS.IsKeyDown(Keys.S))
        Left.MoveDown();
#endregion

#region right
    if (_KBS.IsKeyDown(Keys.Up))
        Right.MoveUp();
    else if (_KBS.IsKeyDown(Keys.Down))
        Right.MoveDown();
#endregion

pad.cs

public void MoveUp() {
    if (!paused)
        RecPad.Offset(0, -speed);

    CheckBorders();
}

public void MoveDown() {
    if (!paused)
        RecPad.Offset(0, speed);

    CheckBorders();
}

private void CheckBorders() {
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

检查球是否反弹
ball.cs

public void CheckBounce() {
    if ((myBounds.Intersects(left) && movement.X < 0) || (myBounds.Intersects(right) && movement.X > 0))
            movement.X *= -1;
}

public void Draw(SpriteBatch sBatch, Texture2D texture, Color color, Rectangle left, Rectangle right) {
    this.left = left;
    this.right = right;

    Move();

    sBatch.Begin();
    sBatch.Draw(texture, myBounds, color);
    sBatch.End();
}

pad.cs

public Rectangle RecPad {
    get { return recPad; }
    private set { recPad = value; }
}

游戏1.cs

Ball.Draw(spriteBatch, ball, Color.White, Left.RecPad, Right.RecPad);

我似乎让垫子恢复工作
问题似乎通过使用 originel recPad 而不是构造函数 RecPad 来解决
现在我只需要让我的边界工作,因为 MathHelper.Clamp 似乎不起作用
查看我的代码更多信息

这段代码现在解决了我的边界问题

private void CheckBorders() {
        if (recPad.Top < borders.Top)
            recPad.Location = new Point(recPad.X, borders.Top);
        if (recPad.Bottom > borders.Bottom)
            recPad.Location = new Point(recPad.X, borders.Bottom - recPad.Height);
    }
4

1 回答 1

2

这立即让我印象深刻(来自 CheckBounce):

    movement.X *= 1;

可能是复制错误,或者您忘记输入“-”。

另外,考虑使用 Rectangle.Contains/Intersects 方法来简化一些碰撞代码,并使用 MathHelper.Clamp 来保持你的桨在界限内。这更多只是为了将来参考,因为您的方法有效,但是利用 XNA 中有用的工具非常好。

编辑:关于那些“有用的工具”:

Rectangle 类具有 Intersect 和 Contains 方法,它们可以分别告诉您该矩形是否与另一个矩形相交或包含某个点。您说您的球只是左上角位置和纹理,但我在您的碰撞检查中看到您还检查了球的半径。我认为您可以更轻松地为您的球定义一个 Rectangle 边界区域并使用 Intersects 方法检查碰撞。这将您的碰撞代码简化为:

public void CheckBounce()
{
    if (myBounds.Intersects(LeftPaddle.Bounds) || myBounds.Intersects(RightPaddle.Bounds))
        movement.X *= -1;
}

相当简单,但并不完全安全——如果球设法移动到桨中足够远的距离,以至于一帧运动不会将它从桨的边界中解放出来,你就会被卡住,永远反转 X 速度,产生“卡住”球的效果。所以我们可以添加更多的检查代码来避免这种情况:

public void CheckBounce()
{
    if ((myBounds.Intersects(LeftPaddle.Bounds) && movement.X < 0) ||
     (myBounds.Intersects(RightPaddle.Bounds) && movement.X > 0))
        movement.X *= -1;
}

如果内联条件过于密集,我深表歉意。这意味着,如果球向左移动并击中右桨,则反转 X。同样,如果球向右移动并击中左桨,则反转 X。这消除了“粘连”。

现在,对于 MathHelper.Clamp,在您的情况下,我会使用它来限制桨的移动。MathHelper.Clamp 只是将一个值限制在上限和下限之间。这相当于使用 Math.Min,然后是 Math.Max。

private void CheckBorders()
{
    //clamps a       value  to a   min  and a           max
    MathHelper.Clamp(recPad.Y, borders.Top, borders.Bottom - recPad.Height);
}

这会将矩形的 Y 位置夹在边框顶部和边框底部减去矩形高度之间。最后一点通过考虑高度来防止矩形的底部剪裁边框的底部。

于 2012-02-25T19:57:13.853 回答