GRA Dino T-Rex - Chromeasaurus rex

Typ_projektu
Arduino
Zdjecie główne
wyłacz neta i włacz chroma
Krótki opis projektu

Projekt gry "Dino" na Arduino to prosta, lecz wciągająca gra, która czerpie inspirację z ukrytej gry z dinozaurem dostępnej w przeglądarce Google Chrome, aktywującej się przy braku połączenia z internetem. W tej wersji Arduino celem gry jest sterowanie dinozaurem, który biegnie przez prehistoryczny pejzaż, unikając przeszkód w postaci drzew i innych elementów. Gracz musi skakać nad przeszkodami, naciskając przycisk podłączony do płytki Arduino, aby utrzymać dinozaura w ruchu jak najdłużej.

Niezbędne elementy

1. Płytka Arduino UNO

2. Płytka SIC Game Console

3. ekran OLED I2C

4. kabel micro USB

Sprzęt

Komputer z oprogramowaniem Arduino.

Opis projektu

Po uruchomieniu, na wyświetlaczu pojawia się dinozaur, który automatycznie zaczyna biec do przodu. Przeszkody pojawiają się na horyzoncie i poruszają się w kierunku dinozaura. Gracz musi nacisnąć przycisk, aby skoczyć i uniknąć kolizji. Gra kończy się, gdy dinozaur wpadnie na przeszkodę, a wynik gracza jest wyświetlany na ekranie.

Projekt ten łączy w sobie elementy programowania mikrokontrolerów, elektroniki i gier komputerowych, oferując satysfakcjonujące doświadczenie zarówno dla początkujących, jak i zaawansowanych hobbystów. Jest to doskonały sposób na naukę podstaw programowania Arduino, obsługi wyświetlaczy i przetwarzania wejścia użytkownika.

Główne cechy gry:

  • Prosta Grafika: Gra wykorzystuje proste grafiki bitmapowe do przedstawienia dinozaura oraz przeszkód, co sprawia, że jest łatwa do zrozumienia i przyjemna wizualnie, zachowując minimalistyczny styl.
  • Sterowanie Jednym Przyciskiem: Gracz używa jednego przycisku do skakania z dinozaurem. Prostota sterowania sprawia, że gra jest dostępna dla graczy w każdym wieku.
  • Dynamiczna Przeszkody: Przeszkody pojawiają się w losowych odstępach czasu i wymagają od gracza zręczności i szybkiej reakcji.
  • System Wyników: Gra może zawierać system punktów, gdzie gracze zdobywają punkty za każdą pokonaną przeszkodę, co zachęca do ponownych prób w celu pobicia własnego rekordu.
  • Wyświetlacz OLED: Gra korzysta z monochromatycznego wyświetlacza OLED do wizualizacji rozgrywki, oferując wyraźny i czytelny obraz mimo ograniczeń rozmiaru.
  • Rozszerzalność: Projekt jest otwarty na modyfikacje i dodawanie nowych funkcji, takich jak różne poziomy trudności, dodatkowe rodzaje przeszkód czy nawet power-upy.

W projekcie gry "Dino" na Arduino skorzystaliśmy z sztucznej inteligencji w uproszczonej formie, co dodatkowo wzbogaca doświadczenie gracza i stanowi interesujący element edukacyjny projektu.

Zdjęcia
kod programu

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
#define SCREEN_ADDRESS 0x3C
#define BUTTON_PIN 5

#define DINO_WIDTH 25
#define DINO_HEIGHT 26
#define DINO_INIT_X 10
#define DINO_INIT_Y 29

#define BASE_LINE_Y 54

#define TREE1_WIDTH 11
#define TREE1_HEIGHT 23
#define TREE2_WIDTH 22
#define TREE2_HEIGHT 23
#define TREE_Y 35

#define JUMP_PIXEL 45

#define MIN_TREE_SPACING 100 // Minimum number of pixels between the trees
#define RANDOM_SPACING 50 // Maximum additional random spacing

// loosen collison detection
#define DINO_PADDING_X 4 // Horizontal padding for the dino
#define DINO_PADDING_Y 5 // Vertical padding for the dino
#define TREE_PADDING_X 4 // Horizontal padding for the trees


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

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
};

// Global variables
int score = 0;
int16_t tree_x = 127, tree1_x = 195;
int tree_type = 0, tree_type1 = 0;
int16_t dino_y = DINO_INIT_Y;

unsigned long gameStartTime = 0; // Stores the start time of the game in milliseconds


// Function prototypes
void displayScore(int score);
void introMessage();
void renderScene();
void moveDino(int16_t *y);
void moveTree(int16_t *x, int type);
void gameOver();
void play();

void setup() {
 Serial.begin(9600);
 if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
   Serial.println(F("SSD1306 allocation failed"));
   for(;;);
 }
 display.clearDisplay();
 display.display(); // Update the display to show the cleared state
 introMessage();
 pinMode(BUTTON_PIN, INPUT_PULLUP); // Initialize the button pin as input with internal pull-up resistor
}

