Exploring Patterns and Planning the Platformer Project

This project is taken from a previous version of my book Learning Java by Building Android Games. The latest version, version 3 went into more detail in earlier projects and so this project did not fit. Some of what I say in this tutorial (and the next 3 tutorials) assume you have read one of the books but a determined beginner should be able to complete this project. I have been unwell for a few years and this tutorial should have been published in 2020. May I also bring to your attention my new books (and website) for getting started with crypto.

patreon

 

 

You can get the code and the graphical assets from Git Hub starting from the Chapter 22 folder onwards here. Chapters 22… refer to parts 1… etc of these articles.

Welcome to the start of the biggest project on my site. Over the next four long articles, we will build a platform game packed full of features like parallax effect scrolling, animated controllable characters, multiple different and challenging levels, and much more.

During this project, we will discover Java patterns like the Singleton, another Java data class, and the HashMap, and explore the gaming concepts of a controllable camera and an animator.

At the same time, we will reinforce all the Java concepts we have already learned including aiding our understanding of and improving upon the entity-component/factory patterns we used in the previous project.

Here is what we will do in part 1:

  • Discuss how we will build the Platformer project including design patterns, Camera class, level design files, graphics handling using the Singleton pattern, and a Transform class
  • Actually, get started coding the Platformer project
  • Specify all the game objects with ObjectSpec classes
  • Code the interfaces for the components that we will begin coding in the next tutorial
  • Code the communications interfaces like EngineController, GameEngineBroadcaster, and InputObserver

Be sure to read the next paragraph box. It is probably the most useful in the book.

Important

The first 2 articles of this project are long, and the classes are all interdependent with each other- they are parts of a system. The project is not executable until the end of Article 2. You can read and code articles 1 and 2 a step at a time if you like but it will take quite a while- make sure you have at least a day to spare. Alternatively, you could just read articles 1 and 2 and carefully review the code and the patterns to make sure you understand what is happening. Then you could simply add the graphics and sound (explained in this chapter), and create 2 packages (explained in part 2 specifying all the game objects with GameObjectSpec classes section and part 2 Create the levels section). Then you can just copy and paste all the class files from Chapter 2 folder of the download bundle into the proper package of your project (via the Android Studio project explorer window). You will then need to make sure/correct a few lines of text in a few files to do with importing your new packages and the first part of the engine can be working within an hour’s work- after having first read through parts 1 and 2 thoroughly.

Choose whichever method you find the most rewarding.

WARNING! If you don’t read the two articles first you won’t understand how to make the package import corrections, you won’t understand the structure of the code, and the code won’t work.

Now we can make a start. Let’s call the platformer, Bob was in a hurry.

Platform Game: Bob Was in A Hurry

This is the most advanced game on Game Code School. It has multiple levels and hundreds of game objects per level. The player must get from the start of the level, find and then reach the exit. The fastest times are kept as high scores for each of the three levels. However, there are also collectible coins scattered throughout the levels, and a time penalty is added to the finish time for each one left uncollected. Precise jumps are required, and the best route is not always obvious so a player wanting to do well will need to explore and experiment. The whole level is not visible on the screen all at once. The level can be dozens of times the size of the screen, so exploration is required to see the whole thing.

Let’s have a look at some screenshots to understand the game better.

B09770_22_01

In the previous image, you can see the home screen. The text labeled as number one is the fastest time for each of the three levels, Underground, Mountains, and Cave. Double tapping on the appropriate third of the screen will start the level and the timer.

Take a look at this next image taken from the Underground level.

B09770_22_02

The levels each have their own distinctive background to set them apart from each other and there is also a good selection of decorative objects, platform designs and obstacles for each level. We will see more of the graphics soon. In the previous image notice the following things:

  1. The time is in the top left-hand corner. The format is as follows: number of seconds taken so far + number of penalty seconds that can be removed by collecting all the coins.
  2. Number two highlights the collectible coins.
  3. Number three highlights an animated fire tile. The tile will flicker, making it obvious this tile is bad for the player’s health. The slightest touch will end the level and send the player back to the home screen.
  4. Number 4 is a Death tile. We need to stop the player from accidentally getting out of the level into an eternal fall. By surrounding possible exits with Death tiles, we can end the game when the player falls or gets themselves into an impossible position. The tiles use a distinctive graphic to make level design and debugging clearer. In the finished game, you would use a transparent (invisible) graphic or change it to something that matched the level.

