我的想法是,每次初始化一个精灵时,它都会被添加到列表中,并且当调用 draw 函数时,列表中的每个精灵都使用 foreach 循环进行渲染。
需要与Game 对象一起更新和绘制的公共对象非常频繁。您可以有多种方法来实现它。 Monogame 甚至有它自己的使用抽象类 GameComponents 的实现,我在最后提到了它。
问题是如果我改变了精灵的属性,比如位置或颜色,那么我必须刷新列表,这不是最好的方法。
我相信这个问题是由于列表中的对象是值类型而不是引用类型(相当于 C# 中的指针)。在这种情况下,您可以尝试以下方法:
- 不要使用泛型类型
List<T>,而是在System.Collections.Generic 中使用LinkedList<T>,您应该按如下方式使用它:
class Game1:Game
{
LinkedList<MyCustomClass> list;
...
void LoadContent()
{
list = new LinkedList<MyCustomClass>();
...
list.AddLast(myobject);
}
void Update(GameTime gameTime)
{
//Do not use a foreach loop. Instead, do this:
for (var node = list.First; node != null; node = node.Next)
{
node.ValueRef.Update();
//Important to use ValueRef, as it returns the reference of the object
}
...
}
}
在这里,LinkedListNode<T> 的 ValueRef 属性(此处由 list.First 属性返回)将为您提供所需的内容:对对象的引用。
- 即使你使用 List 也应该没问题,但你的 Type 必须是 Reference 类型。这意味着您需要将其更改为
class,而不是将您的自定义类型设置为 struct。
如果您使用上面给出的方法 2,您可能需要查看 GameComponents 类,这是 Monogame 解决此问题的内置方法。 GameComponents 是一个抽象类,所以不用说你需要将你的类型从 struct 更改为 class。
假设您有如下所示的自定义类
public class MyCustomClass: Microsoft.Xna.Framework.GameComponent
{
public MyCustomClass(Game game)
: base(game)
{
}
}
LoadContent()、Initialize() 和 Update() 方法是继承的,可以根据自己的喜好覆盖。
您可以在Game 类中创建此类的实例,并将此对象添加到Game 对象的Components 属性中,如图所示
var MyCustomObject = new MyCustomClass(this);
Components.Add(MyCustomObject);
通过这样做,基类Game 在其各自的调用中调用Update()、Draw()、LoadContent() 方法。
您可以使用以下方法遍历所需的对象
foreach (var item in Components)
{
if(item is MyCustomClass)
{
var myitem = item as MyCustomClass;
...
}
}