In one of my previous articles, I walked through the development of a retro-style handheld gaming console featuring local wireless multiplayer connectivity. This article will focus on upgrading that device using a 1.8-inch color LCD for animated graphics and an accelerometer module for motion control input.

For our upgraded hardware, we will program a simple Arduino-based fighting game using the ESP8266, in which two players on opposite sides of the screen battle each other until one of them loses all of their health points. Each character will be animated in 16-bit color and controllable by tilting and shaking that player’s respective console, as demonstrated in the following video.

Video demonstrating the motion-controlled retro handheld gaming console project.

Before building this project, you may want to review the first installment of this series to understand the basics of wireless communications using ESP-NOW, converting and playing MIDI files as background audio, collision detection within a video game, and how to upload code to an ESP8266 microcontroller.

Circuit Design and PCB Layout

Figure 1 is the Eagle schematic diagram for wiring the revamped version of our retro handheld.

Circuit schematic for the retro gaming console with LCD screen

Figure 1. Circuit schematic for the retro gaming console with LCD screen. [click to enlarge]

The PCB design for the upgraded console did not have to change since I intentionally left room for expansion, including pin headers for the larger SPI display and an I2C sensor module (Figure 2). However, as with most of my projects, everything covered today is entirely breadboard and perfboard friendly.

Layout of the PCB for the retro gaming console

Figure 2. Layout of the PCB for the retro gaming console. [click to enlarge]

I have made the Eagle schematic and board files available for download.

Bill of Materials

The following table shows a bill of materials for building one device. Remember that you will need two game consoles for wireless multiplayer gameplay.

Table 1. Bill of materials (BOM) for upgraded gaming console project
Part Quantity Notes
LOLIN D1 Mini 1 Convenient ESP8266 development board.
ATtiny85/45 1 Microcontroller for playing music.
1.8-inch TFT LCD 1  
Buzzers 2 One for music, one for sounds.
10 kΩ resistors 2 Pull-ups on the I2C bus.
330 Ω resistors 2 Current limiters for the buzzers.
Dip switch (2 positions) 1 For muting buzzers.
On/Off Switch 1 For power.
Male and female headers   For connecting display, dev board and power.
AAA or AA batteries 4 AAA would be more compact.
Battery holder for 4 AAA or AA batteries 1 You can hide two AAA holders connected in series behind the PCB.
Custom PCB, Breadboard, or Perfboard   Select one of the three options.

Color Display and Graphics Library

The display is a 1.8-inch 128×160 pixel TFT LCD with a built-in ST7735S SPI driver IC. It uses a 16-bit color format called RGB565 which means that we can potentially display up to 65K colors. You will find that different versions of this display offer varying pin arrangements, so ensure you wire yours up correctly. If you are replicating my custom PCB, you will need to revise it to support the different pinouts.

For this project, we’re going to use Bodmer’s TFT_eSPI graphics library, which is specifically designed to display dynamic images on 32-bit microcontrollers like the ESP8266. These types of images are called sprites and are stored within the processor’s RAM memory. They can be manipulated in various manners and integrated in front of or behind larger 2D scenes. One color of a sprite is always specified as transparent making it easy to overlay them on top of other images.

View of the retro game console with game screen including player characters

Figure 3. Player characters on the screen are implemented using sprites.

All of the sprites used in this project are modified versions of Free Tiny Hero Sprites assets from itch.io. You can always replace them with your own art or other graphics from the internet following the same logic within my code.

Game Scene

The scene in our game is split into three parts:

  • Background.
  • Battle area.
  • HUD (heads-up display).

For the background, I chose a gradient that begins with white on the bottom and transitions to a different secondary color at the top. At startup, the secondary color gets selected randomly from a couple of colors that I thought went well with the assets on top.

Our battle area, or the middle of the display, is where the players will be fighting. One player will spawn on the left side, while the other will spawn on the right. There are three characters in total, and once again, whenever the game starts, it assigns each player one of the characters at random without repetitions.

The HUD is located at the top and the bottom of the display, showing each player’s health points (HP) using a green status bar that gets decremented as that player loses their HP. Next to the status bars, there are framed images depicting the players’ characters and identifiers (Player 1 or Player 2).

Animating the Sprites

To achieve the effect of motion, whenever a player performs an action, instead of showing a still image, we’re going to very quickly scroll through a range of images tied to that particular action, giving the illusion that our character is smoothly and dynamically moving on the screen, similar to how cartoons or conventional video games work.

These images are the sprite assets that I’ve converted into Arduino code using the image to RGB565 tool from Rinky-Dink Electronics, organized in a pointer array, making it easy to iterate through when rendering an action.

For this game, the actions are defined as idling (staying in place and breathing), walking (a gait pattern), and punching (slinging an arm toward the opponent). Each action has only a couple of images that get activated based on a game counter variable that increments whenever our Arduino loop cycles.

Motion Sensing With the Accelerometer

Finally, we need to give the users a way to control their character. We’ll use an MPU6050 accelerometer/gyroscope module, along with Refetick’s MPU6050_light.h library. This library offers a lightweight, fast, and simple communication method with an MPU6050 chip.

In this project, I’ve attached the sensor perpendicular to the PCB, allowing us to use the X-axis tilt-angle readout to move a character left or right whenever the whole console is tilted in either direction. Additionally, similar to my e-ink Etch-A-Sketch project, using the acceleration readout from all three axes, I’ve implemented shake detection that corresponds to a punch action whenever a user shakes their console.

The tilt and shake ranges might vary depending on your particular MPU6050 module and its position. Keep in mind that you will have to tinker with different values before you can determine which sensitivity works best for your setup.

Uploading the Code

Now that we understand the logic behind this project, we need to upload the code to our ESP8266 microcontrollers. Like last time, I will use the Lolin D1 Mini boards, which have a convenient USB-to-serial programmer.

Before starting the upload, you will need to set up your Arduino environment with all relevant boards and libraries. We’ll use the same sketch for both host and client, differentiating them using only two lines of code. One line is a boolean variable called isHost (1 for host, 0 for client):

 bool isHost = 1; // change this variable, 1 is for host, 0 is for client

The second line is an array of the corresponding MAC address for the receiving node:

 uint8_t broadcastAddress[] = { 0x48, 0x3F, 0xDA, 0x4C, 0xEA, 0xDD };  // insert MAC address of the transmitting and receiving nodes

The code for the main program, audio, and MAC finder are available for download from GitHub.

Your Turn

Aside from the functionalities covered in this article and its previous iteration, I’ve also included a basic “connecting” screen that our console boots into, as well as a couple more sprites for actions such as blocking and ducking, which you can implement in your version of the project.

How would you expand this project? What other hardware would you include? What types of games would you want to make?

In my previous article, a user suggested switching over to the ESP32, which offers more GPIO pins, potentially eliminating the need for an I/O expander, previously used as an 8-position tactile switch port. You can also add an MP3 player IC for longer and more complex snippets of background game music.

Thanks to the ESP hardware, you can even scale this project to connect to the global internet and interact with many more players as opposed to the localized functionalities of the ESP-NOW protocol.