2

我正在制作一款农业/塔防游戏,而且我对编程非常陌生。在 XNA 中使用 Lists<> 或数组似乎有一个主要问题。我无法让它从列表中返回我想要的索引。

主要问题在我的种植引擎内部。我已经成功实现了一个种植系统,它可以生成具有不同属性的植物(精灵对象)列表并将它们放置在地图上。现在,我需要一种方法来访问植物列表中基于鼠标单击该植物的特定植物。我觉得我很接近,但我最终得到了一个我无法解决的 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 设置为我正在鼠标悬停的植物的索引。任何建议将不胜感激。

4

2 回答 2

6

首先将其设为正确的 or||并检查>= plants.Count- 请记住该列表的索引位置为0。然后按照建议将其设置为计数 - 1:

if (SelectedIndex >= plants.Count || SelectedIndex < 0)
    SelectedIndex = plants.Count - 1
于 2012-04-14T03:13:38.657 回答
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直接修改它。也就是把方法签名改成 return Plantnot voidSelectPlant = NewPlant把上面的代码改成return NewPlant. 或者为了更有趣的单行:

return plants.Where(p => p.BoundingBox.Intersects(ms))
于 2012-04-14T22:30:43.400 回答