3: Main screen, moving objects and controls

Prerequisites
To make this project you must have first wired together the display and ESP32, see this article.

The Code
The full code for this articles Frogger is available below, click to download

Frogger Part 3

Adding the program to the Arduino IDE
Unlike Space Invaders where the full code was in one file Frogger is more complex and consists of several files that separate out key areas of game functionality. Open up the zip folder you just download and copy the folder within to your Sketch Folder, if you are not sure where this is (it’s where all your programs are) then click “File->Preferences” in your Arduino software and at the top you will see it has an entry for “Sketchbook location”. This is where all your projects are stored. Simply copy the folder in the zip file to this location.

You should then be able to go to “File->Open”, you will see the folder “Frogger”, open this and you will see the Arduino file within called “Frogger.ino” (you may not see the “.ino” extension depending on your settings). Double click this file and your screen should look something like below (click to enlarge);

You should see several Tabs across the top showing all the files of the game. I will be referring to these during this article.

Possible Compile Error

Frogger has to use the screen buffer functionality of the XTronical ST7735 driver, if you do not enable it you will get this error.

error: ‘class Adafruit_ST7735’ has no member named ‘displayBuffer’

This is because by default the screen buffer is turned off so that as standard compatibility is maintained from previous versions so that existing program code with small memory MCU’s is not broken. You need to purposely enable the screen buffer. To do this open up the file “XTronical_ST7735.h” in a text editor of your choice (I use the excellent NotePad++). This file will be within the “XTronical-ST7735-Library” folder which is within the Arduino Library folder (see this guide to locate it if your not sure). Un-comment the line that reads //#define SCREEN_BUFFER so it just reads #define SCREEN_BUFFER. Save and close this file. You will now be able to compile the example and upload it. You should have an output the same as below

In this Article
Tasks in this article are to draw the main screen,move the objects (logs, cars etc.) and add some controls to move the player’s frog. This is not going to be a gaming programming tutorial, if it was then the articles would be very large and take an age to write. However I will highlight certain important aspects and techniques as we go along. In addition the source code is commented and along with the video tutorial (yet to be made at time of writing) you should be able to tweak the game to your own preferences and learn a lot by going through the documented code.

Flicker Free
If you’ve seen the demo (if not see the bottom of this page here) you’ll notice that the game runs smoothly flicker free. If you were involved in games development back in the late 70’s 80’s then you will realise that flickering graphics were a challenge to be overcome. As hardware developed this became less of a problem (but the issue of lag in gaming is ever present). And now as we return to using low cost MCUs to make our games the issue of flicker has returned, but why? They are immensely more power than the arcade hardware they are trying to copy. Well… in many ways they are orders of magnitude better than the hardware of the 80’s but not in one important aspect – graphics processing. In video games dedicated graphics chips/circuits were created to remove the burden of handling these from the main CPU (which ran at around 1-4Mhz -ish). In current MCUs there is no graphics support for working with displays etc. Understandably, they were never designed as games processing chips! So we have to use techniques that help us create flicker free graphics, how that was achieved is explained here, albeit for the ESP8266 MCU, but that doesn’t matter as the principle is exactly the same.

The main loop
If you followed Space Invaders we had a main loop that looked a lot like this one in the “Frogger” file (first tab).

All that happens here is we do the game logic/rules “Physics()” and then update the display “UpdateDisplay()“.  There is no code for the attract screen yet and the boolean Frogger.GameInPlay has been set to true earlier so that the display will appear and not the none existent attract screen. The Frogger.TimeLeft variable is just some test code to ensure the timer bar was drawing correctly.

OOPs
OK, so Space Invaders was written in a traditional procedural way unless I had to call routines in libraries that used Object Orientated Programming (OOP). But for larger more complex projects I prefer using OOP and it is mostly recommended for most projects small or large. As mentioned this is not a programming tutorial so I won’t be teaching any OOP in these articles but just highlighting some parts of the code as we go along. But first a confession, I’ve coded professionally in OOP and none OOP for for many years but have never programmed in OOP “C” (or proper C++ to be precise). I’ve used C++ but always defaulted to using it in a more procedural fashion. So this is a bit of a learning curve for me as well and hopefully I won’t make in big mistakes along the way!

