2014-11-03 47 views
1

我使用XNA制作坦克游戏。我已经实现了使用列表拍摄子弹的功能。拍摄后,我想测试子弹是否已经接近屏幕的边界。如果是这样,从列表中删除特定的项目符号。C# - >索引超出范围错误|使用列表

只有当我在任何给定时间在屏幕上有多个子弹时才会出现此错误。下面是代码:


坦克类:

List<Bullet> bulletList = new List<Bullet>(); 
bool spacebarPrepared = true; //for shooting every 0.5 seconds 
short count = 0; 


//Shoot 
if (Keyboard.GetState().IsKeyDown(Keys.Space) && spacebarPrepared == true) 
    { 
     bulletList.Add(new Bullet(sprBullet, position, turretDirection, turretAngle)); 
     spacebarPrepared = false; 
    } 


if (spacebarPrepared == false) 
    { 
     spacebarCount += (float)gameTime.ElapsedGameTime.TotalSeconds; 

     if (spacebarCount > 0.5) 
     { 
      spacebarPrepared = true; 
      spacebarCount = 0; 
     } 
    } 


//Update bullets 
foreach (Bullet bullet in bulletList) 
{ 
    bullet.Update(bounds); 
} 


count = (short)bulletList.Count; 

//Remove unwanted bullets 
for (short i = 0; i < count; i++) 
{ 
    if (bulletList[i].Alive == false) 
    { 
     bulletList.Remove(bulletList[i]); 
    } 
} 

子弹类:

class Bullet 
{ 
    Texture2D spr; 
    Vector2 origin, pos, dir, turretLength; 
    float rotation, scale, turretLeng; 
    short speed; 
    bool alive = true; 


    public Bullet(Texture2D sprite, Vector2 position, Vector2 direction, float angle) 
    { 
     spr = sprite; 
     scale = 0.15f; 
     turretLeng = (110 + spr.Width) * scale; 
     speed = 5; 
     rotation = angle; 
     pos = position; 
     dir = direction; 
     origin = new Vector2(spr.Width/2, spr.Height/2); 
     FindTurretLength(); 
    } 

    public void Draw(SpriteBatch spriteBatch) 
    { 
     Matrix bulletTranslation = Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(pos.X + turretLength.X, pos.Y + turretLength.Y, 0); 

     spriteBatch.Begin(SpriteSortMode.BackToFront, null, null, null, null, null, bulletTranslation); 
     spriteBatch.Draw(spr, Vector2.Zero, null, Color.White, 0, origin, 0.15f, SpriteEffects.None, 1f); 
     spriteBatch.End(); 
    } 

    public void Update(Vector2 boundary) 
    { 
     pos += dir * speed; 


     if (pos.X < 50 || pos.X > boundary.X - 50 || pos.Y < 50 || pos.Y > boundary.Y - 50) 
     { 
      alive = false; 
     } 
    } 

    public void FindTurretLength() 
    { 
     turretLength = new Vector2(turretLeng * dir.X, turretLeng * dir.Y); 
    } 

    public Vector2 Pos 
    { 
     get 
     { 
      return pos; 
     } 
     set 
     { 
      pos = value; 
     } 
    } 

    public bool Alive 
    { 
     get 
     { 
      return alive; 
     } 
     set 
     { 
      alive = value; 
     } 
    } 
} 

后来我发现自己调试是,当我自己的 '计数' 变量= 2,但bulletList.Count = 1.这可能是问题吗?这是怎么发生的?

任何帮助,非常感谢。

+1

这种错误发生。你应该能够通过调试和检查它正在被抛出的行来弄清楚发生了什么,然后反向工作并逐步查看代码是如何执行的。 – 2014-11-03 20:32:25

+0

另外,为什么你要把'count'声明为'short'?看来“int”会更自然。 – 2014-11-03 20:47:42

+0

你不了解什么样的例外情况? Visual Studio将显示链接,同时在线调试以获取更多帮助 – MickyD 2014-11-04 06:23:45

回答

1

问题出在您的for循环中删除子弹。

比方说,当你开始循环时,你有一个10项目符号列表(索引0 - 9)。第一个项目符号(索引为0)被删除....现在,您的列表中有9个项目符号(索引0 - 8),但计数变量尚未更新,因此您的for循环仍然认为它有10个。

当你达到了“我”大于实际存活子弹数量的程度,你会得到“索引超出范围”。错误。

有多种方法可以解决这个错误。

我会去的:当您尝试在一个列表或数组比项的个数在上述列表中的较高访问元素

bulletList.RemoveAll(x => !x.Alive); 
+0

这是一个完美的答案。我接受了AlexD的回答,因为他的接受速度更快。谢谢! – meestaman 2014-11-04 12:20:01

+2

@meestaman不要接受基于某人的快速回答,而是基于质量。 – joppiesaus 2014-11-04 17:24:40

+0

@Kaz:这两个答案解释并解决了我的问题。这就是为什么我选择了更快的人。但是,鉴于这个问题可能会在未来帮助其他人,我已经改变了我的“接受的答案”,因为它更容易理解,并为问题提供了一个紧凑的解决方案。 – meestaman 2014-11-08 15:03:45