在XNA/C#中移动矩形的最佳方式
本文关键字:最佳 方式 移动 XNA | 更新日期: 2023-09-27 18:25:43
我是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; }
}
Game1.cs
Ball.Draw(spriteBatch, ball, Color.White, Left.RecPad, Right.RecPad);
我似乎让垫子恢复了工作
这个问题似乎可以通过使用original 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);
}
这立刻让我眼前一亮(来自CheckBounce):
movement.X *= 1;
可能是复制错误,或者您忘记输入"-"。
此外,可以考虑使用Rectangle.Contains/Intersects方法来简化一些碰撞代码,并使用MathHelper.Clamp来保持划桨在边界内。这只是为了将来的参考,因为您的方法是有效的,但利用XNA中有用的工具是很好的。
编辑:关于那些"有用的工具":
Rectangle类具有方法Intersect和Contains,它们可以分别告诉您该矩形是与另一个矩形相交还是包含某个点。你说你的球只是一个左上角的位置和一个纹理,但我看到在你的碰撞检查中,你也检查了球的半径。我认为你可以更容易地为球定义矩形边界区域,并使用"相交"方法来检查碰撞。这将您的碰撞代码简化为:
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,在你的情况下,我会用它来限制划桨运动。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位置夹在边框顶部和边框底部减去矩形高度之间。最后一点通过考虑高度来防止矩形的底部剪裁边框的底部。