Hand tools and fabrication machines
I've always been fascinated with the process of game design. I find it amazing how so many people can come together and work on a singular, massive project. The coding, art design, music, environments and everything just meshes together seamlessly in a neat, entertaining package. It's a world that I've always wanted to get into, but have always been afraid to because of what I perceived to be a high learning curve and not exactly knowing where to start. When the opportunity came along to try and code a very simple video game, I was a little hesitant, but ended up pushing myself to do just that. Although the end result is extremely simplistic and only a fraction of what I had originally proposed, the fact that I was able to build and code something wherein the hardware interacts to move a character on a screen has given me the foundation and skills to pursue more involved projects in the future and has given me a nice, introductory step into the world I've always wanted to enter. It's also made me a lot more appreciative of the work that goes into massive projects, and has made me more forgiving towards buggy games that launch incomplete at release!Background
When looking for inspiration as to what type of game I wanted to create, I thought in very simplistic terms. I knew I wasn't going to make the next Super Mario (or even Pong for that matter) but I knew I wanted to have some sort of button functionality because I really like arcade games (especially Galaga). Next, I thought about games that involve button presses that are relatively simple (i.e., the characters on the screen aren't doing much), and my mind immediately went went to the online clicker games, where the only objective is to click your mouse or spacebar as many times as possible within a given timeframe (typically 10 seconds). This main idea of clicking a button as fast as possible got carried over to the final iteration of the project, which was to be a multiplayer game where you and a friend went neck and neck and pressed your respective buttons for a certain amount of time to move your character across the screen. Whoever clicked their button more within that timeframe would see their character farther along the screen and would win. I had also envisioned the game being able to implement music during the game to give it a more auditory element.Current Version of the Project
The core features of the proposed project are operational. Currently, on startup, a narrative of the game is displayed on the SPI Display. This is followed by a set of pregame instructions. Next, the 7-segment display will countdown form 3 to 1, after which the display prompts you to "Go." A character will appear on the screen and will move forward every 15 button clicks. Following 60 button clicks, your character will appear on the other side of the screen and you will be prompted that you have won. Features absent from this iteration of the game include the multiplayer functionality, and the ability to integrate a countdown that will end the game if you don't make it to the end of the screen in a given timeframe. Finally, there is no music implementation in this version of the project.Building the current version of the project
Building this current iteration of the project can be described in two main steps: hardware and software formulation. The process I took was to begin with the hardware because it's a little bit easier to troubleshoot and gives you a better idea of certain parameters, like how much space your project is going to take up, how to efficiently make connections, etc. The overall process is outlined below, along with any significant milestones.Hardware
7-Segment Display and Buzzer
I started by setting up the 7-Segment display and buzzer because I knew I wanted these parts to be heavily integrated. My idea was to have the HEX display serve as the countdown timer that lets the user know when the game has begun and to have the buzzer sound after every countdown beat to give the game an audio component. I wired these two components on their own separate half-size solderless breadboard to make navigation between the different aspects of the game easier. The end result can be seen below:
The HEX Display has an I2C backpack that enables a connection to the PocketBeagle's I2C pins. The Piezo speaker is wired to one of the PocketBeagle's PWM pins.
After the HEX display and buzzer were up and running, the next piece of hardware I addressed was the SPI Display. The SPI display is where the bulk of the game happens. It serves three main functions in this project: (1) it delivers the pregame narrative and in-game instructions; (2) it displays the character image at different positions after a designated amount of user input; and (3) it delivers either a "win" message or "loss message" when the appropriate criteria are met.
To setup the SPI Display required the use of soldering. I soldered a female header with long leads into the SPI side of the display and formed a solder bridge between the IM1, IM2, and IM3 connections on the back. The end result looked like this:
After soldering, I connected the SPI display onto the main solderless breadboard, i.e., the breadboard that contained the PocketBeagle. I then tested its functionality with some test code (which will be given below) to ensure that it was working.
Ensuring that the screen worked with this test allowed me to move on to the last major piece of hardware: the arcade button.
Hooking up the arcade button was initially a little tricky but after using a combination of Male/Male jumper cables and thick, stripped wires I was able to get a secure, mechanical connection to work that was capped off with solder to promote electrical connectivity between the wire and the jumper cable pins. I wired this button to a separate half-sized solderless breadboard just to have more distinction between the separate aspects of the device. Initially, I had two buttons connected because I had planned to implement multiplayer functionality, however, one of the buttons ended up breaking. This ended up being both a curse and a blessing, as implementing multiplayer functionality from a software perspective would have taken too much time. Furthermore, understanding how to move one character on the screen lends itself to implementing multiplayer in another iteration of the project. The wired buttons can be seen below:
By this point in the project, I had all my major hardware pieces integrated into one circuit. The full picture can be seen below. A fritzing diagram with the appropriate connections will be included below.
After the hardware, it came time to start implementing the software for the device. The programming language utilized was Python because of the abundance of libraries and resources available on the internet. The main functions that the code had to perform varied depending on the piece of hardware that was being used. An overview of what the code had to do for each hardware component can be seen below:
1 ) SPI Screen
- Display Text (Pregame narrative, in-game instructions, Win or Lose message)
- Display Image (Initialize the image onto the screen)
- Update Image (Move the image across the screen from left to right after a certain amount of button presses)
2 ) 7-Segment Display
- Countdown from 3 to 1
- Prompt the user to begin clicking the button by displaying "go"
- Countdown from 10 to 1 to let the player know how much time they have left in the game
3 ) Buzzer
- Buzz after each beat on the 7-Segment Display
- End the buzzer sound after a specified amount of time
- Buzz after the game is over to auditorily let the player know it's over
4 ) Arcade Button
- Count the number of clicks the user has made
- Interpret this click number and update the screen after a designated amount of button clicks
At first, I had segmented these codes into separate python scripts, but after realizing that everything could be easily integrated into one script, I opted for that approach. The python script (called "Main_game.py") can be found below.
To manage the SPI screen, I imported several libraries. The main one being the Pillow library, specifically the "Image, ImageDraw, and ImageFont" libraries:
After accessing the appropriate libraries, I began to work on the separate functions. I created a class that, in general, managed the SPI screen and the button input. In total, this class had eight functions. The main function that actually updates the screen after a certain amount of button presses is seen below:
When called, the function will open an image that you give it as an input. The function will obtain the dimensions of the image from a supplementary function known as "get_dimensions" (see Python code). Next, the function uses functions built into the Pillow library to scale the image and initializes the screen by displaying a black background with the image in the forefront (Figure 8).
The main part of this function that coordinates button presses to the screen updating is seen below:
A series of if and else statements control the position of the character relative to the screen by using the function from the python Pillow library "paste." Essentially, after 15 button clicks, the image (positioned in a new place) gets pasted over a freshly made black screen. This process repeats for 60 button clicks, after which another function ("text") is called to display a "win" message. The only way a "lose" message is displayed is if the user holds the button down for longer than 4 seconds.
This is the core of the game, and is the main guts of the game. The other functions are mainly supplementary.Power Block Diagrams
The connections guide for the major hardware components of the project can can be seen below:
After creating a run script, the project was able to run on boot. An example of its operation follows:Next Steps
The multiplayer functionality of this game has yet to be implemented. Also, the original scope of the project included the execution of music during the game (and possibly before and after). Finally, the "challenge" aspect of the game is missing. Originally, I had wanted the user to have 10s to click as fast as possible, however, I was not able to implement this functionality. These objects would be the next things to address. Also, I would like to have some sort of housing for the device.