The T-Rex Game (Chrome Dino) in Arduino Using OLED Display

by bytesByHarsh in Circuits > Arduino

2258 Views, 2 Favorites, 0 Comments

The T-Rex Game (Chrome Dino) in Arduino Using OLED Display

The T-Rex Game (Chrome Dino) in Arduino using OLED Display.png
The T-Rex Game (Chrome Dino) in Arduino using OLED Display (Easy Tutorial)

We all have played the dino game in chrome whenever our internet is not working. I am not so good at playing it though but thought of creating the basic version of the game in Arduino.

For a complete tutorial, you can check out the youtube video or my blog.

Supplies

  • Arduino Mega/Uno
  • 0.96" OLED 64x128 Display Module
  • Arduino IDE

Write Basic Code

Source Code : https://github.com/harshmittal2210/youtubeProjects/blob/master/Arduino/dino_game/dino_game.ino

Implementation

Connect the jumper wires according to the image shown below.

(Note: Wire number can be different for your boards, please read the documentation)



Create a new sketchbook in Arduino IDE and select the correct boards and ports.

Include the Lib:

// Include
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


Note: Remember to install Adafruit Lib in Arduino

Add defines:

// Screen Info
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C

// Dino Info
#define DINO_WIDTH 25
#define DINO_HEIGHT 26
#define DINO_INIT_X 10
#define DINO_INIT_Y 29

// Line info
#define BASE_LINE_X 0
#define BASE_LINE_Y 54
#define BASE_LINE_X1 127
#define BASE_LINE_Y1 54

// Trees info
#define TREE1_WIDTH 11
#define TREE1_HEIGHT 23
#define TREE2_WIDTH 22
#define TREE2_HEIGHT 23
#define TREE_Y 35

#define JUMP_PIXEL 22 // Max jump in pixel


Init display

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


Image to CPP

Generate a byte array of dino and trees.

You can use the site: https://javl.github.io/image2cpp/

static const unsigned char PROGMEM dino1[]={
// 'dino', 25x26px
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x06, 0xff, 0x00, 0x00, 0x0e, 0xff, 0x00,
0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x0f, 0xc0, 0x00,
0x00, 0x0f, 0xfc, 0x00, 0x40, 0x0f, 0xc0, 0x00, 0x40, 0x1f, 0x80, 0x00, 0x40, 0x7f, 0x80, 0x00,
0x60, 0xff, 0xe0, 0x00, 0x71, 0xff, 0xa0, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x7f, 0xff, 0x80, 0x00,
0x7f, 0xff, 0x80, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00,
0x03, 0xfc, 0x00, 0x00, 0x01, 0xdc, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00,
0x01, 0x0c, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00
};

static const unsigned char PROGMEM tree1[]={
// 'tree1', 11x23px
0x1e, 0x00, 0x1f, 0x00, 0x1f, 0x40, 0x1f, 0xe0, 0x1f, 0xe0, 0xdf, 0xe0, 0xff, 0xe0, 0xff, 0xe0,
0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xc0, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00,
0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00
};

static const unsigned char PROGMEM tree2[]={
// 'tree2', 22x23px
0x1e, 0x01, 0xe0, 0x1f, 0x03, 0xe0, 0x1f, 0x4f, 0xe8, 0x1f, 0xff, 0xfc, 0x1f, 0xff, 0xfc, 0xdf,
0xff, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff,
0xfc, 0xff, 0xef, 0xfc, 0xff, 0x83, 0xfc, 0xff, 0x03, 0xfc, 0xff, 0x03, 0xf8, 0x7f, 0x03, 0xe0,
0x1f, 0x03, 0xe0, 0x1f, 0x03, 0xe0, 0x1f, 0x03, 0xe0, 0x1f, 0x03, 0xe0, 0x1f, 0x03, 0xe0, 0x1f,
0x03, 0xe0, 0x1f, 0x03, 0xe0
};



