我正在研究XNA中的Collision。有些原因,尽管经过多次尝试,它仍无效。如果我触摸它,它会工作。但有时随机会停止运行,就像发生碰撞一样。它的工作方式是有50个20px乘20px的正方形。如果你的方块以任何方式触及另一个方格,那么游戏就结束了。
checkcollision()
{
for (int i = 0; i < 50; i++)
{
if ((loc.X + me.Width > enemyloc[i].X) && (loc.Y + me.Height > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y) && (loc.X < enemyloc[i].X)) { return true; }
if ((loc.X > enemyloc[i].X) && (enemyloc[i].X + enemy[i].Width > loc.X) && (loc.Y + me.Height > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y)) { return true; }
if ((loc.X > enemyloc[i].X) && (loc.X < enemyloc[i].X + enemy[i].Width) && (loc.Y > enemyloc[i].Y) && (loc.Y < enemyloc[i].Y + enemy[i].Height)) { return true; }
if ((loc.X < enemyloc[i].X) && (loc.X + me.Width > enemyloc[i].X) && (loc.Y < enemyloc[i].Y) && (loc.Y < enemyloc[i].Y + enemy[i].Height)) { return true; }
}
return false;
}
答案 0 :(得分:2)
我同意这段代码看起来有点太复杂了。我建议将敌人和玩家碰撞盒存储为Rectangle struct的实例。 Rectangle结构提供了一个名为Contains的方法,定义为:
public bool Contains(int x, int y);
如果在x和y中定义的点存在于矩形中,则此方法将返回true。因此,使用此结构代码将变得更加简单:
public bool checkcollision(Rectangle player)
{
for (int i = 0; i < enemy.Length; i++)
{
if (enemy[i].Contains(player.Left, player.Top)
|| enemy[i].Contains(player.Right, player.Top)
|| enemy[i].Contains(player.Left, player.Bottom)
|| enemy[i].Contains(player.Right, player.Bottom))
{
return true;
}
}
return false;
}
答案 1 :(得分:0)
正如我在评论中所说, 太难读了。虽然我不会声称它是 问题(使用Mitch Wheat建议的调试器),但它确实可以解决!
首先,让我们概述单轴X的碰撞检测。我们不是先查看碰撞,而是查找 no collision 。当“(玩家离开敌人)或(玩家左边的敌人)”时,不会
设p = Player,e = Enemy,然后当(p.X + p.W&lt; e.X)||时,无碰撞 [仅] (e.X + e.W&lt; p.X)。这意味着在相反/否定的情况下发生碰撞!
因此我们可以编写碰撞方法:
bool Collides (IEntityBox p, IEntityBox e) {
bool noCollisionX = (p.X + p.W < e.X) || (e.X + e.W < p.X);
bool collisionX = !noCollisionX;
bool noCollisionY = (p.Y + p.H < e.Y) || (e.Y + e.H < p.Y);
bool collisionY = !noCollisionY;
// not that the collision on BOTH axises must be fulfilled
return collisionX && collisionY;
}
备注(作为练习留下):
IEntityBox具有X / Y和W / H属性,并且(0,0)被假定为屏幕的左上角。使用正确的类型/ propeties实现。如果玩家和其他实体之间的定位是统一的,那就更简单了。
可以重写表达式(并且可以应用De Morgan)来清理它。简单的折叠将消除所有变量,并使其“易于”阅读。
如果noCollisionX(暗示!collisionX)为真,我们不需要计算noCollisionY。如果折叠,可以使用if / else或短路评估。
同样清理用法:
bool PlayerCollidesWithAnyEnemy () {
foreach (var e in enemies) { // avoid hard-coding numbers
if (Collides(player, e)) {
return true;
}
}
return false;
}
// ..
var playerOopsed = PlayerCollidesWithAnyEnemy();
或者,使用LINQ:
var playerOopsed = enemies.Any(e => Collides(player, e));