Welcome to the Space Invaders coding project for Android. In this game project, we will step through everything you need to know to have a fully playable Space Invaders clone running on your Android phone or tablet. The wave of invaders is genuinely challenging yet achievable and it would be simple for you to extend this project to add extra features like increasingly difficult waves, high scores or perhaps add a flying saucer-like in the original arcade classic.

patreon

 

 

About this project

Skill level 1
Time to complete 1 hour

New Concepts:

  1. Internal animation timing to make the Invaders flap their arms
  2. Using an external class for the view of the game
  3. Enemies that think, move, and take aim

Recommended preparation tutorials

Getting started

The finished game will allow the player to move left and right by holding the corresponding side of the screen near the bottom. As the player also needs to shoot at the invaders we will respond when the screen is touched slightly higher than the lower part as well. The Invaders will slide across the screen flapping their arms and spitting bullets. If they hit a player he loses a life if they hit a shelter it will crumble until eventually the player has nowhere to hide. When the invaders reach the side of the screen they will drop down and scroll back the other way; a little bit faster. Eventually, they will be moving so fast the player is doomed. The space invaders must be taken out quickly and efficiently to survive.

To get started create a new project in Android Studio, call it Space Invaders, and name the Activity SpaceInvadersActivity then read on because we will do things slightly differently compared to the Breakout project.

Making the game a full-screen landscape

We want to use every pixel that the device has to offer so we will make changes to the app’s AndroidManifest.xml configuration file.

  1. In the project explorer pane in Android Studio double click on the manifests folder, this will open up the AndroidManifest.xml file in the code editor.
  2. In the AndroidManifest.xml file, locate the following line of code,  android:name=".SpaceInvadersActivity">
  3. Place the cursor before the closing > shown above. Tap the enter key a couple of times to move the > a couple of lines below the rest of the line shown above.
  4. Immediately below SpaceInvadersActivity but BEFORE the newly positioned > type or copy and paste these two lines to make the game run full screen and lock it in the landscape orientation.

Let’s talk a bit about the assets we will use in Space Invaders.

 

 

The Graphics

In this project, we will use a mixture of bitmaps from external graphics files for the invaders and player ship and use the Canvas class’ drawRect method to represent the lasers and the shelters. Something worth mentioning at this point is that even the classes that use bitmaps will still have a RectF object because although we don’t need it for drawing we can still use it for collision detection. More on this later in the project.

Before we get coding we want to add the player ship graphic and two different graphics for the two frames of animation for our invader to our project files so we can use them in our code. The graphics are white so they are displayed below on a blue background. Here they are.

The Space Invaders player ship graphic

The Space Invaders player ship graphic

The first frame of animation for the invader

The first frame of animation for the invader

The second frame of animation for the invader

The second frame of animation for the invader

 

You can download them by right-clicking on the images and then selecting the Save image as… option. Just make sure the file names are kept the same. They are named playership.png, invader1.png, and invader2.png. Add the graphics to the drawable folder within your Android Studio folders.

The sound

We will have a menacing two-tone sound to represent the invader’s movement. This sound will speed up as the invaders speed up. I have called these two sounds “uh” and “oh” because if we were attacked by invaders we might say, “uh oh”. We also need sounds for shooting a laser, the player being hit, an invader being hit and a shelter being damaged.

Of course, we need to add the sound files to our project. You can create your own or download mine by right-clicking on the files listed below. Just make sure you use exactly the same file names. You can also listen to each of the sounds by using the media controls below each of the links.

uh.ogg

 

shoot.ogg

 

playerexplode.ogg

 

oh.ogg

 

invaderexplode.ogg

 

damageshelter.ogg

When you have your preferred sound FX, using your operating system’s file browser go to the app\src\main folder of the project and create a folder called assets. Add your sound file to this folder.

The class structure

For this project, we will vary slightly from the structure of the Breakout project. But far from adding complexity, we will see how by separating out further the code in the different files we will make our Space Invaders project simpler to write, manage and extend.

Each game object will be represented by its own class. So we will have one for the player’s ship, one for an invader, a bullet, and the brick of a defense shelter. Furthermore, we will also take the inner class which represents the view of the game, and make it a class in its own right. It will be called SpaceInvadersView. This changes nothing about how we code it internally but it does make the whole project more manageable.

