Let’s say I got a collection (simple grid) of invaders:

In this image, only invader type C can shoot.
Shots are fired, an invader gets destroyed:

Now, invader type B in the third column in the second row can fire as well. Note that there can only be three random invader shots on the screen at the same time. So only three of the invaders in the set {C, C, B, C, C, C} can shoot.
How would I go about implementing this? I am thinking of two solutions:
-
Use an array of arrays [][] (or [,]). When an invader get shot, the place where the invader was gets set to null. Then, when it’s time for the invaders to fire, there’s a loop going over the first row. Encountering a null makes it check the space above the null. Is it null? Then do the same for the space above that. Is the space in the uppermost row null? Go to the next column in the first row.
-
Each invader type has a position (I use Point for that). Assign to each position the row number (the collection used will be some sort of dictionary). So, when looking at the image, all C’s get a 1, all B’s get a 2, and all A’s get a 3.
In this picture, C at position (2, 2) is destroyed. It should then subtract 1 from it the Y value of the point, which will be (2, 1). If there’s a position like that in the collection, then assign the invader at that position (2, 1) to the position of the invader that got destroyed (2, 2).. Like this, I don’t have to have a jagged array containing a bunch of nulls.
My thoughts about how it should look like -> when the game starts the first set is {C C C C C C} and then it will be {C C B C C C}. From this set, three will be randomly chosen to fire.
So, any thoughts?
In game development, especially in a managed language like C# and especially on the Xbox 360, in general your first priority should be to avoid allocating memory while the game is running. Saving memory and reducing operation count is a secondary concern.
A
null(in 32-bit, which XNA runs in) is just four bytes!A 2D array (
[,]) containing pointers to your invaders seems entirely appropriate. Especially as it allows you to make the location of each invader implicit by its location in the data structure. (Do you even need to create individual invader objects and point to them? Just use a number which indicates what “type” of invader they are.)Looping through that data structure (in the manner you suggest) is going to be so amazingly fast that it may well be a “free” operation. Because the processor itself can process the data faster than you can bring it into the cache anyway.
AND you’re not even doing it every frame – only when your invaders fire! I am willing to bet that it would be slower to calculate and store that data whenever an invader is destroyed and then load it when your invaders fire.
(Basically what you are proposing is caching/pre-computing that data. A useful performance optimisation technique – but only when it’s actually necessary.)
You should be a lot more worried about costs that happen each frame, than ones that are only triggered occasionally by timers and user input.
Do not use a jagged array (
[][]). This is basically an array of arrays. It uses more memory and involves an additional layer of indirection which in turn also has the effect of potentially reducing the locality of your data (meaning your data might not end up in the cache in a single hit – this is the “slow bit”). It also increases the number of objects the GC has to think about. Do not use aDictionaryfor the same reasons.In game development it helps to keep this kind of performance stuff at least in-mind when you work (anywhere else this would be completely premature optimisation).
But, for something as simple as Space Invaders, you can pretty much do whatever you like! So do the simplest thing that could possibly work.