This next image shows the Mountain level which is mainly a series of awkward jumps. The part highlighted in number 1 is the level destination. When the player reaches the highlighted game object the game goes back to the home screen and if they got a faster time it will be updated.

B09770_22_03

The next level shown below is the City level. I have borrowed the background from the previous project.

B09770_22_04

In the image, I have highlighted three rectangles. They are moving platforms. They go up and down a distance of 10 blocks. Once you see how to code them, it will be trivial to add horizontal movement or vary the distance they travel.

How we will build the game

By going through a few things in advance albeit not in great detail will give a clearer picture of how the project will eventually turn into a fully-fledged game by the end of  Part 4.

Level design files example

In all the previous projects we spawned objects like bats, balls, snakes, apples, aliens, bullets, and lasers based on logic in our code. With this game, we need a way to sit back a little and design each level. There are a few different ways we could have done this. We could draw the levels in a graphics application like Paint or Photoshop and then write code to turn a level design image into a game. Another option is to write an entire app that allows the user to select different game objects and then drag and drop them around the screen. The application could then save the design and use it in the game. I opted for the method to lay out the level designs in text, in Android Studio. In the designs, different, alpha-numeric characters would represent different game objects. This is visual and allows the game designer to create, test and tweak quite easily and is also quite simple to implement.

Take a look at this image of one of the level design files. Also, open the Chapter 23/Levels folder in the download bundle. Open the files and you can examine them more closely than the image allows.

I don’t provide the level files in the book because they are entirely impractical to try and present them on the page. Remember that the download bundle is free and quick to get hold of on the book’s page on the Packt website- in case you haven’t got it already.

B09770_22_05

This next image is a zoomed-out view of the game that the game engine translated the previous text file into.

B09770_22_06

The zoomed-out effect was achieved using the Camera class that we will explore soon.

We will look at the level designs and which letters/numbers to use in greater detail in the next chapter.

The graphics

Here is all the graphics provided for this project.

B09770_22_07

Notice the graphics we will use as tiles for the player to walk on (coal, concrete, scorched, snow, stone, turf). And look at the graphics that will be purely decorative (no collisions or interactions), dead_tree, lamppost, snowy_tree, stalactite, stalagmite, and the three backgrounds, city, mountain, and underground. There are also two obstacle graphics. Obstacles are things that don’t do anything but will need to be jumped over. These are cart and stone_pile. Notice the coin graphic which is the time-saving collectible. The graphic named platform is the moving platform mentioned earlier.

There are two graphics not mentioned so far. Look at a close-up of the player graphic.

B09770_22_08

The player graphic is a sprite sheet. It is a series of frames of animation. Only one of the representations of Bob is shown on screen at any given frame of the game. But our code will loop through them one at a time to create an animated walking effect. This will be controlled by a class called Animator.

Now have a look at the fire graphic which is also a sprite sheet and will create a flickering fire animation.

B09770_22_09

We have seen the graphics, we know how we will decide their layout although we haven’t seen any code yet but how will we decide which part of the game world should be on the player’s screen at any given frame?

Cameras and the real world

The answer to the question is a special class that can be thought of as the camera which is recording the gameplay. Look at the next image.

B09770_22_10

The image is a mock-up made in a simple graphics package that attempts to illustrate the camera in action. We can think of most of the game world existing off-screen and unseen and just the relevant portion being shown on-screen.

In the previous project, the player’s ship sat in the middle of the screen and the way we made it look like the ship was moving was a bit of a bodged job. The scrolling background did most of the work but the various …AlienMovementComponent based classes helped too. They took account of the direction the player was facing/flying and moderated (sped up or slowed down) their movement towards or away from the player accordingly. There is a better way.

In this project, all the game objects will have world coordinates. The coordinates held by each of the objects will have no connection to pixels on the screen. It could be simpler if you think about these coordinates as virtual meters. In fact, Bob is 2 units tall which is about the height of a not untypical human. Each and every piece of platform, scenery, collectible, Bob, and even the background will have a position in the game world as well as a width and height (also in virtual meters) and not know anything about the screen resolution.