We want to create classes to represent the view and the game objects we have just discussed. We will require the following classes.  SpaceInvadersView, Invader, PlayerShip, DefenceBrick and  Bullet. By creating empty implementations of all these classes we can then declare objects of them in  SpaceInvadersView right away. This avoids constantly revisiting SpaceInvadersView to add new declarations. All we will need to do is implement each object, in turn, initialize it, update it, and draw it.

With this in mind let’s create those empty classes. Now, Right-click the java folder in the Android Studio project explorer as shown in the next image.

Creating a new Java class called Paddle

Creating a new Java class called

Now select New|Java class then select …\app\source\main\java and click OK. Now enter SpaceInvadersView as the name for our new class and click OK. We have now created a new Java class in a separate file called SpaceInvadersView.java. As previously mentioned the class is not an inner class as the view was in the Breakout project.  This helps us to compartmentalize our code and keep it organized into logical areas to a greater extent than we did previously.

Now do the same and create new classes for  PlayerShip, Bullet, DefenceBrick, and Invader classes. You should now have six classes in total including SpaceInvadersActivity. Just for clarity, the code for each of the five new classes is shown below (excluding the package declaration at the top of each class). We will then look at each of the classes, in turn, starting with SpaceInvadersActivity.

SpaceInvadersView

PlayerShip

Bullet

DefenceBrick

Invader

 

Coding the Space Invaders Activity class

There is nothing new here compared to the Activity class from the Breakout project. The only difference is that there is no inner class extending SurfaceView. Notice that we still create a new object of type SpaceInvadersView and set it as the view for the screen. We also get the screen resolution and pass this information into the  SpaceInvadersView constructor method. The code below will show some errors until we implement the SpaceInvadersView class.

Tip: We will be using plenty of classes from the Android API in this project. You can use the Android Studio shortcut Alt + Enter while the mouse cursor hovers over any Android class which is showing an error. This will add the appropriate import… line at the top of the file.

Delete the default code that was auto-generated from SpaceInvadersActivity then add the code below.

Now we have a working Activity class that is the entry point to our Space Invaders game. It will simply get the screen resolution, and pass it to SpaceInvadersView where all the game action will take place. SpaceInvadersActivity will not do anything unless it gets a message from the operating system to say it is being shut down or restarted; in which case it will call the pause and resume methods of SpaceInvadersView which will shut down or start the main game thread.

Coding the Space Invaders view class outline

As we have already created a bunch of empty classes we can flesh out our game engine along with a whole bunch of the key variable and object declarations right away. I have broken the starting code for this class into a number of sections as the code is quite lengthy. However, there is not much that we didn’t already see in the last project.

The SpaceInadersView declaration and member variables

First of all, in the next block of code, we see that the class declaration needs to be modified to extend SurfaceView and implement Runnable to provide our drawing and threading functionality. We then see a bunch of familiar member objects and variables for handling our thread, drawing, main game loop, frame rate, and screen resolution. The comments should act as a reminder to what does what.

Starting with the declaration of the playerShip object we see the Space Invaders-specific declarations. We have an object of PlayerShip and one of Bullet which will unsurprisingly represent the player’s ship and his solitary bullet. We then have an array of Bullet objects called invadersBullets along with a couple of variables nextBullet and maxInvaderBullets to help us manage this array.

After this, we then declare an array to hold a whole army of Invader objects and again, a variable to help us manage the array. Then we have an array of DefenceBrick objects. We will see how we construct and destroy the player’s shelters from this array later.

Following that we have the usual SoundPool object and a  int to represent each of the sound FX we will want to play. Then we have an int to represent score and a  int to represent lives. The last variables we declare are new and we will see near the end of the project how we use menaceInterval, uhOrOh and lastMenaceTime to time the flapping of the invader’s arms and the speed of the “uh oh” sound FX.

Declaring all the variables we just have will make progress through the rest of the project much faster.

The SpaceInvadersView constructor

The constructor is the first method we will implement. The constructor is the method called from SpaceInvadersActivity in the code spaceInvadersView = new SpaceInvadersView(this, screenX, screenY). So the first thing we notice is the signature of the method which receives the variables passed in.

As before we call the parent class ( SurfaceView) to help set up our object with the code super(context). The next line is new. this.context = context copies the Context object passed into the constructor to the SpaceInvadersView own context object. This makes it available throughout the class and not just in the constructor. The rest of the constructor we have seen in the last project. We simply initialize screenX and screenY then prepare our sound files ready to be played.