void loop() {
 static bool lastButtonState = HIGH; // Store the last state of the button
 bool currentButtonState = digitalRead(BUTTON_PIN); // Read the current state of the button

 // Check for a button press (transition from HIGH to LOW)
 if (lastButtonState == HIGH && currentButtonState == LOW) {
   delay(50); // Simple debounce delay to avoid detecting false presses

   play(); // Start the game when the button is pressed
 }

 lastButtonState = currentButtonState; // Update the last button state for the next loop iteration

 // Optionally, include a small delay at the end of the loop to give some time between reads
 delay(10);
}

void displayScore(int score) {
 display.setCursor(0, 0);
 display.print("Score: ");
 display.println(score);
}

void introMessage() {
 display.setTextSize(2);
 display.setTextColor(SSD1306_WHITE);
 display.setCursor(10, 5);
 display.println("Dino Game");
 display.setTextSize(1);
 display.setCursor(5, 45);
 display.println("Press SW6 To Play");
 display.display();
}

void renderScene() {
 displayScore(score);
 moveTree(&tree_x, tree_type);
 moveTree(&tree1_x, tree_type1);
 moveDino(&dino_y);
 display.drawLine(0, BASE_LINE_Y, SCREEN_WIDTH, BASE_LINE_Y, SSD1306_WHITE);
}

void moveDino(int16_t *y) {
 display.drawBitmap(DINO_INIT_X, *y, dino1, DINO_WIDTH, DINO_HEIGHT, SSD1306_WHITE);
}

void moveTree(int16_t *x, int type) {
 if (type == 0) {
   display.drawBitmap(*x, TREE_Y, tree1, TREE1_WIDTH, TREE1_HEIGHT, SSD1306_WHITE);
 } else {
   display.drawBitmap(*x, TREE_Y, tree2, TREE2_WIDTH, TREE2_HEIGHT, SSD1306_WHITE);
 }
}

void gameOver() {
 display.clearDisplay();
 display.setTextSize(2);
 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("Press SW6 To Play Again");
 display.display();
}

void play() {
 gameStartTime = millis(); // Record the current time as the game start time

 // Initialize or reset the game state
 score = 0;
 tree_x = 127;
 tree1_x = tree_x + MIN_TREE_SPACING + random(0, RANDOM_SPACING);
 tree_type = random(0, 2);
 tree_type1 = random(0, 2);
 dino_y = DINO_INIT_Y;
 int jump = 0; // 0: no jump, 1: jumping up, 2: falling down

 while (true) {
   display.clearDisplay();

   bool buttonPressed = digitalRead(BUTTON_PIN) == LOW; // Button is pressed if the pin reads LOW

   // Allow jumping if enough time has passed since the game started
   if (buttonPressed && jump == 0 && millis() - gameStartTime > 500) { // Adjust the 500ms delay as needed
     jump = 1; // Start the jump
   }

   // Handle jumping logic
   if (jump == 1) { // Jumping up
     dino_y -= 4; // Move dino up
     if (dino_y <= DINO_INIT_Y - JUMP_PIXEL) {
       jump = 2; // Start falling down
     }
   } else if (jump == 2) { // Falling down
     dino_y += 4; // Move dino down
     if (dino_y >= DINO_INIT_Y) {
       dino_y = DINO_INIT_Y; // Reset to ground level
       jump = 0; // End jump
     }
   }

   // Move trees
   tree_x -= 3; // Move first tree to the left
   tree1_x -= 3; // Move second tree to the left

   // Check for tree reset
   if (tree_x < -TREE1_WIDTH) {
     tree_x = SCREEN_WIDTH;
     tree_type = random(0, 2); // Randomize tree type
     // Randomly adjust the spacing for the next tree
     tree_x += MIN_TREE_SPACING + random(0, RANDOM_SPACING);
     score++; // Increase score for passing a tree
   }

   if (tree1_x < -TREE2_WIDTH) {
     tree1_x = SCREEN_WIDTH;
     tree_type1 = random(0, 2); // Randomize tree type
     // Randomly adjust the spacing for the next tree
     tree1_x += MIN_TREE_SPACING + random(0, RANDOM_SPACING);
     score++; // Increase score for passing a tree
   }

   // Collision detection
   if (((tree_x + TREE_PADDING_X < DINO_INIT_X + DINO_WIDTH - DINO_PADDING_X) && 
        (tree_x + TREE1_WIDTH - TREE_PADDING_X > DINO_INIT_X + DINO_PADDING_X) && 
        (dino_y + DINO_HEIGHT - DINO_PADDING_Y > TREE_Y)) ||
       ((tree1_x + TREE_PADDING_X < DINO_INIT_X + DINO_WIDTH - DINO_PADDING_X) && 
        (tree1_x + TREE2_WIDTH - TREE_PADDING_X > DINO_INIT_X + DINO_PADDING_X) && 
        (dino_y + DINO_HEIGHT - DINO_PADDING_Y > TREE_Y))) {
     // Collision occurred
     gameOver();
     return; // Exit play function and return to the main loop
   }

   // Render the scene
   renderScene();
   display.display();

   // Small delay to control game speed
   //delay(20);
 }
}

Youtube
Tagi
rex gra dino arduino chrome