Whenever we move an object we will do so in virtual metres. Whenever we do collision detection we will do so in virtual metres. The virtual meter coordinates can still be held in a RectF and the width and height (in virtual meters) can still be held in a PointF. However, when the objects are drawn to the screen the Camera class will calculate whereabouts- if at all they get drawn. The camera will follow the player so as Bob moves around, and his virtual meters-based coordinates change the camera will reposition on-screen the objects drawn around him creating the illusion of moving through the game world.

We get to see the code for this in the next chapter and it is surprisingly straightforward.

The slightly modified ObjectSpec

In the previous project, because of the lack of a camera, we had slightly ambiguous values for width, height, and speed. We used relative values that would cause them to scale to the screen size on the device it was running on. In this project, because we have the Camera we can use our new virtual meters. This will make the ObjectSpec class (which all the specification classes drive from) much clearer. We will see this class and code all the specification classes for the entire project, later this chapter.

New improved transform hierarchy

Also, in this project, we will write better code for the Transform of the game objects. We crammed way too much into the Transform class of the Scrolling Shooter project. It was a bad design, but it served the purpose of getting the project done without getting any bigger.

If the Scrolling Shooter project was an ongoing thing that was going to be extended it would be worth re-writing the Transform class and using a Camera class as well.

For the Platformer project, we will have a base/parent Transform class that has much less data in it and suits just the simple game objects like platforms and decorations and we will extend this class to create a BackgroundTransform and PlayerTransform with much more specific methods and data but also still allowing access to the base class’s data and methods.

We will code the Transform class in the next chapter and the two extended classes across the rest of the project.

Project patterns

The Entity-Component pattern will be used for every game object in this project just as it was in the previous one. We will not need any spawn-related component classes, however, because starting positions will be determined by the level layout files and none of the objects need to respawn (as the aliens and lasers did).

We will still need a component class that handles what happens during the update phase of the game loop but as many of the objects don’t move we will have an UpdateComponent interface instead of a MovementComponent interface. Same job with a new name.

We will still have a GraphicsComponent interface as we did in Scrolling Shooter. We will code these interfaces after we have coded the specification classes later in this chapter.

We will still need to communicate from the GameState class to the GameEngine and will again have an EngineController interface to achieve this. Furthermore, we will use the Observer pattern in the exact same way as before to handle communicating the user’s input with the classes that need to know about it.

We will also still be using a GameEngineFactory class to construct GameObject instances using component classes based on the various specification classes. This time the class will need to be a bit smarter to make sure each GameObject instance gets the correct type of Transform. Otherwise, this class will be very familiar. As already stated we will code all the specifications in a minute but the components themselves will take shape over the rest of the project.

BitmapStore

In this project, some of the levels will have hundreds of game objects. In all the previous projects the game object classes held a copy of the required bitmap. In the Snake game we drew lots of body segments and this was OK because the Snake class reused the body graphic over and over. The platforms, however, will only know about themselves, not all the other platforms. This implies that if there is a platform that is 100 tiles long we will need 100 game objects with 100 copies of the graphic. That is not only a waste of memory and processing power but might even cause older Android devices to crash because they have run out of memory. In the next chapter, we will code a BitmapStore class whose only job is to store and share bitmaps. Therefore, if there is a length of the platform in the game that is 1000 blocks wide if they are all the same object, perhaps turf, then there will only be one copy of the bitmap.

Levels and LevelManager

In the previous project, we had the Level class. It defined which object types and how many of them were in the game. It used the GameObjectFactory class to construct the objects we wanted in the game. If we had wanted more divers and fewer chasers we would have made changes to Level. If we had invented a new type of alien or a smart bomb for the player, we would have added it to the Level class. Most games have more than one level and this platformer is no exception.

To handle this, we will create a Level class and then extend it to create specific levels called LevelCave, LevelMountain and LevelCity. These Level-based classes will hold all the details of the specific level of the game. We will then create a LevelManager class that will understand how to use the GameObjectFactory class to load the required level when prompted to do so by the GameState class which will work in a similar way to the previous project.

Getting started with Bob was in a hurry

Now we can make a start with the project. Remember that you can do this step by step. All the instructions that follow assume you are doing it step by step, but you could just read Chapter 22 and Chapter 23 and then refer back to the information box at the start of this chapter to do a super-quick copy & paste job to get the project to its first runnable state.

Final warning! The author recommends you don’t attempt to do the copy and paste job until you have thoroughly studied chapters 22 and 23 as there are key things you need to be aware of or the copy & paste won’t work.

