Search code examples
c#loopsfor-loopdirectxdirect2d

Program 'for loop' is changing multiple values in the array in one instance


I was working line by line in the debugger option (red dot) in express 2010 visual c#. This loop was assiging creatures[2].sprite.position and creatures[3].sprite.position to the same vector (100,320) at the same instance, when i equaled 2.

Further testing showed that when i = 3 the same would happen, then on i = 4, all 2,3, and 4 were changed at the same time to the same vector.

any suggestions on whats causing this, it feels like a bug, thinking about it now, I should try a different variable than i, maybe its being used some where else.

public class GameImages
    {
        //Image Diminsions
        public Texture2D texture;
        //Images position on the Viewport
        public Vector2 position = new Vector2(0,0);
        //Color
        public Microsoft.Xna.Framework.Color color = Microsoft.Xna.Framework.Color.White;
    }

 public class CreaturesAttributes
    {
        //Image
        public GameImages sprite;
        //Level
        public double Level;
    }

CreaturesAttributes[] creatures = new CreaturesAttributes[100];


public void LoadTeam()
    {
        int j = 0;
        for (int i = 1; i < creatures.Length; i++)
        {

            if (creatures[i].Color1 != null)
            {
                creatures[i].sprite.position = new Vector2(j, 320);
                j += 100;

            }
            else
            {
                i = creatures.Length;
            }
        }
    }
    protected override void Initialize()
    {
        for (int i = 0; i < creatures.Length; i++)
        {
            creatures[i] = new CreaturesAttributes();
            creatures[i].sprite = new GameImages();    
        }
    }

Solution

  • This happens because you probably initialized all your array elements to point to a single instance:

    var newCreature = new Creature(/* ... */);
    for (int i = 0; i < creatures.Length; i++) {
      creatures[i] = newCreature;
    }
    

    Or perhaps you created multiple creatures, but with the same "sprite":

    var defaultSprite = new Sprite(/* ... */);
    for (int i = 0; i < creatures.Length; i++) {
      creatures[i] = new Creature();
      creatures[i].sprite = defaultSprite;
    }
    

    or maybe sprite or position are static fields:

    static Sprite sprite;
    //or
    static Vector2 position;
    

    All the above will cause all your mutations and accesses to happen to the same instance, so it looks like changing one is changing all of them (while there in reality is just a single creature/sprite/position that you're referencing from multiple places).

    The solution is to ensure that the fields are not static, and make sure to create a new creature and creature.sprite for each:

    // No static fields, and new instances for each index
    for (int i = 0; i < creatures.Length; i++) {
      creatures[i] = new Creature();
      creatures[i].sprite = new Sprite();
    }