Kultowa gra przeglądarkowa Chrome Dino teraz w odsłonie na ekranach OLED.
1. Płytka Arduino UNO
2. SIC Game Console
3. Ekran OLED 64x128
4. Kabel USB
Komputer ze środowiskiem Arduino
Kod implementuje prostą grę na platformie Arduino, w której gracz steruje postacią, unikając przeszkód poruszających się z lewej do prawej strony ekranu. Gra skupia się na szybkiej reakcji i precyzji gracza, gdyż nawet najmniejszy błąd może prowadzić do zderzenia z przeszkodą i zakończenia rozgrywki. Gracz porusza się za pomocą jednego przycisku, który odpowiada za skok postaci. Skok jest kluczowy w unikaniu przeszkód, dlatego precyzyjne naciśnięcie przycisku w odpowiednim momencie jest kluczowe dla sukcesu w grze. Skok jest kontrolowany poprzez długość naciśnięcia przycisku, po czym następuje opadanie z powrotem na ziemię. Symulacja grawitacji wprowadza element ryzyka, ponieważ gracz musi dobrze ocenić czas skoku, aby uniknąć przeszkód. Do tego w przypadku gdyby ocena była nieprecyzyjna lub przeszkoda była zbyt duża, można skok wydłużyć dodatkowym kliknięciem przycisku. Na drodze gracza pojawiają się przeszkody w postaci "dinozaurów", które przesuwają się w kierunku prawej strony ekranu. Punkty zdobywane są za każdą przeszkodę, którą udaje mu się przejść, zwiększając tym samym swoją ogólną liczbę punktów. Gra kończy się, gdy postać zderzy się z przeszkodą. Kolizje są wykrywane poprzez sprawdzanie, czy obszar dinozaura nakłada się na obszar przeszkody. Po zakończeniu gry wyświetlany jest ekran "Game Over" wraz z liczbą zdobytych punktów. Grę można na różne sposoby modyfikować we własnym zakresie , zmieniają długość i wysokość przeszkód, dodając ikonki startu czy pauzy i zmieniając wygląd postaci i przeszkód modyfikując odpowiednie bitmapy.
#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 -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BUTTON_PIN 7
#define DINO_WIDTH 16
#define DINO_HEIGHT 16
#define OBSTACLE_WIDTH 25
#define OBSTACLE_HEIGHT 16
#define MAX_OBSTACLES 4
#define TIME 1.5
#define GRAVITY 0.3
#define JUMP_STRENGTH 3.9
#define MIN_OBSTACLE_DISTANCE 80
#define MAX_OBSTACLE_DISTANCE 150
int dinoX;
int dinoY;
float dinoYSpeed;
float treeSpeed = 2;
int treeShift;
bool isJumping = false;
int doubleJump = 0;
int counter = 0;
int obstacleX[MAX_OBSTACLES];
int obstacleY[MAX_OBSTACLES];
bool gameOver = false;
void setup() {
display.setRotation(2);
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
dinoX = SCREEN_WIDTH / 10;
dinoY = SCREEN_HEIGHT - DINO_HEIGHT;
dinoYSpeed = 0;
}
void generateTrees(){
for(int i = 0; i < MAX_OBSTACLES; i++) {
if(i==0){
obstacleX[i] = SCREEN_WIDTH/5 + random(MIN_OBSTACLE_DISTANCE, SCREEN_WIDTH);
}
else{
obstacleX[i] = obstacleX[i-1] + random(MIN_OBSTACLE_DISTANCE, SCREEN_WIDTH);
}
obstacleY[i] = SCREEN_HEIGHT - OBSTACLE_HEIGHT;
}
}
void generateTree(int i){
if(i==0){
obstacleX[i] = obstacleX[i+3] + random(MIN_OBSTACLE_DISTANCE, SCREEN_WIDTH);
}
else{
obstacleX[i] = obstacleX[i-1] + random(MIN_OBSTACLE_DISTANCE, SCREEN_WIDTH);
}
obstacleY[i] = SCREEN_HEIGHT - OBSTACLE_HEIGHT;
}
void drawDino() {
static const unsigned char PROGMEM dinoBitmap[] =
{
B00000000, B00000000,
B00000001, B11000000,
B00011101, B11000000,
B00111101, B11000000,
B00111001, B11001110,
B00111001, B11000110,
B00111001, B11000110,
B00011101, B11000110,
B00001111, B11001110,
B00000111, B11111000,
B00000001, B11100000,
B00000001, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000001, B11000000,
};
display.drawBitmap(dinoX, dinoY, dinoBitmap, DINO_WIDTH, DINO_HEIGHT, WHITE);
}
void drawTree(int x, int y) {
static const unsigned char PROGMEM treeBitmap[] =
{
B000000, B00000000, B00000000, B00000,
B000111, B11111000, B00000000, B00000,
B011111, B10011110, B00000000, B00000,
B011111, B10011110, B00001000, B00000,
B011111, B11111110, B00000100, B00000,
B000000, B11111110, B00000010, B00000,
B000001, B11111110, B00000011, B00000,
B000000, B00111111, B11000001, B00110,
B000000, B00111111, B11111101, B11100,
B000000, B11111111, B11111111, B11100,
B000000, B10011111, B11111111, B11000,
B000000, B10000111, B11111111, B00000,
B000000, B00000001, B10000110, B00000,
B000000, B00000001, B10000100, B00000,
B000000, B00000001, B00001100, B00000,
B000000, B00000111, B00000000, B00000
};
display.drawBitmap(x, y, treeBitmap, OBSTACLE_WIDTH, OBSTACLE_HEIGHT, WHITE);
}
void drawObstacle(int x, int y) {
display.fillRect(x, y, OBSTACLE_WIDTH, OBSTACLE_HEIGHT, WHITE);
}
void drawGameOver() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(20, 20);
display.println("Game Over");
display.setCursor(20, 40);
display.println("Score:");
display.setCursor(100, 40);
display.println(counter);
}
void drawCounter(int counter) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(110, 20);
display.println(counter);
}
void loop() {
display.clearDisplay();
drawCounter(counter);
if (!gameOver) {
// Ruch dinozaura
if(digitalRead(BUTTON_PIN) == LOW && doubleJump < 5) {
dinoYSpeed = JUMP_STRENGTH;
isJumping = true;
doubleJump++;
}
// Symulacja grawitacji
dinoYSpeed -= GRAVITY*TIME;
dinoY -= dinoYSpeed*TIME;
//speed increase
treeSpeed += 0.004;
treeShift = treeSpeed*TIME;
// Odbicie od podłoża
if(dinoY > SCREEN_HEIGHT - DINO_HEIGHT) {
dinoY = SCREEN_HEIGHT - DINO_HEIGHT;
dinoYSpeed = 0;
isJumping = false;
doubleJump = 0;
}
// Rysowanie dinozaura
drawDino();
// Kolizja z przeszkodami
for(int i = 0; i < MAX_OBSTACLES; i++) {
if (obstacleX[i] <= dinoX + DINO_WIDTH && obstacleX[i] + OBSTACLE_WIDTH >= dinoX &&
obstacleY[i] <= dinoY + DINO_HEIGHT && obstacleY[i] + OBSTACLE_HEIGHT >= dinoY) {
gameOver = true;
}
}
// Poruszanie przeszkodami
for(int i = 0; i < MAX_OBSTACLES; i++) {
obstacleX[i] = obstacleX[i] - treeShift;
if(obstacleX[i] < -OBSTACLE_WIDTH) {
generateTree(i);
counter++;
}
drawTree(obstacleX[i], obstacleY[i]);
}
} else {
// Wyświetlanie napisu "Game Over" przez 2 sekundy
display.clearDisplay();
drawGameOver();
display.display();
delay(2000);
// Resetowanie gry
gameOver = false;
doubleJump = 0;
dinoY = SCREEN_HEIGHT - DINO_HEIGHT;
dinoYSpeed = 0;
treeSpeed = 2;
generateTrees();
counter = 0;
}
// Aktualizacja wyświetlacza
display.display();
// Pauza
delay(20);
}