Part 3 – Animating and moving the Invaders

In episode 3 we move onto making the Invaders move left to right and back again across the screen dropping down nearer to your player tank in every pass. We’ll also introduce their animation.

This episode is also available to view on line below:

The full code is shown below (click to expand as it is quite large).

We’ve introduced two more constants to support the alien movement on screen, they are:

The INVADERS_DROP_BY definition is how many pixels the Invaders will move down when they reach the edge of the display. The INVADERS_SPEED is how fast they move across the screen at the start of a new level, the lower the number the faster they will go, which is kind of counter-intuitive I know, but the programming is a little easier that way. I’ve used an initial value of 12, which seems about right. Be warned that values should be between 0 and 127 as we use a counter variable later on in combination with this value which is a signed byte and the largest value for a signed byte is 127.

Status of game objects
In the vast majority of games something can be destroyed and Invaders is obviously no different in this respect. As every object in this game can be active or destroyed we need a variable within the GameObjectStruct structure to identify if this object is “active” or not (destroyed). The following shows this change to GameObjectStruct.

We now have a new variable Status that represents an objects current status. To Support this we have a new #define as well:

So to set a game object to active you would use the ACTIVE constant/define, something like this:

MyGameObject.Status=ACTIVE;

Animations
Space Invaders has very simple animations, for each alien character there are two separate graphics defined (i.e. two frames of animation) . We change between each one every time we move the Invaders. We just need to keep track of which one is currently being displayed.  Each extra frame of animation for each Invader is simply named with a “2” at the end, as shown here for the middle Invader:

The variable that keeps track of which animation to display is this one:

If it’s false we will display one frame of the Invaders animation, if true the other frame. When and how we toggle this from value to another will be discussed later.

Other variables involved in the Invaders Movement

AlienXMoveAmount : The number of pixels that the Invaders will move at a time. This changes as the game speeds up towards the end of the level. The higher the number the quicker they appear to move.

InvadersMoveCounter : Used in conjunction with INVADERS_SPEED constant.  This counter gets set to INVADERS_SPEED and then is decremented once per game cycle. When it reaches 0 we move the Invaders and reset back to the INVADERS_SPEED value. More on this later.

The loop
The Arduino loop function has the following code:

Just two functions, the first Physics() is basically all the game logic and rules, from moving the Invaders to checking for collisions. Here it is below;

Not much to it! Well, yet. There will be more in this routine in later episodes but for now the only thing we are implementing are the Invaders movements with the function AlienControl(), shown below:

This entire routine exists just to move the invaders on screen, that is to say alter their X and Y positions, it does not plot them to the display, that is done separately by the UpdateDisplay() which is called just after the Physics routine. It is normal and good practice to separate out your game physics/ logic/rules from the final display to screen. It makes code easier to read, more manageable and disconnects any internal coordinate units we may use from the actual display. What do I mean by that? Well, what if we were suddenly blessed with a screen display of 256×128 (twice the resolution). It would be relatively trivial in the display routine to make our game work on the new display without changing any of the physics code at all. That could be all the same and we just scale to the new display in our display code. If you have plotting to screen all intertwined with your game logic it becomes an unmanageable mess even without considering different displays, so keep them separate 🙂

Let’s go through the routine.

If you remember (hopefully, it was only a few lines ago!) InvadersMoveCounter  is basically controlling the speed of the Invaders across the screen. Looking at the line its value is first decremented by 1 and then a check is made to see if it is less than 0. If so then the Invaders are moved else we basically do nothing and exit the routine ready to be called again. At the beginning this variable is set to INVADERS_SPEED , which itself is set to 12. So every 12 cycles of the main loop we update the Invaders position. At least at the start of the level that is the case for their speed.

As an aside this line “if((InvadersMoveCounter–)<0)” may have some “C” purists shouting that it could have been written in a different slightly more compact way and in by-gone days it may have been a little faster executing. However modern compilers should ensure there is no speed penalty and for beginners the way the line is written is more approachable for beginners or those more used to strongly typed programming languages. If you have no idea what I may be referring to then don’t worry and move on but for those that do and were ready to comment I have deliberately chosen not to write it in a more perhaps C style.

So if it is time to update the Invaders positions (InvadersMoveCounter is less than 0) then we go on to line 145 and create a local variable:

Dropped is an indicator of whether the Invaders have reached the end of the screen and are dropping down. We need to know this as if it is true we only move down and do not update the X positions in this current Invader position update.  The next three lines check if we are at the edge of screen and set and change some variables if we are:

The first line may look a little complex but it can be broken down into two parts, the check for the Invaders going beyond the right edge of the screen and the check for them going beyond the left edge. This is the check for the right:

