简体   繁体   English

在XNA / C#中移动矩形的最佳方法

[英]Best way to move a rectangle in XNA/C#

I'm a starter in XNA and I'm trying to make a pong-game. 我是XNA的入门者,正在尝试制作乒乓球游戏。
I've been able to make a pong game, but all the code was in one class. 我已经能够做一个乒乓球游戏,但是所有的代码都在一个类中。 So I wanted to try to add a little bit of OOP and I've made a class for the ball and one for the pad. 因此,我想尝试添加一些OOP,并为球类和护垫类做了一类。

The ball moves perfectly, but I don't seem to able to make the ball bounce from the pads. 球运动得很好,但我似乎无法使球从护垫弹起。

These are the codes I use: 这些是我使用的代码:
To move the pads 移动打击垫
Game1.cs 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 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);
}

To check if the ball bounces 检查球是否弹跳
ball.cs 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 pad.cs

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

Game1.cs Game1.cs

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

I seemed to get the pads back to work 我似乎要恢复工作了
The problem seems to be solved by using the originel recPad instead of the constructor RecPad 该问题似乎可以通过使用originel recPad而不是构造函数RecPad来解决。
Now I only need to get my boundries working, because the MathHelper.Clamp doesn't seem to work 现在我只需要使边界起作用,因为MathHelper.Clamp似乎不起作用
See my code for more info 查看我的代码以获取更多信息

This code now fixed my border-problem 这段代码现在解决了我的边界问题

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);
    }

This immediately stands out to me (from CheckBounce): 这立即对我突出(从CheckBounce):

    movement.X *= 1;

Could be a copying error, or you forgot to put a '-'. 可能是复制错误,或者您忘记输入'-'。

Also, consider using the Rectangle.Contains/Intersects method(s) to streamline some collision code, and MathHelper.Clamp to keep your paddles in bounds. 另外,请考虑使用Rectangle.Contains / Intersects方法简化一些碰撞代码,并使用MathHelper.Clamp来使桨划定界限。 This is more just for future reference, since your methods work, but it's nice to take advantage of the helpful tools in XNA. 由于您的方法可以使用,因此这仅供以后参考,但是最好利用XNA中有用的工具。

Edit: Concerning those 'helpful tools': 编辑:关于那些“有用的工具”:

The Rectangle class has the methods Intersect and Contains, which can tell you if that rectangle is intersecting another rectangle or containing a certain point, respectively. Rectangle类具有Intersect和Contains方法,可以分别告诉您该矩形是与另一个矩形相交还是包含某个点。 You say your ball is just a top left position and a texture, but I see in your collision checking you also check for the radius of the ball. 您说您的球只是左上角的位置和纹理,但我发现在碰撞检查中您还检查了球的半径。 I think you'd have an easier time defining a Rectangle bounding area for your ball and using the Intersects method to check for collision. 我认为您可以更轻松地为球定义Rectangle边界区域,并使用Intersects方法检查碰撞。 That simplifies your collision code to: 这将您的冲突代码简化为:

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

Fairly simple, but not entirely safe-- if the ball manages to move far enough into a paddle that one frame of movement wouldn't free it from that paddle's bounds, you'd be stuck perpetually inverting the X velocity, producing a 'stuck ball' effect. 相当简单,但也不是完全安全的-如果球设法移动到桨板中足够远的位置,以致一帧运动无法将其从桨板的边界中释放出来,那么您将永远被困在X速度反转的方向,从而产生“卡住”球效应。 So we can add just a bit more checking code to avoid that: 因此,我们可以再添加一些检查代码来避免这种情况:

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

I apologize if the inline conditionals are a little too dense. 如果内联条件过于密集,我深表歉意。 What this means is, if the ball is moving left and hits the right paddle, invert the X. Likewise, if it's moving right and hits the left paddle, invert the X. This removes the 'sticking'. 这意味着,如果球向左移动并击中右桨,则将X反转。同样,如果球向右移动并击中左桨,则将X反转。这将消除“粘滞”。

Now, as for MathHelper.Clamp, in your situation I would use it to restrict paddle movement. 现在,对于MathHelper.Clamp,在您的情况下,我将使用它来限制桨运动。 MathHelper.Clamp simply clamps a value between an upper and lower bound. MathHelper.Clamp只是在一个上限和下限之间钳制一个值。 It's the equivalent of using Math.Min, then Math.Max. 这等效于使用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);
}

This clamps the Y position of your rectangle between the top of your borders, and the bottom of your borders minus the height of the rectangle. 这会将矩形的Y位置夹在边界的顶部之间,边界的底部减去矩形的高度。 That last bit keeps the bottom of your rectangle from clipping the bottom of the borders by taking the height into account. 最后一点通过考虑高度来防止矩形的底部修剪边界的底部。

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

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