Проблемы со списками C# и ArgumentOutOfRangeException
Я нахожусь в процессе создания игры по защите ферм / башен, и я очень новичок в программировании. Кажется, у меня есть большая проблема с использованием списков<> или массивов в XNA. Я не могу получить его, чтобы вернуть индекс, который я хочу из списка.
Главный вопрос внутри моего посадочного двигателя. Я успешно внедрил систему посадки, которая может генерировать список растений (спрайтобъектов) с различными свойствами и размещать их на карте. Теперь мне нужен способ доступа к конкретному растению в списке растений, основанный на щелчке мышью по этому растению. Я чувствую, что я очень близок, но в результате я получил ArgumentOutOfRangeException, который не могу решить. Вот прохождение кода:
инициализация
public void Addplants()
{
switch (Mode)
{
case "Wotalemon":
NewPlant = new Plant(Texture, msRect);
NewPlant.AddAnimation("seed", 0, 16, 64, 64, 1, 0.1f);
NewPlant.AddAnimation("sprout", 64, 16, 64, 64, 1, 0.1f);
NewPlant.AddAnimation("wota", 128, 16, 64, 64, 1, 1.0f);
NewPlant.CurrentAnimation = "seed";
NewPlant.DrawOffset = new Vector2(32, 48);
NewPlant.Position = Position;
NewPlant.Type = "wotalemon";
NewPlant.Birthday = Days;
NewPlant.IsSelected = false;
plants.Add(NewPlant);
thisPlant = NewPlant;
//various plants after this
Обновление /Draw
Я использую несколько простых циклов foreach для обновления и рисования растений, здесь нет проблем.
GetInfo (этот метод использует свойство hitbox объекта spriteobject и mouseRectangle)
public void GetInfo(Rectangle ms)
{
msRect = ms;
for (int i = 0; i < plants.Count; i++)
{
foreach (Plant NewPlant in plants)
{
if (NewPlant.BoundingBox.Intersects(msRect))
{
SelectedIndex = i;
NewPlant.Tint = Color.Black;
}
else
NewPlant.Tint = Color.White;
}
}
}
наконец, вот проблема:
public void SelectPlant()
{
//if (SelectedIndex != null)
if (SelectedIndex > plants.Count | SelectedIndex < 0)
SelectedIndex = plants.Count;
SelectedPlant = plants[SelectedIndex];
}
Исключение выдается в этой строке:
SelectedPlant = plants[SelectedIndex];
Отладчик показывает значение как 0. Я пытался различными способами, чтобы предотвратить нулевой индекс. Я чувствую, что что-то в методе Getinfo() является ключевым здесь. Я убежден, что я очень близок к успеху, потому что цветовой тест, который я вставил туда, работает отлично. Когда я наведите курсор мыши на растение, оно станет черным, когда я уберу мышь, оно вернется к норме.
Это именно тот тип поведения, который мне нужен, за исключением того, что я хочу, чтобы он установил selectedIndex в качестве индекса растения, над которым я нахожусь. Любой совет будет принята с благодарностью.
2 ответа
Я добавлю это как новый ответ, так как это решает совершенно другую проблему. Взгляните на этот код:
msRect = ms;
for (int i = 0; i < plants.Count; i++)
{
foreach (Plant NewPlant in plants) // <-- this is redundant
{
if (NewPlant.BoundingBox.Intersects(msRect))
{
SelectedIndex = i;
NewPlant.Tint = Color.Black;
}
else
NewPlant.Tint = Color.White;
}
}
Вы проходите через "растения" дважды внутри друг друга! После использования индекса (for (int i = 0 ...
), а затем внутри этого снова с помощью итератора (foreach (Plant NewPlant ...
).
Ваши варианты либо изменить GetInfo
установить правильный индекс с помощью одного цикла:
msRect = ms;
for (int i = 0; i < plants.Count; i++)
{
Plant NewPlant = plants[i];
if (NewPlant.BoundingBox.Intersects(msRect))
{
SelectedIndex = i;
NewPlant.Tint = Color.Black;
}
else
NewPlant.Tint = Color.White;
}
Или сделайте то же самое и замкните накоротко необходимость в SelectPlant() и SelectedIndex в первую очередь:
msRect = ms;
foreach (Plant NewPlant in plants) // no need for indexes
{
if (NewPlant.BoundingBox.Intersects(msRect))
{
SelectedPlant = NewPlant; // this is everything you need
NewPlant.Tint = Color.Black;
}
else
NewPlant.Tint = Color.White;
}
Однако вы должны быть осторожны, используя "глобальную" переменную, такую как SelectedPlant
чтобы захватить эту логику. Вам лучше изменить весь GetInfo
способ вернуть выбранное растение, вместо того, чтобы модифицировать его SelectedPlant
непосредственно. То есть измените сигнатуру метода для возврата Plant
не void
и изменить SelectPlant = NewPlant
в коде выше, чтобы return NewPlant
, Или для еще большего удовольствия одной строкой:
return plants.Where(p => p.BoundingBox.Intersects(ms))
Во-первых, сделать это правильным или ||
и проверить на >= plants.Count
- помните, что список проиндексирован на 0
, Затем, как предложено, установите его на счет - 1:
if (SelectedIndex >= plants.Count || SelectedIndex < 0)
SelectedIndex = plants.Count - 1