Search code examples
c#pointersmonogame

How can I make a list of pointers in c#?


I'm currently programming my own 2d engine with monogame and can't get any further because I want to create a list of sprite pointers. My idea is that every time a sprite is initialized it is added to the list and when the draw function is called, every sprite in the list is rendered with a foreach loop. The problem is if I change the properties of the sprite, like position or color, then I have to refresh the list, and that's not the best way. My new idea is to make a list of pointers that point to the respective sprites.So that when you render you have access to the variable and not to a reference.Or maybe there is also a list object that does the work for me? Thanks in advance!


Solution

  • My idea is that every time a sprite is initialized it is added to the list and when the draw function is called, every sprite in the list is rendered with a foreach loop.

    The need for having common objects that need to be updated and drawn along with the Game object is very frequent. You can have multiple approaches for implementing it. Monogame even has it's own implementation of it using the abstract class GameComponents and I have mentioned it in the end.

    The problem is if I change the properties of the sprite, like position or color, then I have to refresh the list, and that's not the best way.

    I believe this problem is due to the fact that the objects in your list are value types and not reference types (equivalent to pointers in C#). In this case, you have the following approaches to try:

    1. Instead of using the generic type List<T>, use a LinkedList<T> in System.Collections.Generic, and you should use it as follows:
    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
            }
    
            ...
    
    
        }
    }
    

    Here, the ValueRef property of LinkedListNode<T> (Here returned by list.First property) will give you exactly what you need: A reference to your object.

    1. Even if you use a List, it should be fine, but your Type must be a Reference type. This means instead of making your custom type as struct, you need to change it to class.

    In case you are using method 2 given above, you might want to check out the GameComponents class, which is Monogame's in-built approach to this problem. GameComponents is an abstract class, so it goes without saying you need to change your type from struct to class.

    Let's say you have your custom class as shown

    public class MyCustomClass: Microsoft.Xna.Framework.GameComponent
    {
        public MyCustomClass(Game game)
            : base(game)
        {
    
        }
    }
    

    The LoadContent(), Initialize(), and Update() methods are inherited and can be overridden to your liking.

    You can create an instance of this class in your Game class, and add this object to the Components property of the Game object as shown

        var MyCustomObject = new MyCustomClass(this);
        Components.Add(MyCustomObject);
    

    By doing this, The base class Game calls the Update(), Draw(), LoadContent() methods on its own respective calls.

    You can iterate through your required objects using the following approach

        foreach (var item in Components)
        {
            if(item is MyCustomClass)
            {
                var myitem = item as MyCustomClass;
                ...
            }
        }