Logic


setup()

Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
introMessage();
// Run game in loop
while(1){
if (Serial.available()){
if(Serial.parseInt()==1){
play();
}
}
}


introMessage() function will display the game name and further instructions

void introMessage(){
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(10,5);
display.println("Dino Game");
display.setTextSize(1);
display.setCursor(5,45);
display.println("Enter 1 To Play ");
display.display();
}

play() is the main game function. Let's Break it down into smaller pieces for better understanding.


# Initialize evrything
int16_t tree_x=127; // End of the screen
int16_t tree1_x=195; // So that second type of tree comes after some time
int tree_type = random(0,2); // Select random type of tree
int tree_type1 = random(0,2);
int16_t dino_y = DINO_INIT_Y;
int input_command;
int jump=0; // init jump state is 0 i.e on base
int score=0;

The rest of the code will be in a for loop unless a collision happens:

display.clearDisplay();

if (Serial.available()){ // Check for serial Data
input_command = Serial.parseInt();
if(input_command==5){ // Jump
Serial.println("Jump");
if(jump==0) jump=1;
}
}

Change Jump status:

if(jump==1){ // Going UP
dino_y--;
if(dino_y== (DINO_INIT_Y-JUMP_PIXEL)){
jump=2;
score++;
}
}
else if(jump==2){ // Comming down
dino_y++;
if(dino_y== DINO_INIT_Y){
jump=0;
}
}


Check for collision:

if(tree_x<= (DINO_INIT_X+DINO_WIDTH) && tree_x>= (DINO_INIT_X+(DINO_WIDTH/2))){
// Serial.println("Might be Collision Happend");
if(dino_y>=(DINO_INIT_Y-3)){
// Collision Happened
Serial.println("Collision Happend");
break;
}
}
if(tree1_x<= (DINO_INIT_X+DINO_WIDTH) && tree1_x>= (DINO_INIT_X+(DINO_WIDTH/2))){
// Serial.println("Might be Collision Happend");
if(dino_y>=(DINO_INIT_Y-3)){
// Collision Happened
Serial.println("Collision Happend");
break;
}
}


Render the scene:

displayScore(score); // Live Score
moveTree(&tree_x,tree_type);// Move tree 1
moveTree(&tree1_x,tree_type1); // Move tree 2
moveDino(&dino_y); // Move dino
display.drawLine(0,54,127,54, SSD1306_WHITE); // Base line

Move trees:

tree_x--;
tree1_x--;
if(tree_x==0) {
tree_x = 127;
tree_type = random(0,1);
}
if(tree1_x==0) {
tree1_x = 195;
tree_type1 = random(0,1);
}

Display everything:

display.display();

Once collision happens:

Serial.println("Game Over");
gameOver(score);

Move dino and tree:

// Move dino function
void moveDino(int16_t *y, int type=0){
display.drawBitmap(DINO_INIT_X, *y, dino1, DINO_WIDTH, DINO_HEIGHT, SSD1306_WHITE);
}
// Move tree funciton
void moveTree(int16_t *x, int type=0){
if(type==0){
display.drawBitmap(*x, TREE_Y, tree1, TREE1_WIDTH, TREE1_HEIGHT, SSD1306_WHITE);
}
else if(type==1){
display.drawBitmap(*x, TREE_Y, tree2, TREE2_WIDTH, TREE2_HEIGHT, SSD1306_WHITE);
}
}

gameOver():

// Game over display with score
void gameOver(int score=0){
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(10,5);
display.println("Game Over");
display.setTextSize(1);
display.setCursor(10,30);
display.print("Score: ");
display.print(score);
display.setCursor(1,45);
display.println("Enter 1 To Play Again");
display.display();
}

This concludes this tutorial on creating a very basic game using Arduino and OLED. For the demo check out the video:


Hope you liked it!!


The T-Rex Game (Chrome Dino) in Arduino using OLED Display (Easy Tutorial)