I've always been very interested in electronics since I got an "Electronic for Kids" kit that my parents bought me more than 15 years ago, it felt like playing with LEGO but much more interesting. The thing is that as the years passed, I got more interested in software and somehow stopped doing electronics just for fun (I coursed some electronics courses in the university).
With the pandemic and the lock-down, I have been recovering the interest of doing more side-projects in my free time (I don't have the guts to go out from home yet) and then I remembered that I had some electronic stuff and an Arduino in my shelves. With the stuff I found, I then started thinking about what project could I do that will help me learn new stuff in both software and hardware.
After some minutes thinking about which project I could do with the stuff I had, I came up with this idea about doing a project like the game of the Chrome's Offline dinosaur where you have to jump over some obstacles. This will be possible with the 16 x 2 LCD screen I found, the Arduino, and the push button.
You can check the code of the project with its corresponding breadboard view in this GitHub repository:
A very simple game for Arduino.
Jump
This is a very simple game for Arduino, you should avoid having the ball deflated by falling into the spikes.
Getting started
To run this project you must have the following items:
Installation
- Clone the project.
- Open
jump.ino
with Arduino IDE.
- Upload it to your Arduino UNO.
Breadboard view
How does this work?
To Do list
The following items are missing to say this is v1 release:
- I may have a bug somewhere because the LCD flickers strangely in the "Game Over" message.
- A better animation when the ball jumps.
- A blog entry explaining how I did it.
- Better screenshots to show…
Let's work
First I needed to connect the LCD screen to the Arduino. I forgot how to do that, the last time I did something in an LCD screen was at the university for a "security system" project and that was like 3 or 4 years ago. So I followed the "Hello world" tutorial for LCD Screen in the Arduino website.
When the screen lit up and displayed the "hello, world" message I was ready to get into the coding of the game. I divided the game development into 3 stages:
- Create the obstacles in a random position and slide them in the screen.
- Create the ball and the collision logic.
- Add the jump logic to the ball.
Generating obstacles and movement
The obstacles are going to fill the whole bottom row of the LCD screen. I could do this with two different approaches: Using a boolean array of 16 positions or using a single short
typed variable.
I choose the latter approach because it will use only 2 bytes, while the former would be using 16 bytes. This also meant that I have to the operations in the obstacles by doing bitwise operations.
Let's start with the fundamental operation of the obstacles: "Being painted on-screen". The code can be reviewed in the paintObstacles() function, I'm going to iterate the 16 positions of the bottom row and I'll check if the current position has a 1 in the binary representation of the number. For example, if I had the number 143 its binary representation is 10001111 and those positions will be filled as an obstacle.
To check if the current position has 1 or a 0, I just do an AND bitwise operation with the rightmost digit, and then I do a right shift bitwise operation to move all the digits to the left one position.
To generate the new obstacles, the code can be reviewed in the generateObstacles() function and I use a simple random number generation between 0 and 9, and there is a 30% chance that you get a new obstacle in the game. To generate a new obstacle I do a left shift operation to move the digits one place to the left and then an OR operation with the rightmost digit in case you get a new obstacle.
That's all for obstacles!
Generating the ball and adding collision logic
The ball will be stationary in a cell of the LCD screen, starting in the bottom cell, the code can be reviewed in the paintBall() function. The ball is always going to be in the third cell from left to right which could be represented in binary as 8912.
The function to set the cursor of the LCD receives and integer from 0 to 15, so I cannot send 8192 as an argument. Getting that number is done by doing a subtraction and logarithm: First I do a log10(8192)/log10(2)
to obtain 13 (2 to the power of 13 is 8192) and then I subtract this number from the total number of columns which is 16, that gives me 3.
To know if the ball has collided with an obstacle I just check if the ball is in the air or not (a boolean variable) and do a AND operation between USER_POSITION
(which is 8192) and the currentObstacles
value (which can be any number between 0 and 32767); if this operation returns 1 it means that the ball has collided with an obstacle. This code can be reviewed in the hasLost() function.
After implementing this logic, I tweeted the current progress of the project, this is the tweet I made when I finished the collision logic.
Translation: The idea is to make a game similar to the dinosaur game in Chrome where you have to jump obstacles. I'm missing the jump logic and refining the code.
Jump Logic
When pressing the push button I save the the current execution time in a variable. I have function called isInAir() checking if that time is lower than 2 frame executions in the game, a frame is painted every 500ms. If the return of this function is true I paint the ball in the upper row and the collision logic will return false.
This is another tweet I made showing the final result.
Translation: It's got jumps 😃 I've got to refine the code that went downwards in cleanness over time, and I'll upload it to GitHub. I've got some details to fix, such as the Game Over which looks to have bug in the letters and add some details to the ball when it jumps.
Ta-da!
That's the game project, well at least this first version. I'm thinking into adding a bit more animations and small features such as a score.
I hope you all like it and reproduce your own version at home! I'll be happy to receive PRs to the project with cool stuff that you implement on your own version.
Conclusion
I wanted to optimize as much as possible in the size of the program, that's why I made some decisions in the design of the game such as using a short data type instead of the 16 positions bool array. The program ended weighting 3048 bytes (roughly 3 KB) and using 91 bytes of dynamic memory.
Doing this kind of projects will make have fun (if you like doing electronics) and will also teach you different topics related to programming such as bit management.
Thanks so much for reading up to here and remember to like ❤️ and share the article if you found it interesting!