Creating the project and adding the assets

Create a new project called Platformer with an empty Activity called GameActivity, no layout file and without backward compatibility; just as we have for every project in the book.

Grab the project’s graphics from the download bundle; they are in Chapter 22/drawable folder. Highlight the contents of this folder and copy them. Now right-click the drawable folder in the Android Studio solution explorer and select Paste.

Get the sound files from the download bundle in Chapter 22/assets folder. Copy the entire assets folder including the folder itself. Now, using your operating systems file browser navigate to the Platformer/app/src/main and paste the assets folder into your project.

As usual, we want to make the game full-screen and locked in landscape orientation. As a reminder, here is how to edit the AndroidManifest.xml file:

  1. Make sure the xml file is open in the editor window.
  2. In the xml file, locate the following line of code: android:name=”.GameActivity”>
  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 GameActivity 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.

 

Specifying all the game objects with GameObjectSpec classes

In the previous project, the folder with all our class files was getting a bit crowded. This project will have even more classes, so we will help ourselves a little by separating things out into different packages. We will have a folder(package) for all the GameObjectSpec related classes and a folder for all the Level-related classes. Everything else will remain in the usual folder.

When you create a new package, it is important to do so in the correct folder. The correct folder is the same one that we have been putting all the Java files in throughout this book. If you call this project Platformer it will be the app/java/yourdomain.platformer folder.

In the Android Studio solution explorer, right-click the app/java/yourdomain.platformer (NOT yourdomain.platformer(androidTest) and NOT yourdomain.platformer(test)), select New | Package and  name it GOSpec.

We will now add a whole bunch of classes that will define all the objects of the game; their sizes, tags (for collision detection mainly), speed, starting location, associated graphic file, frames of animation and a list of components that define their behavior.

There is one parent class, GameObjectSpec from which all the other specification classes extend. There are lots of them, 23 in total and I don’t recommend you sit there and type them all in. They can all be found in the download bundle in the Chapter 22/java/GOSpec folder. You can highlight all the files, copy them and then right-click and Paste them all into the GOSpec folder/package you just created. What you might need to do manually is click into them and check that the package declaration at the top of each file was correctly auto-adjusted from my package name to yours.

If you used Platformer as the project title your package name should be:

package yourdomain.platformer.GOSpec;

If you check three or four files and the package was auto-adjusted correctly then chances are good that they all were, and you don’t need to check all 23.

While the specification classes are very similar, I thought it still advantageous to show all the code because they are worth examining. Flick through the next few pages of specification classes. When you look at them take note of the different sizes, speeds, graphics files, frames of animation, and especially the different component names in the components array. Here is the complete listing from all the specification classes with a few notes on each.

In a professionally built game, it would be more typical to load such things from text files with a single line of text per component or attribute. If you want to upgrade your project (wait until you have it all working in Chapter 25 first) you can read about parsing a text file using a simple Web search. However, sorting the required data from the text file is an in-depth process (but not beyond a determined beginner). A simple Web search will provide a good example code to get started. By doing things this way we keep all our work inside Android Studio and get to play with making our own packages.

The following list of 23 classes appears in the same order they will appear in Android Studio with the exception that I present the base/parent class to the other 22 classes first to aid understanding.

GameObjectSpec

This is the class that all the …Spec classes will extend. It provides a related member variable/object instance for each of the specifications a game object can have.

 

The main method (the constructor) has the job of receiving the specifications from all the child classes and copying the values to the member variables/instances. Our code will then be able to handle instances of GameObjectSpec regardless of what the actual game object is; animated, controllable player through to dumb, unmovable tree.

All the other methods of this class are simple getter methods that the various parts of our program can call to find out more about the game object.

BackgroundCitySpec

Review the code for this class and then we can talk about it.

I will spend more time reviewing this game object because it is the first one we are looking at. In the remaining 22 I will just point out the occasional distinctive feature. It is still important, however, to glance at and make a mental note of the different specifications of the game objects.

 

The tag is mainly used by the collision detection code we will write in Chapter 25. Even the background which doesn’t collide needs to be identified so that we can discount it from collision detection.

The bitmapName variable holds the name of the graphics file that is used to represent this game object.

The framesOfAnimation variable is set to 1 because this is not a sprite sheet. The player object on the other hand will be set to 5 because that’s how many frames there are and the fire object’s framesOfAnimation will be set to 3.

