Something that was bothering me for some time now is that I haven't made anything fun in a while, mainly because I lack good ideas for things like that. Luckily, an idea came to my mind to do this project out of nowhere, and viola, here we are.
Now, just to point out, this project was NOT written in Arduino, rathte pure AVR C code using Atmel Studio. I am using an Arduino Uno and an Uno-compatible shield, but mainly because that is the cheapest and most available thing I have with me (same goes for the keypad shield I have it for years now). So for anyone familiar with C but only worked in Arduino, about half of the code would look confusing here, but take it from someone who took to learn AVR C (by myself), it's not hard at all as I managed to adapt to it in a week (more less).
If you want use the code or just flash the firmware on the UNO board, I recommend watching this video.
For the most part, I've explained everything in the code itself, here I'm going to more explain the working principle of the code.
This was a bit of a strugle for a datasheet newbie, but interfacing with this IC was pretty frustrating. I ended up copying configuration bytes from this guy (thanks dude). Everything else depends on setting the bits in the upper 4 pins of the PORTD register and using EN and RS pins properly. In my implemetation the whole PORTD is wasted for communicating with the display (thus nullifying the benefits of the 4-bit mode) and effectively wasting the UART but I wans't going to use those for anything else anyway so it's ok for this use case. Make sure when you interface with this IC to use proper delays otherwise it wont be able to proccess the data properly (it is a fairly slow chip). Another point is that the game speed is limited by how quick the display can refresh. At its highest peek speed, the display updates at 11.8Hz (85ms delay on loop) and it's readable enough to play this kind of game, everything further causes major gosting and brightness issues. Now, you have to keep in mind, this isn't want the IC and display are made for, just simple text displaying.
As I wanted to make this game as random as possible, every time I loop I read the analog value from ADC5 that is left floating and use that number as a seed for C's RNG function. This is far from perfect as there can appear repeating sequances that take few seconds to go away, but without adding any aditional hardware, this is (probably) the best it can get.
Every 500us Timer1 is set to triger TIMER1_COMPA_vect ISR where it's checked if the up button is pressed and global variable(s) is set accordingly.
To make everything easier to code and effectively shrink the application logic I use a buffer for the line one and a buffer for the line two of the display. Everything is written to those 2 buffers and they are written as a whole to the display.
Nothing special here, I made a 5x8 image in paint.net and drew the dinosaur and the cactus. Every colored square represents a 1 and empty (white) one represents to zero. After that I translated that to hex and added everything to the two uint8 arrays. Those 2 characters are stored in IC's CGRAM, where dinosaur is 0x00 and cactus is 0x01 in its register.
- Game speeds up the longer you play it
- The cactuses are initialy seperated by minimaly 5 spaces, as the game progresses it goes down to 3
- Current score is displayed in the game, current, and best score are displayed after you lose
- There is 500ns interrupt pooling to check if the Up button is pressed and thus there are no issues with delay blocking the input
- Cheating by holding the Up button constantly or spaming it are prevented
- The dinosaur is in the air 3 loop cycles after it jumps
- Custom characters made for the cactuses and dinosaur
After you loose, press the select button to restart the game.