Visual Studio 吃豆人收集硬币

c3frrgcw  于 2023-02-19  发布在  其他
关注(0)|答案(1)|浏览(119)

我尝试了两种不同的方法来收集硬币,但都不起作用。我不知道我做错了什么。我用c#编写代码。是我遗漏了什么,还是我应该事先做些什么?
下面是方法1:

//collecting coins
            foreach(Control x in this.Controls)
            {
                if (x is PictureBox && x.Tag == "coin")
                {
                    if (((PictureBox)x).Bounds.IntersectsWith(pacman.Bounds))
                    {
                        this.Controls.Remove(x); //remove that point
                        score++; // add to the score
                    }
                }
            }

下面是第二种方法:

//collecting coins
            foreach(Control x in this.Controls)
            {
                if (x is PictureBox)
                {
                    if ((string)x.Tag == "coin" && x.Visible == true) 
                    {
                        if (pacman.Bounds.IntersectsWith(x.Bounds))
                        {
                            score += 1;
                            x.Visible = false;
                        }
                    }
                }
            }
vfhzx4xs

vfhzx4xs1#

由于没有完整的源代码和可视化树,我只能试着理解为什么这不起作用,在我看来,pacman对象和coins没有定义在同一个父对象中。
bounds属性相对于作为坐标原点的父控件。
如果控件集合中的每个元素都位于可视化树的同一级别,并且具有相同的父级,则该函数可以正常工作。否则,intersect将很难为true,因为它正在检查两个不同的坐标原点,并且即使返回true,屏幕上的位置也无法匹配。
由于您的pacman似乎被引用到集合之外的其他地方,因此您的控件可能没有相同的父级,并且您的pacman和硬币不太可能具有相同的起源,并且IF...ELSE永远不会命中。请确保为pacman和硬币使用相同的父级。
另一个解决方案是使用绘图原语在画布上绘制游戏对象,并创建临时对象来存储绘图矩形。这是首选的解决方案,因为使用GDI+对象绘制游戏元素的性能不佳。如果您使用画布,则您所要做的就是在每个绘图循环中使用游戏对象的图像更新画布。这样,控件的可视化树不会有任何问题。

**编辑:**如其他评论所述,如果你成功地达到了交集条件,在你的代码的第一个版本中,你也将面临在使用foreach迭代集合时从集合中移除项的异常。在这种情况下,解决方案是首先迭代列表,并将项添加到一个新的“removedItemsList”,然后迭代这个新列表,从控件集合中移除项,而不迭代它。它不是很有效,在我看来,你的第二个解决方案要好得多。它效率不高至少有两个原因:一是因为每次移除控件时,可视化树都会为每个剩余控件更新。二是必须分配新列表,并在每次击中硬币时重复该列表。可见性只会使控件呈现矩形无效,并且在下一次绘制路由时,它将绘制为不可见。

相关问题