The speed variable in this project is different from that in the previous project because it is the speed in virtual meters per second rather than some convoluted measure relative to the player as it was in the last. Now we are making the jump to game-world-based coordinates using a camera we can use these more real-world-based size and speed measures.

Next up is size and you can consider the city to be 100 meters by 70 meters. When we code the Camera class in the next chapter we will see how these virtual meters translate to pixels and how we know which parts to show on the screen of the game at any given frame.

We also have a String array for a list of components just like we did in the previous project. The actual components themselves, however, will be different to the previous project.

The exception to this is this object, the background, which has very similar components.

Notice the two actual components we will need to code to bring this game object to life:

BackgroundGraphicsComponent

BackgroundUpdateComponent

 

Finally, notice the constructor that does nothing other than pass all the specifications into the parent class constructor which as we saw stashes the values away in the appropriate variables.

BackgroundMountainSpec

This is the same as the previous except it uses a different graphic, mountain.png.

 

BackgroundUndergroundSpec

This is the same as the previous except it uses a different graphic.

 

Review the specifications and move on.

BrickTileSpec

This is a regular platform tile. Bob will be able to walk on it, so we will need to perform collision detection on it. Its position in the game world never changes so it is technically inanimate. Note though that the relative position of the block on the screen to the camera will change and the brick graphic will need to be drawn accordingly but the Camera class will take care of all of that.

 

Finally, notice the size is just one virtual meter wide and high.

CartTileSpec

This specification has the same components as the previous one but note we can assign any value for the size we like. This mine cart object is two meters by one meter. The graphic must of course be drawn to suit the size otherwise it will appear squashed or stretched.

 

Review the specifications and move on.

CoalTileSpec

Just another walkable tile.

 

Review the specifications and move on.

CollectibleObjectSpec

Although this next object has quite a different use to say the brick object, notice that everything is the same apart from the graphic file and the tag. This is fine.

 

We can detect a collision and determine that it is a collectible item from its tag and then handle what should happen.

ConcreteTileSpec

Just another walkable tile.

 

Review the specifications and move on.

DeadTreeTileSpec

This tile has minor differences to those we have seen so far. Firstly, it is quite large 2 metres by 4 metres. It also uses a DecorativeBlockUpdateComponent instead of an InanimateBlockUpdateComponent. The differences between these components in code is small but useful. As trees are just decoration in the background we will not bother to add or update a collider thus saving a few computation cycles per tree, per frame.

 

Review the code and move on.

FireTileSpec

This is the first component we have seen that has more than one frame of animation. Our code will detect that an Animator object needs to be assigned to this game object and will manage a simple flickering effect on the fire tile using the frames from the sprite sheet fire.png.

 

Also, notice that the AnimatedGraphicsComponent is used instead of the InanimateBlockGraphicsComponent.

GrassTileSpec

This is another walkable tile.

 

Review the code and move on.

This next spec is for the blocks that will cause the player to instantly die and end the game. It helps the level designer prevent embarrassing bugs like falling out of the game world.

LamppostTileSpec

This is the same as the tree that we discussed previously except for the size and the graphic. Review the specifications and move on.

 

Review the code and move on.

MoveablePlatformSpec

This game object is new. Notice the MovableBlockUpdateComponent. We will code these to make these platforms move in the game world allowing the player to jump on them and be transported up and down.

 

Note that we can still use a regular InanimateBlockGraphicsComponent. Just in case it is causing confusion, inanimate refers to the fact it doesn’t use a sprite sheet (has no frames of animation), we can still change its location in the game world (move it) via the MoveableBlockUpdateComponent.

ObjectiveTileSpec

The objective game object is an important game object because it triggers the player to reach the end of the level. However, as with the collectible object all the significant functionality can be handled by the PhysicsEngine via its unique tag, and no new components or features are needed for this game object’s specification.

 

PlayerSpec

This is perhaps unsurprisingly our most advanced game object. It has an AnimatedGraphicsComponent just as the fire tile does so that it sprite sheet graphic is used to animate its appearance. It also has a specific PlayerUpdateComponent that will be much more advanced than all the other …Update… components. It will handle things like moving, jumping and falling. The PlayerInputComponent will communicate with the GameEngine class to receive and translate the players screen touches. The communication method will use the same Observer pattern that we learnt for the previous project.

 

Review the code and move on.

