Я использую XNA для создания танковой игры. Я реализовал функцию для стрельбы по пулям, используя список. После съемки я хочу проверить, приближалась ли пуля к границам экрана. Если это так, удалите эту конкретную марку из списка.
Ошибка появляется только в том случае, если на экране в каждый момент времени отображается более одной пули. Вот код:
Класс бака:
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;
}
}
}
Что я заметил сам, когда отладка заключалась в том, что моя собственная переменная count = 2, но bulletList.Count = 1. Может быть, проблема? Как это происходит?
Любая помощь приветствуется.
Проблема заключается в вашей петле for, которая удаляет пули.
Допустим, у вас есть список из 10 пуль (индексы 0 - 9) при запуске цикла. 1-я пуля (с индексом 0) удаляется.... теперь ваш список имеет 9 пуль (индексы 0 - 8), но переменная count не обновлена, поэтому ваш цикл по-прежнему считает, что у него 10.
Когда вы достигнете точки, где "i" больше, чем ACTUAL количество пуль вживую, вы получите "Индекс был вне допустимого диапазона". ошибка.
Существует несколько способов устранения этой ошибки.
Я бы пошел:
bulletList.RemoveAll(x => !x.Alive);
count
short
? Кажется,int
будет более естественным.