Finally, in the constructor, we call the prepareLevel method which is where we will initialize all our game objects and get ready to play the game. Notice in the implementation of prepareLevel there is a bunch of comments that indicate where code we have yet to write will eventually go. Add all the code in the constructor and prepareLevel immediately after the previous block of code. Be sure to include the comments in prepareLevel as reference points for the code we will soon write.

We are making good progress. We just need to add some of the usual suspects (methods) to the project and then we can get on with coding our first game object.

The usual game-loop methods: run, update, and draw

Next, we will add a whole bunch of methods that we have seen before when we looked at coding a basic game loop and coding a Breakout game. However, notice all placeholder comments that will be invaluable for locating where the code we will soon write needs to go. Add the methods below right after the prepareLevel method.

A few more methods that we have seen before follow next.

More of the usual suspects: pause, resume, and onTouchEvent

Add these methods which start and stop our thread and will eventually detect the player’s input.

Now we can run the Space Invaders game and see just the score and a plain background.

The first runnable screen shot of the Android Space Invaders project

The first runnable screenshot of the Android Space Invaders project

Now we have the outline for our SpaceInvadersView class let’s build the player’s spaceship.

Implementing the PlayerShip class

First of all, we have an  RectF instance that will be used for collision detection, then we have an  Bitmap object into which we will load the playership.png graphic, a float for each of the height and length,  a float for the x and y coordinates of the spaceship on the screen and another float, shipSpeed which is how many pixels per second the ship can move.

After that, we have three final int members STOPPED, LEFT and RIGHT which are public and can, therefore, be accessed from the SpaceInvadersView class to tell the spaceship which way to move. Then we have shipMoving which will be assigned one of the aforementioned final values and this is used internally in the update method of this class to determine which way to move if any.

Add all these member variables and objects just after the class declaration.

Here is the PlayerShip constructor where we set up our PlayerShip class ready to defend the Earth. Notice the method parameters receive a Context and the screen’s horizontal and vertical resolution. We will see how we use these soon.

First, we initialize rect as a blank rectangle. It will become apparent how this object is useful soon when we implement the update method. We initialize length and height by dividing the screen resolution on the horizontal and vertical axes by ten. Ten is an arbitrary value but it works well. For a smaller ship, increase the number for a bigger ship decrease the number.

Next, we initialize x and y to the middle of the screen horizontally and just above the bottom vertically. The x and y variables actually refer to the top left pixel of the spaceship so dividing screenX by two is not exactly the middle but it is good enough.

Now we load bitmap with the .png file using BitmapFactory.decodeResource and after that, we scale the bitmap to the correct length and height using Bitmap.createScaledBitmap method.

Finally, for the constructor, we initialize the speed of our spaceship. Add this code just after the previous block of code.

Here are some getters and setters so that SpaceInvadersView can grab a copy of rect for collision detection, bitmap for drawing the spaceship, x and length for firing bullets dead-center from the ship and the setter setMovementState gives onTouchEvent the ability to determine which way the ship should move each time update is called.

Add these methods below the last block of code then we can look at the update method.

And here is the last method of the PlayerShip class called update. It is very simple in the beginning and we have seen before how we update the x variable by shipSpeed divided by the current frame rate the game is running at and dependent upon the value of shipMoving. But what happens next is the key to how we detect collisions for our spaceship. We update the starting and ending horizontal and vertical positions of rect with the x and y locations of the spaceship. We know the ending locations simply by adding height to y and length to x. Now whenever SpaceInvadersActivity calls getRect it will get an  RectF object which effectively wraps the player’s spaceship. This RectF can then be used in the RectF.intersects method in exactly the same way it was in the Breakout game. Add the update method to the PlayerShip class.

That’s it for the PlayerShip class. Now we can put it to work in three stages. First, we will initialize one in the prepareLevel method, then we will call its update method from update and then we will draw it in the draw method. We won’t be able to move the ship however until we fully implement the onTouchEvent method which we will do after we have implemented the Bullet class.

Enter this code in the prepareLevel method in the place indicated by the comment.

Enter this code in the update method in the place indicated by the comment.

Enter this code in the draw method in the place indicated by the comment.

            // Now draw the player spaceship
            canvas.drawBitmap(playerShip.getBitmap(), playerShip.getX(), screenY - 50, paint);