ScorchedTileSpec

Another simple walkable object.

 

Review the specifications and move on.

SnowTileSpec

Another simple walkable object.

 

Review the specifications and move on.

SnowyTreeTileSpec

Just like the dead tree but lusher and covered in snow.

 

Review the specifications and move on.

StalactiteTileSpec

This is another purely decorative game object.

 

Review the specifications and move on.

StalagmiteTileSpec

This is another purely decorative object.

 

Review the specifications and move on.

StonePileTileSpec

A pile of stones the player can jump on.

 

Review the specifications and move on.

Summary of component classes

Looking at the components you will notice the three main types each has. We will therefore need a graphics, update and input related interface. We will code them now. Throughout the rest of this project we will then code the classes that implement these interfaces and match the component classes we just saw in the GameObjectSpec related classes.

Coding the component interfaces

Now we will code an interface to suit each of the components that will make up all the different game objects we have just coded the specifications for. We will not code a different interface for each different component type, rather we will code generic types that relate to them all. Allowing all the different types of update and graphics components to be used polymorphically in our code – as we did in the previous project.

Therefore, we will need an update component interface and a graphics component interface.

You can use copy & paste as you did in the previous section, just be sure to examine the code and understand it to avoid confusion later in the project.

Let’s start with the graphics component.

GraphicsComponent

All graphics components will need to be able to do two things. This means they will need two methods. Note that the implementation of the actual components that implement these interfaces are free to add more methods- and some will. But they will be required to implement the required methods of the interface as a minimum.

Review and add the interface to your project.

 

Any component that implements this interface will have to add an implementation for its two methods. Therefore, all the graphics related components will implement this interface we can then be sure that we can just call intitialize and draw on any game object and be confident that they will handle initializing and drawing themselves in a manner appropriate to them.

There are still some errors due to missing classes. These include Camera and Transform. Don’t try and auto-import them because we need to code them first. If you try and auto-import them, you might end up with Android classes that are different from the one that we want. All the classes you need to import at this stage are included in the code listing. Especially take note that we are importing our very own package for the first time. In the listing see this line of code highlighted.

import com.gamecodeschool.platformer.GOSpec.GameObjectSpec;

You will need to adjust this if you used a different domain name to com.gamecodeschool.

UpdateComponent

In the previous project, we had several different …Movement… related component classes and we coded a MovementComponent interface. The update method of GameObject is then called move on each of the appropriate movement-related components. This interface is essential for the same job but as our objects are more diverse using UpdateComponent as the name seemed to make sense. After all trees and platforms aren’t technically moving. Add the UpdateComponent.

 

Every single object will have one of these and get called on each frame of the game.

The player’s transform could have been left out of the argument list of the update method because it is only needed by the background (to see which way the player is moving). However, if we added enemies later they would likely need to know where the player is and what he is doing. So, I left it in rather than create another communication interface between the background and the player.

Coding the other interfaces

There are three more interfaces that we need to code. They are for communications between specific classes of the game. We need the GameState class to be able to trigger a new level via the GameEngine class and we will code the EngineController interface for that.

We will need the GameEngine class to broadcast to multiple input-related classes whenever the player interacts with the screen and we will need these input-related classes to register themselves as observers just as we did in the previous project. For this, we will code the GameEngineBroadcaster interface and the InputObserver interface.

Let’s quickly add them now.

EngineController

Add the EngineController interface as shown next.

 

In the next chapter we will make GameEngine implement this interface as well as pass a reference to GameState. GameState will then be able to call the startNewLevel method.

GameEngineBroadcaster

Add the code for the GameEngineBroadcaster interface.

 

This is the first step in wiring up the GameEngine to the classes that need to be able to handle input. Classes that receive a reference to this interface will be able to call the addObserver method and receive all the details of the player’s screen interaction. We will make GameEngine implement this interface in the next chapter.

InputObserver

Add the code for the InputObserver interface as shown next.

 

Each of the classes that handle input will implement this interface and the required method (handleInput). They will also share an InputObserver reference via the addObserver method and our control system will be all set up and ready to go. We will do these final steps during the next chapter.

Summary

There was a lot of talk and theory in this chapter but hopefully it has set us up ready to make fast progress in the next. There was no runnable code in this chapter but in the next we will have a home screen with high scores and even be able to tap the screen to choose a level and see the beginnings of each of the playable levels.

patreon