我正在制作农场/塔防游戏,我在编程时非常陌生。我似乎在使用Lists<>时遇到了一个重大问题或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
更新/绘图
我使用一些简单的foreach循环来更新和绘制植物,这里没有问题。
GetInfo(此方法使用spriteobject的hitbox属性和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设置为我将鼠标悬停在上的工厂的索引。任何建议都将不胜感激。
答案 0 :(得分:6)
首先将其设为正确或||
并检查>= plants.Count
- 请记住该列表已编入0
索引。然后按照建议将其设置为count - 1:
if (SelectedIndex >= plants.Count || SelectedIndex < 0)
SelectedIndex = plants.Count - 1
答案 1 :(得分: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))