If you run the game you will see the spaceship at the bottom of the screen.

The ship only

The ship only

Now we can implement the Bullet class

Shooting bullets

First, we add some member variables. An x and y to hold the bullet’s location on the screen. a RectF which will be used to both draw and detect collisions on a bullet. Two final int variables; UP and DOWN that SpaceInvadersView can use to control the direction of a bullet and heading which will hold one of those values; we initially initialize to -1 because it is going nowhere at the moment. The speed variable is initialized to 350. This is the pixels per second that the bullet will travel at. This is quite fast and presents a challenge even on a medium-resolution tablet. All bullets have a width and a height. The width is initialized right away to 1 pixel, height will be initialized in the constructor, and will be relative to the resolution of the screen. The last variable is a boolean isActive. We can set this to  true and false as needed so we know when to draw and update each bullet and when we don’t need to bother.

Finally in the block of code below we have the constructor which initializes y as previously described, sets isActive to false and initializes a blank RectF object. Enter the code below in the Bullet class.

Next, we have a bunch of getters and setters that pass rect back to SpaceInvadersView for collision detection and drawing, returns the status ( isActive true or false) which as we will see is useful for knowing when to draw and check for collisions and finally we have a getImpactPointY method which returns the tip pixel of the bullet. This will be different depending on whether the bullet is heading down (fired by an invader) or up (fired by a player). Enter the getters and setters we have just discussed below the previous block of code.

Next, we have the important shoot method which works by first confirming that the bullet is NOT already active. If it is already active, the launch of the bullet fails. Otherwise, a starting x and y location is initialized, the heading is set and the bullet is set to isActive = true. We return true to the calling code so further actions can be taken for a successful bullet launch; namely playing a sound and keeping track of the invadersBullets array. If the bullet was already active at the time this method was called the code returns false to let the calling code know that a new bullet launch was not possible.

Enter the shoot method below the previous block of code.

Of course, this class will also need a  update method. Notice that we update x and y in the usual way and also update rect so it is up-to-date for drawing and collision detection when required. Enter the update method into the Bullet class.

Now we just need to initialize, update and draw the bullets. Obviously, we won’t actually see any bullets until we implement a fire button for the player’s single bullet and the Invader class which will trigger the firing of the enemy bullets.

Notice in the next three blocks of code that we keep the single player’s bullet ( bullet) and the array of bullets ( invaderBullets) the invaders will use separately. We don’t want to waste time doing collision detection on the invader’s bullets against the invaders themselves so it is good to know which bullet belongs to which protagonist. Although we will detect the player damaging his own shelter as this feature was in the original arcade classic.

Enter this code in the prepareLevel method in the place indicated by the comment.

Enter this code in the update method in the place indicated by the comments.

Enter this code in the draw method in the place indicated by the comments.

Now we can implement the player controls to let him move and shoot.

Giving the player control

In the next block of code, I show the entire onTouchEvent method including the code we fleshed out near the start of the project. In it, you can see that we set paused to false in the ACTION_DOWN case. Also in  ACTION_DOWN case we detect any touches in the bottom eighth of the screen ( if(motionEvent.getY() > screenY - screenY / 8)) then further test which side of the screen the touch was and call setMovementState with the appropriate public final int  to update which way the player’s spaceship will travel.

After this, still in  ACTION_DOWN case we detect if a touch occurs ABOVE the bottom eighth of the screen ( if(motionEvent.getY() > screenY - screenY / 8)) and if so we call shoot on bullet passing in the coordinates of the top center of the player’s ship. If the shoot method returns true then a bullet is launched and a sound FX is played.

In the next case, ACTION_UP we simply stop the ship from moving by passing STOPPED into setMovementState.

You can now run the game, and move the spaceship around by holding the screen on the bottom left and right. Furthermore, if you tap anywhere above the bottom eighth of the screen the player’s ship will fire a bullet. It will also play a laser-shooting sound effect.

Let’s give the player something to shoot at.

Implementing the Invader class

This class like the PlayerShip class will have an  RectF object as well as an  Bitmap object for collision detection and drawing respectively. We will implement these features in exactly the same way. However, the Invader class will have a Bitmap for each frame of animation (arms up and arms down). We will see in this class that we have a getBitmap and a getBitmap2 method. We will see later in the draw method of SpaceInvadersView how we choose which one to call each frame.

