防止小型快速物体的隧道效应

我正在和朋友做一个基本的射击游戏,我遇到了一个问题。 我有点知道解决scheme,但我不能实施它。 这是我用XNA / MonoGame制作的第一款游戏,我也不太喜欢c#。 所以我的问题是子弹和敌人之间的碰撞检测。 有时候子弹穿过敌人,有时候会打到。 问题似乎在我的碰撞检测代码,因为它只检测我的数组列表中的一个项目。 这个( 扫描testing )可能是某人建议的解决scheme,但对我来说看起来太复杂了。 这可能是如此简单的修复,但就像我说我只是不知道如何做到这一点。 我会发布我的代码,并希望有人可以帮助。 谢谢!

这是我的主要类别,它应该消除死亡的敌人:

foreach (enemy enem in enemies) { enem.Update(graphics.GraphicsDevice); } LoadEnemies(); foreach (bullet bull in bullets) { bull.Update(); } //WSAD movement if (Keyboard.GetState().IsKeyDown(Keys.D)) { charRect.X += 6; } if (Keyboard.GetState().IsKeyDown(Keys.A)) { charRect.X -= 6; } if (Keyboard.GetState().IsKeyDown(Keys.W)) { charRect.Y -= 6; } if (Keyboard.GetState().IsKeyDown(Keys.S)) { charRect.Y += 6; } if (Keyboard.GetState().IsKeyDown(Keys.Space)) { LoadBullets(); } //Screen collision detection if (charRect.X <= -41) { charRect.X = -41; } if (charRect.Y <= 0) { charRect.Y = 0; } if (charRect.Y >= 400) { charRect.Y = 400; } if (charRect.X >= 632) { charRect.X = 632; } base.Update(gameTime); break; } case State.Menu: { playButton = new button(Content.Load<Texture2D>("playButton"), new Vector2(100, 100)); playButton.Update(); break; } case State.GameOver: { break; } } } public void LoadEnemies() { if (enemySpawnInterval >= 1) { enemySpawnInterval = 0; if (enemies.Count < 4) { int randY = r.Next(1, 600); enemies.Add(new enemy(Content.Load<Texture2D>("enemyChar"), new Vector2(800, randY))); } } for (int i = 0; i < enemies.Count; i++) { if (!enemies[i].isOnScreen) { enemies.RemoveAt(i); i--; } if (enemies[i].enemyIsHit) { enemies.RemoveAt(i); enemyKilled.Play(); i--; } } } 

这是我生成子弹和敌人的地方:

  Texture2D enemyChar; Vector2 position; public static Rectangle enemyBox; public Boolean enemyIsHit = false; public Boolean isOnScreen = true; public enemy(Texture2D newEnemyChar, Vector2 newPos) { enemyChar = newEnemyChar; position = newPos; } public void Update(GraphicsDevice graphics) { enemyBox = new Rectangle((int)position.X, (int)position.Y, enemyChar.Width, enemyChar.Height); if (enemyBox.Intersects(bullet.bulletBox)) { enemyIsHit = true; } if (position.Y <= 0 || position.Y >= graphics.Viewport.Height - enemyChar.Height) { position.Y = 100; } if (position.X < -80) { isOnScreen = false; } position.X -= 5; } 

你只需要一个双循环,就像(伪代码):

 for each enemy{ for each bullet{ if bullet intersect enemy{ //handle hit } } } 

编辑:伪码在碰撞检测期间逐渐移动子弹,代替在其他地方移动子弹:

 for each bullet{ loop 10 times{ move bullet 1/10 of original speed for each enemy{ if bullet intersect enemy{ //handle hit } } } } 

把对象看作单点而不是多边形也许是可能的。 通过这样做,您可以在对象的最后位置和当前位置之间画一条线,然后进行一条线交叉检查,看看它们是否已经通过对方。

例如。

你的敌人在(0,0)和1步时间移动到(10,10)。 你的子弹在(10,0)和移动到(0,10)在一个时间步骤。

从(0,0)到(10,10)为敌人创建一条线,从(10,0)到(0,10)

如果你在一张方格纸上做这个,很容易看到它们相交。 但是,我们如何让我们的程序来做到这一点。 我已经在Third Party Ninjas中find了一个非常好的教程和代码示例。

查看post: http : //thirdpartyninjas.com/blog/2008/10/07/line-segment-intersection/

特别是Game1.cs文件中的processIntersection()方法。

为什么不使用光线投射? 如果你的子弹在更新过程中移动得太快而无法正常检测到,你可以检查他们的最后一个位置和当前位置之间是否有东西。 虽然这个例子可能会有点消化,如果你不是很熟悉C#它包括你可以走过的源代码。

http://www.codeproject.com/Articles/15604/Ray-casting-in-a-2D-tile-based-environment