尽可能整齐地处理碰撞期间的速度矢量
我正在尝试创建一种好方法来处理两个对象之间所有可能的碰撞。通常,其中一个会移动并撞击另一个,然后应该“弹开”。
到目前为止我所做的(我正在创建一个典型的游戏,你有一个棋盘并在砖块上弹球)是检查矩形是否相交,如果相交,则反转 Y 速度。
这是一个非常丑陋且临时的解决方案,无法长期工作,而且由于这种处理在游戏中非常常见,我真的很想为未来的项目找到一种很好的方法。任何链接或有用的信息表示赞赏。
下面是我的碰撞处理函数现在的样子。
protected void collision()
{
#region Boundaries
if (bal.position.X + bal.velocity.X >= viewportRect.Width ||
bal.position.X + bal.velocity.X <= 0)
{
bal.velocity.X *= -1;
}
if (bal.position.Y + bal.velocity.Y <= 0)
{
bal.velocity.Y *= -1;
}
#endregion
bal.rect = new Rectangle((int)bal.position.X+(int)bal.velocity.X-bal.sprite.Width/2, (int)bal.position.Y-bal.sprite.Height/2+(int)bal.velocity.Y, bal.sprite.Width, bal.sprite.Height);
player.rect = new Rectangle((int)player.position.X-player.sprite.Width/2, (int)player.position.Y-player.sprite.Height/2, player.sprite.Width, player.sprite.Height);
if (bal.rect.Intersects(player.rect))
{
bal.position.Y = player.position.Y - player.sprite.Height / 2 - bal.sprite.Height / 2;
if (player.position.X != player.prevPos.X)
{
bal.velocity.X -= (player.prevPos.X - player.position.X) / 2;
}
bal.velocity.Y *= -1;
}
foreach (Brick b in brickArray.list)
{
b.rect.X = Convert.ToInt32(b.position.X-b.sprite.Width/2);
b.rect.Y = Convert.ToInt32(b.position.Y-b.sprite.Height/2);
if (bal.rect.Intersects(b.rect))
{
b.recieveHit();
bal.velocity.Y *= -1;
}
}
brickArray.removeDead();
}
I'm trying to create a good way to handle all possible collisions between two objects. Typically one will be moving and hitting the other, and should then "bounce" away.
What I've done so far (I'm creating a typical game where you have a board and bounce a ball at bricks) is to check if the rectangles intersect and if they do, invert the Y-velocity.
This is a really ugly and temporary solution that won't work in the long haul and since this is kind of processing is very common in games I'd really like to find a great way of doing this for future projects aswell. Any links or helpful info is appreciated.
Below is what my collision-handling function looks like right now.
protected void collision()
{
#region Boundaries
if (bal.position.X + bal.velocity.X >= viewportRect.Width ||
bal.position.X + bal.velocity.X <= 0)
{
bal.velocity.X *= -1;
}
if (bal.position.Y + bal.velocity.Y <= 0)
{
bal.velocity.Y *= -1;
}
#endregion
bal.rect = new Rectangle((int)bal.position.X+(int)bal.velocity.X-bal.sprite.Width/2, (int)bal.position.Y-bal.sprite.Height/2+(int)bal.velocity.Y, bal.sprite.Width, bal.sprite.Height);
player.rect = new Rectangle((int)player.position.X-player.sprite.Width/2, (int)player.position.Y-player.sprite.Height/2, player.sprite.Width, player.sprite.Height);
if (bal.rect.Intersects(player.rect))
{
bal.position.Y = player.position.Y - player.sprite.Height / 2 - bal.sprite.Height / 2;
if (player.position.X != player.prevPos.X)
{
bal.velocity.X -= (player.prevPos.X - player.position.X) / 2;
}
bal.velocity.Y *= -1;
}
foreach (Brick b in brickArray.list)
{
b.rect.X = Convert.ToInt32(b.position.X-b.sprite.Width/2);
b.rect.Y = Convert.ToInt32(b.position.Y-b.sprite.Height/2);
if (bal.rect.Intersects(b.rect))
{
b.recieveHit();
bal.velocity.Y *= -1;
}
}
brickArray.removeDead();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以下是一些可能有帮助的建议。
首先,您的所有对象,例如
Player
、Bal
(不确定那是什么)和Brick
都有一些相似的界面 - 它们都有sprite
(定义对象的大小)、rect
(对象的边界框)、position
(当前位置)、velocity
(当前速度)。这表明您可以创建一个公共基类来封装此功能。另请注意,您始终会根据当前
位置
和sprite
重新计算rect
。这表明rect
实际上应该是一个隐藏重新计算的属性(它总是相同的!)因此,您可以从定义一个像这样的公共基类开始(我将遵循 .NET 标准编码样式并使用属性和
CamelCase
名称):如果您现在使用此类型作为所有游戏对象的基类,您应该能够编写以下内容:
将两者之间的函数 - 一个检查
bal
和player
,另一个检查砖块。Here are a couple of suggestions that may help.
First of all, all your objects such as
Player
,Bal
(not sure what that is) andBrick
have somewhat similar interface - they all havesprite
(defining the size of the object),rect
(bounding box of the object),position
(current position),velocity
(current velocity). This suggests that you could create a common base class to encapsulate this functionality.Also note that you're always recalculating
rect
based on the currentposition
andsprite
. This suggests thatrect
should actually be a property that hides the recalculation (which is always the same!)So, you can start by defining a common base class like this (I'll follow .NET standard coding style and use properties and
CamelCase
names):If you now use this type as a base class for all your game objects, you should be able to write this:
It also sounds like a good idea to split the function between two - one that checks
bal
andplayer
and the other that checks the bricks.