With this in mind enter this code to declare all the objects and variables the Invader class will need.

Next, we have the Invader constructor that initializes  rect as a blank rectangle, initializes length and width based on the screen resolution sets isVisible as  true because we want to see the invader unless it is shot. Notice how the x and y location on the screen is determined by the invader’s position in the invader army. A row and column number is passed into the constructor and this is used, along with an  padding of one twenty-fifth of the screens x resolution to determine the invader’s exact starting location.

Then in the constructor, we initialize and scale two Bitmap objects using the two graphics files. Finally, we set the speed to forty pixels per second. This will increase as the army of invaders make their way down to Earth.

Next, we have a bunch of getters, setters, and helper methods. The first two below get and set the object as invisible and get the current state of visibility. The next two get the two bitmaps and return them to the code that called them. The next three,  getX  getY and getLength return the x,  y and length values respectively. These are used, as they were with PlayerShip to get precise coordinates at which to fire a bullet. Enter these getter and setter methods.

And of course, our Invader class needs a update method. This works in exactly the same way as it did for the PlayerShip class. Notice however that there is no code to handle the invader moving down. We will see this code next. Enter the code for the Invader class update method.

The next method dropDownAndReverse does exactly as the name suggests. It swaps LEFT for RIGHT or vice versa then increases the invader’s y coordinate by height which has the effect of moving it down the screen. Finally, the speed is increased by 18% by multiplying by 1.18. Enter the dropDownAndReverse method.

The takeAim method is kind of like our invader’s artificial intelligence. The first block of code in this method detects if the Invader object is approximately horizontally aligned with the player. If it is a random number is generated to produce a 1 in 150 chance of returning true to the calling code. As we will see shortly in the calling code, when true is returned an attempt to launch a bullet is made with a call to shoot.

If 1 in 150 doesn’t seem like very much chance that a shot will be fired just consider that this method will be called up to sixty times a second on one or maybe even two complete columns of invaders that return true to the initial if condition. So there will be loads of bullets flying when we run this code.

In the second block of code in this method, every invader is given a chance to unleash a shot no matter if they are aligned to the player or not. This is great for creating a hostile environment and taking out the shelters. As every single invader gets around sixty throws of the dice every second the odds have been changed to 1 in 2000. These are good variables to play with if you want to make the game harder or easier.

Initializing, drawing, and updating the invaders

Now, as usual, we need to add code to the relevant places in SpaceInvadersView to bring our army of Invader objects to life.

Notice how we pass in a row, changing, and column numbers to each successive Invader object in our array. And we keep track of the overall number of Invader objects in our array by incrementing numIvaders. Enter this code in the prepareLevel method in the place indicated by the comments.

This next block of code which updates our array of invaders in each frame is quite lengthy but when examined closely it is not complicated. First, we loop through each and every invader and check if it is visible. If it is we call its update method and its coordinates will be updated. Next, we call takeAim on each and every invader in the array. Using the odds and aiming criteria specified in the takeAim method it might or might not return true. If it returns true we call shoot on the next bullet in the array as identified by nextBullet. If a bullet is successfully fired nextBullet is incremented ready for the next invader. We then check if nextBullet is equal to maxInvaderBullets and if it is we set nextBullet back to zero.

Back outside of the takeAim if block, we check if the invader has touched either the left or right side of the screen and if it has we set bumped to true.

Enter the code we have just discussed in the update method in the place indicated by the comment.

This next code handles how the invaders are triggered to drop down and start heading the other way. It also decreases the value of menaceInterval making the invader arm waving and menacing sounds more frequent although we have a little more coding before this will take effect.

Enter this code in the update method immediately after the last block in the place indicated by the comment.

Now we draw the invaders, notice the code we use to switch between the two different frames of animation. We will make this code fully functional in the section Timing the animation and the menacing sound.

Enter this code in the draw method in the place indicated by the comment.

Now we can run the game and see the invaders move from side to side getting lower all the time.

Space Invaders with the player ship and the invaders drawn to the screen

Space Invaders with the player ship and the invaders drawn to the screen

At the moment, however, they are not waving their arms or sounding very menacing. We will fix this now.

Timing the animation and the menacing sound

