我知道这个问题可能会被问到很多,为此我很抱歉。但是我在游戏中遇到了一段时间的碰撞问题,我想要一些帮助。
首先,游戏是2D平台游戏。每个实体都放在一个列表中。我有这个用于碰撞检测的代码,对我来说非常有用:
if (player.rectangle.Intersects(rect))
{
player1Collision = true;
colSolid = solid;
colRectangle = rect;
}
if (player1Collision)
{
Vector2 pos = player.position;
Vector2 pLeft = new Vector2(player.BoundingBox.Left, 0);
Vector2 pRight = new Vector2(player.BoundingBox.Right, 0);
Vector2 pTop = new Vector2(0, player.BoundingBox.Top);
Vector2 pBottom = new Vector2(0, player.BoundingBox.Bottom);
Vector2 sLeft = new Vector2(colSolid.BoundingBox.Left, 0);
Vector2 sRight = new Vector2(colSolid.BoundingBox.Right, 0);
Vector2 sTop = new Vector2(0, colSolid.BoundingBox.Top);
Vector2 sBottom = new Vector2(0, colSolid.BoundingBox.Bottom);
if (player.rectangle.Intersects(colRectangle))
{
if (player.velocity.X > 0 && Vector2.Distance(pRight, sLeft) < player.texture.Width / 2)//left
{
player.velocity.X = 0f;
pos.X = colSolid.BoundingBox.Left - player.BoundingBox.Width;
}
else if (player.velocity.X < 0 && Vector2.Distance(pLeft, sRight) < player.texture.Width / 2)//right
{
player.velocity.X = 0f;
pos.X = colSolid.BoundingBox.Right;
}
if (player.velocity.Y > 0 && Vector2.Distance(pBottom, sTop) < player.texture.Height/ 2) //top
{
player.velocity.Y = 0f;
player.gravityOn = false;
pos.Y = colSolid.BoundingBox.Top - player.BoundingBox.Height;
}
else if (player.velocity.Y < 0 && Vector2.Distance(pTop, sBottom) < player.texture.Height / 2)//bottom
{
player.velocity.Y = 0f;
pos.Y = colSolid.BoundingBox.Bottom;
}
player.position = pos;
}
else
{
player.gravitySpeed = 0.15f;
player.gravityOn = true;
}
}
然而问题是,如果玩家没有与矩形相交,我将重力设置为打开,因此当他与实体碰撞时,他会连续跌落,然后被放在上面,不会与它发生碰撞。我需要知道的是:我怎么能避免这种情况?有没有其他任何方法可以让重力开启,而玩家不会连续地落到实体上,只会被重新放回到固体顶部再次落下?
感谢任何帮助。
答案 0 :(得分:0)
我解决这个问题的方式可能不是最优的(事实上我确定它可能不是)但是到目前为止我在所有的2D平台项目中都有效。
我首先为精灵类定义第二个矩形。此矩形将具有与主边界框相同的宽度和X坐标,但它将稍高(在我的情况下为2或3)。您还需要偏移它,以便两个矩形的底边都是内联的,以说明:
Rectangle boundingRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
Rectangle gravityRect = new Rectangle((int)boundingRect.X, (int)boundingRect.Y - 3, texture.Width, texture.Height + 3);
精灵类还需要一个bool来跟踪玩家是否应该摔倒。还有一个用于跟踪它是否是实心的(您在初始化期间明显指定了它)。
public bool isGrounded = false;
bool isSolid;
在我的Game1课程的顶部,我宣布了2个整数:
int gravityTotalI = 0;
int gravityCounterI = 0;
初始化我的精灵时,我通常会将它们全部添加到List中。所以我可以这样做:
foreach (Sprite s in spriteList)
{
if (s.isSolid)
{
gravityTotalI++;
}
}
现在,我在Game1更新方法中使用了这一点逻辑:
foreach (Sprite s in spriteList)
{
if (!s.Equals(player)
{
if (player.boundingRect.Intersects(s.boundingRect) || player.boundingRect.Intersects(s.gravityRect))
{
player.isGrounded = true;
gravityCounterI = 0;
}
else
{
gravCounterI++;
if (gravCounterI >= gravTotalI)
{
player.isGrounded = false;
gravCounterI = 0;
}
}
if (player.boundingRect.Intersects(s.boundingRect))
{
player.position.Y -= 2f; //set the resistance of the platform here
}
}
} //end of foreach loop.
if (!player.isGrounded)
{
player.position.Y += 2f; //set the force of gravity here.
}
构建一个合适的定向碰撞引擎是另一回事,但这种技术将处理基础知识(并摆脱那种地狱般的反弹)。
希望这不是太冗长/不会错过任何重要的事情,我真的希望它有所帮助 - 我很长时间都遇到与你完全相同的问题,我知道它是多么令人沮丧!
我期待看到其他人处理此问题的技巧!