The goal of this project was to create a 2-button game which has you "stop" when the screen has as much blue as possible without being entirely blue. If the screen does become entirely blue, it is called timing out, and you get a score of zero points. Another goal was to add the "back button" feature, which also wants you to be as close as possible to blue, but instead of ending the game, it adds a multiple of the end closeness to your score. This bonus allows you to score significantly more points than you would with just the "stop" button. To clarify more directly, your score is (approximately) as follows:
stopCloseness * Σ numBackPresses i=0 closenessAtPress / numBackPresses
This is not 1:1, but it establishes the concept. It’s not multiplying for each press, but more presses make more score, but more bad presses lower score and can be more harmful than just not pressing it to begin with. There is also a home screen, a score screen, and 2 information screens which explain the game. The system runs using a finite state machine (excluding interrupts) to determine what actions to perform at any given time, and you can only do screen-specific actions on each screen.
Video |
The module is based on BG22-EK4108A Microcontroller Development Kit from Silicon Labs and color LCD with 96x64 resolution with built-in SSD1331 driver. It also has 2 buttons for interfacing with the user.
Schematic | Board layout | Assembled device | ||
The major software modules used in my project are as follows:
Home screen | Help screen 1 | Help screen 2 | Score screen | |||
![]() |
![]() |
![]() |
![]() |
---|
The gradient in the background is the same for every image. The black on the score screen is for consistency with the text module I didn't bother figuring out.
To produce results, we are going to need parameters of gameplay, and the ability to track button presses, time, and the state of the system. What naturally follows are the following variables:
In order to actually use these states, you have to have certain functionality. Trivial ones won't be mentioned, but important ones will be.
I really liked the end result of the getRGBAt(x, y) function, as it made the gameplay visuals unique and exactly what I was looking for, and it was the entire reason I decided to make a timing game in the first place. This project was a thinly veiled attempt at masking the desire to make a fun interactive gradient :). Regardless, there are some things I would do differently if I made this project again. First off, I would recommend not using the integrated SSD1331 system's image renderer, as the images it takes have to be pre-loaded with every pixel and if you're dealing with things at the pixel level, you might as well do it yourself and save yourself the headache of trying to learn the system. Additionally, I would recommend avoiding splitting the location of where your logic is stored. Pick either the state-based methods or interrupts, but not both. I recommend going purely interrupt driven, however it is not what I ended up doing. This results in what I believe to be a less responsive system, sadly. Also, I would have added a feature where the longer you held the 'back' button, the more points it is worth, but adding a limit to how long you can hold it for and some screen effect alterations to indicate how close you are to expiring it. That gameplay feature would have made the system a bit more interesting.