Implement playing the uh-oh sound by adding this code right at the very end (inside the closing curly brace) of the run method. This will also trigger the invaders to start waving their hands. The code simply alternates the value of uhOrOh based on an ever-decreasing (and therefore more frequent) value of menaceInterval.

Initialize the menacing variable in the prepareLevel method

You can now play the game and the menacing sound and invader arm waving will speed up with every trip across the screen. Notice that the invaders will only fire ten bullets and the player just one before no more can be shot. We will shortly do some collision detection and reset the bullets at appropriate events to fix this.

Before we do let’s build the player some destructible shelters.

Implementing the DefenceBrick class.

The DefenceBrick class is really simple. It has a RectF and a  isVisible boolean variable. In the constructor the width and height are initialized based on the screen resolution as are all our other game objects. We also declare and initialize a brickPadding variable to 1, a shelterPadding variable to one-ninth of the screen width, and a startHeight for the first brick of each shelter.

When we then initialize rect we combine these values with the row, column and shelterNumber to create the perfectly positioned brick within one of four shelters. Of course, another key to this code is how we call the DefenceBrick constructor. We will see that in a minute. Add this code to the DefenceBrick class.

Here we have some simple getters and setters for DefenceBrick which get the rect object set the object as invisible (for when it is destroyed) and get its current state of visibility. Add these three methods to the DefenceBrick class.

Now, as usual, we will add code to SpaceInvadersView bring our shelters to life. Note that we do not need any code in update because they do not move or think. We will see how we destroy a brick in update later on.

In the code below we have a triple nested for loop to loop through four shelters made up of 10 columns and five rows of DefenceBrick objects each.

Enter this code in the prepareLevel method in the place indicated by the comment.

Now we can just loop through the bricks array drawing any brick where getVisibility returns true.

Enter this code in the draw method in the place indicated by the comment.

Run the game and we see that graphically we are finished.

Space Invaders with shelters added

Space Invaders with shelters added

We just need to handle all the different collisions.

Collision detection

There are five separate collision events that we need to detect and respond to. We will handle them each individually but each block of code can be entered straight into the update method in the locations indicated by the comments.

Here we check if the player’s bullet has hit the top of the screen. If it has we call setInactive making it invisible and available for shooting again. The code then loops through all the bullets in invadersBullets doing exactly the same.
Enter the code we have just discussed in the update method at the place indicated by the comment.

In this next code, we check if the bullet is active, and if it is we loop through each of the invaders. For each invader that is visible, we use RectF.intersects to check for a collision with the player’s bullet. When a collision is detected the invader is made invisible, we play an explosion sound, set the bullet to inactive, and add ten to the score.
Enter the code we have just discussed in the update method at the place indicated by the comment.

Now we loop through every alien bullet in the invadersBullets array. We check if it is active and if it is we loop through each and every brick in the bricks array and for each visible brick we call RectF.intersects to detect if they have collided. If they have the bullet set to inactive, the brick is set to invisible and the sound effect indicating a shelter has been damaged is played. Note that each and every active bullet is checked against each and every visible brick. This is a significant amount of checks. We will discuss ways of improving on this in the next project.
Enter the code we have just discussed in the update method at the place indicated by the comment.

Here we do just the same as we did in the previous code block except we only check each brick against the player’s bullet. This is great for shooting a firing slit in the shelter.
Enter the code we have just discussed in the update method at the place indicated by the comment.

Now for the last block of code in the whole Space Invaders project. This code loops through each and every active bullet in the invadersBullets array and checks to see if it has hit the player. If it has a life it is deducted, a sound is played and the bullet is made inactive. Finally, a check is made in case the player has lost all their lives at which point the game is started again with a call to prepareLevel.
Enter the code we have just discussed in the update method at the place indicated by the comment.

Congratulations we are done!

The completed Space Invaders game running on an Android phone

The completed Space Invaders game running on an Android phone

Space Invader’s final thoughts

The next project will have a scrolling world. That is the entire game area will not be drawn to the screen at one time. This will introduce the concept of a viewport which defines what the player can see at any given frame of play. We can also use the viewport to clip objects that don’t need updating or collision checking which in turn makes our code faster. Take a look a the Android 2D scrolling shooter project.

There is also a project you might be interested in to introduce a class to handle internal animations so we can have multiple objects all doing their own cool animations; like the Space Invaders arm waving but with an unlimited and dynamic number of frames.

Please leave any comments below. Thanks and happy coding.

patreon