(RightMostPos()+AlienXMoveAmount>=SCREEN_WIDTH)

The function (which we will look at shortly) RightMostPos returns the right most Invaders X position. Obviously the right most Invader changes as the game progresses as some are destroyed, so this routine simply scans the Invaders for the rightmost one that is still active and returns that X position. We then add to that, the amount we would like them to move by, AlienXMoveAmount. If this total is more than or equal to the screen width (SCREEN_WIDTH) we have therefore hit the right hand edge.

The left hand edge check is very similar,

(LeftMostPos()+AlienXMoveAmount<0)

If the left most Invader + AlienXMoveAmount is less than 0 we have hit the left hand edge of the screen. But… some of you may be wondering how that could possibly work, how could adding the left most position which must be 0 or above to a movement amount ever be a value less than 0? Well if we are moving to the left the AlienXMoveAmount will actually be a negative number, i.e. if move to the right it would be, i.e. +2 (or just 2), if to the left it would be -2. So if the LeftMostPos was 0 we would have the following sum to be worked out of we were moving left:

0+AlienXMoveAmount

and if AlienXMoveAmount is -2 then the line becomes

0+-2

Adding a minus number to a positive ends up subtracting it from that positive number. So the answer would be -2 and less than 0 so we know we’ve hit the left hand edge.

OK, so if we have gone beyond the left or right edge we will execute the following code:

Whichever edge we have reached the code is the same as we need to indicate we are dropping, Dropped=true. We then need to reverse the direction of movement, the line

AlienXMoveAmount=-AlienXMoveAmount. 

does this reverse of direction by changing the mathematical sign of the movement value. Let’s look at a couple of examples, if AlienXMoveAmount was 2 then the line above (if we filled in the numbers) would be:

AlienXMoveAmount=-2

and so we have swapped a +2 to a -2. But what if it is already -2, well let’s put the numbers in again:

AlienXMoveAmount=–2

We now have a minus minus 2 (–2) , one thing learnt from school is that if you minus a minus number you get a positive number so the above becomes

AlienXMoveAmount=2

and we’ve swapped the direction of movement.

Updating the Invaders positions

Here we just loop through every single Invader and the key lines are these:

If the invader is active (i.e. not destroyed) we update its position. If we are currently dropping (remember this is set above) we update its Y position only else we update its X position, which will move it either to the left or right depending on the mathematical sign of AlienXMoveAmount, discussed earlier.

The last two lines of this routine reset the Invader Speed Counter back to its default and flip the animation frame to the next ready for the display routine.

The ! symbol in C (and other languages) means simply “invert” or make opposite and applies only to True and false expressions (Boolean values). So false would become true and true would become false etc.

The Left and Right most positions
In the previous routine we needed to know the left or right most positions of the Invaders and introduced two routines called LeftMostPos and RightMostPos, lets have a look at the code for LeftMostPos.

We set up two counters Across and Down to loop through all the Invaders and also we set a variable (Smallest) to store the currently smallest X position currently found which we initialise to a massive number of twice the screen width, which  will be bigger than any current X position.  Now we could have gone through every single Invader comparing their X position with the smallest X position and if that value was smaller storing it in the variable Smallest.  Then at the end of the routine just return that variable, however there is a more efficient way. The smallest value for X will always be in the left most Invader column as all the other columns occur after this then they must be higher and thus cannot be smaller. So within the loop we go from the left column (Across=0) to the right column. We then scan down each invader in this column (Down=0 to last row). If the Invader is active we check if there X value is less than the current Smallest X value

if(Alien[Across][Down].Ord.X<Smallest)

If it is then we store this as the current smallest value

Smallest=Alien[Across][Down].Ord.X

When we’ve checked all the rows in a column we check if the Smallest variable has changed from what it was initially set at if(Smallest<SCREEN_WIDTH*2). If so we know we have now found the smallest X position for the left most Invader and we exit the routine with return Smallest.

The RightMostPos function is very simaler with just the small matter of having to also include an Invaders width into the calculation, so I won’t go over that but leave it for the reader to examine.

The display function “UpdateDisplay”
This was discussed in part 2 and has been altered only slightly with the addition of a decision as to which animation frame to display, for example for the top Invader (row 0) these are the lines that accomplish this:

So if AnimationFrame is true draw the normal InvaderTopGfx graphic else draw InvaderTopGfx2 graphic (which of course it the other frame of the animation.

That wraps up this episode, next time we’ll look at adding a player “Tank” character and making it move in response to button presses.

Enjoy and Learn 🙂