Video games provide a great opportunity to program something that you can enjoy. And they can also teach you the fundamentals you need to be a good programmer. This article explores a DIY handheld Arduino video game project to get you started.
What Are We Making and Why?
Before diving into the guide part of this article, it makes sense to explore what we are making and why we have chosen it for this project. Several challenges come with making games for devices like Arduinos.
Storage Space: Most Arduino boards come with very little RAM or flash memory. Not only does this place a limit on the amount of code they can run, but it also presents challenges when it comes to working with variables. Processing Power: The Arduino we used has a low-power CPU, so it’s impossible to create resource-hungry applications for it. Limited Components: Arduinos have a lot of pins available, but many components need more than one. This limits us when it comes to controls and display outputs.
With these challenges in mind, we decided to create a handheld device that runs a very simple reaction-based game. You could easily make other games for the hardware we’re working with, and we encourage you to be creative.
The game itself is very simple. Three blocks appear on the screen, two outlined and one filled, each with a corresponding physical button below. The player has to press the right button each round to continue playing, and if they press the wrong button or run out of time the game is over. Each successful button press awards points. The game slowly raises its difficulty by reducing the reaction time available.
Wiring the OLED Display, Arduino, and Buttons
Wiring up your handheld game is the first step in this process. As you can see in the circuit diagram above, you don’t have to make many connections to get started, and you can even use a breadboard for this project.
We have already published a guide to help you to wire push buttons to an Arduino. Our Arduino Aquarium Monitor project shows you how to use an OLED display with a microcontroller like this. As such, we will be focusing on the code for this project for the rest of this article.
Arduino Handheld Game Code
Proper formatting and tidy file structures are very important to novice and veteran programmers alike. You will thank yourself for taking the time to organize your code neatly if you ever have to go back through it.
The code uses a main INO file to form the foundation of our project. There’s also a C++ file to control our display, a C++ file to run the main game code, and an Arduino library file to connect it all together.
We will dive deeper into this code below, but we encourage you to take a look through the commented code in our Arduino Handheld Game project on GitHub. It will help you to refer to it alongside this article.
The Library File (library.h)
Our library file serves a crucial role, connecting our other project files together so that they can work as a single application. This file contains declarations to include the Arduino.h library and all the functions within our game code that need to work between our files. Without this, our code simply wouldn’t work.
The Main INO File (main.ino)
Like many Arduino projects, this one started with the default template provided by the Arduino IDE. That template gives it setup and loop functions that we use to call functions in our other files. This file also has a declaration to include the library.h file.
The setup function is ideal for initializing our display and buttons, as it only runs once when the Arduino is reset or powered on. For this, we call the disSetup() function in our display file and the butSetup() function in our game file.
Our loop() function is even simpler than the setup() function, with just a single call to the gameState() function found in our game file. We will explore this in greater detail later in the article.
The Display Code File (display.cpp)
We are using an SSD1306 OLED display for this project, though you can use a different type of display if you edit the code accordingly. This file starts with the inclusion of the library file, library.h. It then includes declarations for the SPI, Wire, Adafruit_GX, and Adafruit_SSD1306 libraries. Following that, it defines some constants to provide settings for the display.
The first function, disSetup, initializes the display and shows a logo splash screen. It then clears the display after waiting approximately 2 seconds. Our main file, main.ino, calls disSetup in its setup function.
The rest of the functions in this file, except for timerBar(), form the different screens seen throughout the game. The game file, game.cpp, calls each of these functions.
startGame(): This function controls the first screen the player sees. It simply asks if they are ready while calling the switchInstance function found in the game file. startingGame(): Once the player starts the game, this screen shows a short countdown. It then changes the game’s state to match. inGame(): This is the most complex of our display functions, using three variables to load each round of the game. It starts with an if statement that determines which of the three tiles to fill, followed by displaying the tiles and the player’s level and score. timerBar(): This function uses a variable to display a timer bar at the bottom of the screen. It shows the player how much time they have for each round. successScreen(): This is a simple function that displays a message each time the player successfully completes a round. endGame(): This final function displays a game over screen with the player’s score and the option to start the game again.
The Game Code File (game.cpp)
Finally, as the last file to explore, it’s time to look at the game code. This file, like the others, starts with the inclusion of the library.h file. It also contains a long list of different integer variables that we use during the game.
You will find the butSetup() function before anything else. The setup() function in our main file calls butSetup. This function uses variables to set up our buttons as inputs that we can read later on.
switchInstance(): This function switches between instances of the game, from the start screen to the game and game over screens. It receives a variable to tell it which game state to switch to. An if statement waits for a button press to start the game from the startGame() state. Another if statement starts the game again from the endGame() state. gameState(): This function sets the game difficulty based on the player’s score and calls the right function depending on the state of the game. It starts with a series of if statements that set variables based on the player’s score, followed by more if statements to check the current instance. tileSelector(): This function generates a random number between 0 and 2 that tells the game which of the three tiles to fill at any given time. theGame(): This function is arguably the most important of all. It calls the tileSelector and inGame functions, picking a new tile and displaying it on the screen. Following this, you will find a for loop that acts as a timer for each round. It contains a set of if statements that pick up button presses and determine if they are correct.
Building Your Own Handheld Arduino Game
This article is a companion to the project code found on GitHub. You can find more information about the specific lines of code we have used in the comments in those files. But you are also welcome to simply load it onto your Arduino and enjoy the fun.
Creativity is key in the world of game development, and we encourage you to work on your own game ideas alongside this one.