I have for some time wanted to (re)write some of the computer games from my younger days as an exercise in programming and for a bit of fun. I recently decided to do this on a very low-res display made from individual LED matrix modules and in the process created a new library to manage the LED panel display.
Making the Display
One of the characteristics of the ‘retro’ computer games was that screen resolution was exceptionally low.
The display is made up from five 4×1 MAX7219 LED matrix modules commonly available online, shown on the left.
To create the display, the modules are stacked so that the DATA IN on the right and snakes back to the right at the end of each row, as shown in the figure and photo below (also described in this previous blog post). Note that the only wiring that actually follows the zig-zag pattern is the DATA OUT to DATA IN. The other signals can all be connected in parallel (in the photo each row is in parallel).
To create a more finished look I then made a frame and stand from plywood, MDF, dowel and acrylic plastic scraps from my woodshop. The final product was a LED matrix display with 40×32 pixel resolution. After running some tests, the power requirement with all LEDs on is in excess of 1A, so the Arduino/USB power supply definitely needs to be replaced with a more capable external supply.
A New Library
I had planned on adding graphics routines to the MD_MAX72xx library to run the 2D matrix, but it quickly became clear that implementing new graphics primitives in this library was the wrong approach. It made more sense to move the few existing graphics functions out of MD_MAX72xx to create the kernel of a new overlay library for a panel of modules.
So the MD_MAXPanel library was born to manage x×y matrix panels. The library enables control of individual LEDs using cartesian coordinates and provides graphics functions for lines, triangles, rectangles, circles and text. The display can also be rotated 90° (for example, from portrait to landscape mode) and a built-in method will automatically adjust the X and Y coordinates.
In both modes, the (0,0) coordinate for the panel is always in the lowest left hand corner. X and Y coordinates increase to the right and upwards respectively. In cartesian terms, the display is located in the first quadrant (shown with the tick-marked axes in the figure on the right).
Fun and Games
With the screen and the start of the library library sorted I moved on to coding a few games I remember playing in ‘my youth’ (a long time ago now!) –
- Pong – tennis or ping-pong type game with a bouncing ball. This was the easiest ‘bat and ball’ game to code and provided the template for many of the other games.
- Bricks – similar to Breakout, where walls of bricks are destroyed by a bouncing ball.
- Snake – the classic game.
- Meteor – similar to Asteroids where bullets break up the meteor as it descends towards the shooter. The ‘shooter’ is similar to the Bricks bat although the logic for eliminating bricks was somewhat complicated.
- Tetris – another classic. This could be a complicated game but my implementation was greatly simplified by a video found on YouTube, referenced in the sketch.
- TicTacToe – simple kids game. This was a further test of using the MD_TicTacToe library for game logic with a new user interface. See this previous blog post.
To provide the same look and feel for all the games, I made a few early design decisions:
- The top row of LED matrix modules would display the score, with the remainder of the screen showing the playing field.
- Re-use code wherever possible. In the end the classes for scoring and sound were identical across all the games, and a function for creating a ‘random’ seed from analog input noise was re-used several times.
- Sound feedback was going to be the same primitive ‘bips’ and ‘bops’ of those early games. This also made the project simpler as the the standard Tone library and a cheap piezo speaker were sufficient.
- Standard tact switches would be the user interface. Most games need a subset of Left, Right, Up, and Down (LRUD). I also decided to include Select and Enter (SE) switches. This allowed me to make the very simple ‘game controller’ in the photo at right (click to enlarge) – basically 6 switches all connecting to ground when active.
- The games would work equally well in portrait or landscape mode just by changing the display mode (ie, no reprogramming). This meant being careful to use adaptable programming constructs rather than hard coding sizes and positions.
- The small display needed a small font, so I designed a 5×3 font which works well for the numbers displayed but is a bit ‘low res’ for text – readable but very primitive. For me this added to the retro feel for the games.
Even with such a low resolution, the games are fun to play and work well. The video below shows the library being used and features the games. All the applications in the video are part of the examples supplied with the library.
All in all, a fun little project with some good outcomes!