The Frogger Class
As noted in the main loop the Boolean variable Frogger.GameInPlay is set if a game is currently in play. This variable is within the Frogger_Class which itself is defined in Frogger.h. We create an instance of this class (just like creating a variable) at line 29 of the main Frogger File (Frogger.cpp);

Frogger_Class Frogger;

The Frogger_Class contains all sorts of useful information about the game itself, have a look at it and see what else it contains.

Class Naming Conventions
My personal preference is to always end a class definition with “_Class”, this is often because I want to use the prefix part of the class name, in this case Frogger as a variable name (in fact I do this very often) and this just stops a conflict. If the class was just called “Frogger” then I couldn’t have a variable called Frogger either, i.e. I couldn’t have this line as it would be invalid

Frogger Frogger;

In addition I always find my code such more easier to read with the “_Class” postfix.

Frogger_Class Frogger;

to me this clearly states I’ve a object called Frogger which is of the type Frogger_Class. But this is just my personal preference and I’ve not really seen anyone else use a similar method over the years, perhaps I’m just weird!

 

Creating/Drawing the main screen
The function UpdateDisplay draws the mains screen and all objects of the game. The graphics were all converted from the original arcade version and this was a right pain to be honest! All graphics had to be halved in resolution and needed tweaking by myself, it took time and was boring! In the future it is unlikely I would take this approach again and would go for a higher resolution screen that can display the graphics natively.

Moving Objects
The Physics function handles user input and game logic. Which at present is mostly just moving the traffic etc. and checking for user input.

 

The Files

Frogger.cpp and Frogger.h
These contain most of the game logic and display code.

GraphicsData.h
This file has all the definitions for the graphics, all in Hex. They were created by taking the original graphic, halving its size in an art package (I used Fireworks but any would do). Tweaking it if it didn’t look right (which none of them did!), using this websites conversion utility to convert the graphics for this kind of display. Then pasting the resultant data from the utility into the GraphicsData.h file.

Graphics.cpp and Graphics.h
These have the class definitions and code for all objects that can move (including the players frog).

Levels.cpp and Levels.h
Contain all the data about the levels, there are five main levels in Frogger where speeds and number of vehicles etc. vary.  Here for example is the code from the initialisation of level 1

Each line consists of the data to define the objects positions and then on the same line (as it aids readability) we call a routine to create those objects. The decimal parameter (parameter 3 for vehicles and 2 for logs and turtles) sets the speed and direction of movement. With negative numbers meaning the object moves to the left. Changing this affects how fast those objects travel. These values were arrived at by timing the time it took for those objects to travel across the screen on the original arcade game.

 

Getting Some Control
You may notice on the screen that we have a Frog being displayed at the bottom ready to go and in fact the code is in place to move the little fella, you just need to add some control buttons to the circuit. Now, originally I wanted a small joystick for this as a joystick was used in the arcade version, but I could not find a supplier of these anywhere, yet you see them on small games for sale in shops and online. If anyone knows where to get one I’d be grateful to know. So I had to go for a classic D-Pad which I knocked up from tactile buttons on a perf-board. The circuit diagram is shown below;

I built this circuit onto perf-board in the classic D-Pad arrangement. Note that I have added player 1 and player 2 buttons even though I do not intend to have a 2 player option. This is because it’s not cooperative play, it was just taking turns in the arcade. So you may as well finish a game then hand it to a friend if they want a go!  But I’ve implemented both buttons in case I want to make use of them later in this project or in re-using the D-Pad in another project. Here’s a couple pics of the D-Pad that I built.

There is a pin header at the top for plugging into a breadboard if required but I added DuPont cables to make it easier to control the game at a distance from the breadboard. Build something similar and plug the wires into these GPIO connections on the main board (taken from Frogger.h file)

You should then be able to move you frog  around by the amount that the original game did. However it is not yet animated so looks a little “clunky.” There is also no collision detection or checks for moving off screen. That’s all for now, click below for the next article.

Previous Episode (Connecting the display)         Next Episode (Collision Detection)