Celem projektu było stworzenie prostej i łatwej w obsłudze gry w środowisku Arduino. Ten program, umożliwia zagranie w popularną grę Maze Runner. Założeniem gry jest dojście z pozcji początkowej do wyjścia unikając dotykania ścian.
1. Płytka Arduino UNO
2. Wyświetlacz OLED 64x128 pikseli
3. "Game Console v0.2 beta"
4. Kabel USB do Arduino
Komputer PC
Opis projektu:
Projekt jest realizacją gry "Maze Runner", czyli w tłumaczeniu "Biegacz labiryntu". Gracz steruje postacią (pikselem), która porusza się po labiryncie, starając się dotrzeć do wyjścia. Labirynt jest przedstawiony na wyświetlaczu OLED, a gracz steruje postacią za pomocą przycisków sterujących.
Główne elementy projektu:
a) Konstrukcja
Wyświetlacz OLED: Do wyświetlania labiryntu i aktualnej pozycji gracza użyto wyświetlacza OLED o rozmiarach 128x64 pikseli.
Sterowanie: Gracz steruje postacią za pomocą czterech przycisków: góra, dół, lewo, prawo. Przyciski te odpowiadają za poruszanie postacią w odpowiednich kierunkach.
b) Interfejs
Labirynt: Labirynt jest ręcznie zdefiniowany za pomocą białych linii na wyświetlaczu. ały ekran został obramowany, żeby wyjście z labiryntu było tylko jedno.
c) Gra
Zasady: Celem gry jest dotarcie od wejścia do labirytnu (lewy górny róg) aż do wyjścia (prawy dolny róg). Gracz musi unikać kolizji z liniami reprezentującymi ściany labiryntu.
Kolizje: Funkcja sprawdzająca kolizje zapobiega postaci przechodzenia przez ściany labiryntu. Jeśli postać ‘wejdzie’ w ścianę, jej ruch zostanie zatrzymany.
Wygrana: Gracz wygrywa, gdy dotrze do określonego punktu na planszy, który został zdefiniowany jako wyjście z labiryntu.
Przegrana: Jeśli postać gracza uderzy w ścianę, gra zostaje zakończona, a na ekranie OLED wyświetlany jest komunikat o zakończonej rozgrywce.
Projekt pozwala na prymitywną rozrywkę oraz wykorzystuje podstawowe funkcje wyświetlacza OLED i obsługę przycisków. Dzięki temu, możliwe jest stworzenie prostej, lecz wciągającej gry.
#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_UP 9
#define BUTTON_DOWN 7
#define BUTTON_LEFT 8
#define BUTTON_RIGHT 10
int playerX = 2; // Pozycja gracza w osi X
int playerY = 2; // Pozycja gracza w osi Y
#define PLAYER_SIZE 1 // Rozmiar gracza
void setup() {
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_LEFT, INPUT_PULLUP);
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
// Inicjalizacja wyświetlacza OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Nie udało się znaleźć wyświetlacza OLED"));
for(;;);
}
display.display();
delay(1000); // Czekaj 2 sekundy przed rozpoczęciem gry
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
}
// Ruch gracza
void loop() {
// Sprawdzanie wciśniętych przycisków i przesuwanie gracza
if (digitalRead(BUTTON_UP) == LOW && playerY > 0) {
playerY -= 2;
}
if (digitalRead(BUTTON_DOWN) == LOW && playerY < SCREEN_HEIGHT - PLAYER_SIZE) {
playerY += 2;
}
if (digitalRead(BUTTON_LEFT) == LOW && playerX > 0) {
playerX -= 2;
}
if (digitalRead(BUTTON_RIGHT) == LOW && playerX < SCREEN_WIDTH - PLAYER_SIZE) {
playerX += 2;
}
// Sprawdzenie kolizji z linią labiryntu
if (checkCollision(playerX, playerY)==true) {
endGame(); // Zakończ grę, jeśli doszło do kolizji z linią
}
if (checkWin(playerX, playerY)==true) {
win(); // Zakończ grę, jeśli jest wygrana
}
// Rysowanie labiryntu
display.clearDisplay();
drawMaze();
// Rysowanie gracza
display.fillRect(playerX, playerY, PLAYER_SIZE, PLAYER_SIZE, SSD1306_WHITE); // Wypełniony obszar gracza
display.display();
delay(100); // Opóźnienie dla płynnego ruchu gracza
}
void drawMaze() {
// Rysowanie ścianek labiryntu
// Rysowanie ścianek labiryntu
// Ramka
display.drawLine(6,0,SCREEN_WIDTH-1,0,SSD1306_WHITE);
display.drawLine(0,0,0,SCREEN_HEIGHT-2,SSD1306_WHITE);
display.drawLine(0,62,120,62,SSD1306_WHITE);
display.drawLine(127,0,127,62,SSD1306_WHITE);
// labirynt
display.drawLine(6,0,6,24,SSD1306_WHITE);
display.drawLine(6,24,18,24,SSD1306_WHITE);
display.drawLine(18,24,18,6,SSD1306_WHITE);
display.drawLine(18,6,34,6,SSD1306_WHITE);
display.drawLine(12,0,12,18,SSD1306_WHITE);
display.drawLine(40,6,40,44,SSD1306_WHITE);
display.drawLine(0,30,24,30,SSD1306_WHITE);
display.drawLine(18,30,18,44,SSD1306_WHITE);
display.drawLine(18,44,34,44,SSD1306_WHITE);
display.drawLine(24,30,24,12,SSD1306_WHITE);
display.drawLine(6,36,6,46,SSD1306_WHITE);
display.drawLine(6,36,18,36,SSD1306_WHITE);
display.drawLine(24,12,34,12,SSD1306_WHITE);
display.drawLine(30,18,40,18,SSD1306_WHITE);
display.drawLine(46,0,46,34,SSD1306_WHITE);
display.drawLine(46,34,40,34,SSD1306_WHITE);
display.drawLine(41,56,6,56,SSD1306_WHITE);
display.drawLine(24,24,34,24,SSD1306_WHITE);
display.drawLine(24,30,34,30,SSD1306_WHITE);
display.drawLine(12,50,12,41,SSD1306_WHITE);
display.drawLine(24,44,24,49,SSD1306_WHITE);
display.drawLine(18,50,18,56,SSD1306_WHITE);
display.drawLine(6,56,6,61,SSD1306_WHITE);
display.drawLine(120,61,120,50,SSD1306_WHITE); //1
display.drawLine(120,50,110,50,SSD1306_WHITE); //2
display.drawLine(110,50,110,38,SSD1306_WHITE); //3
display.drawLine(110,38,120,38,SSD1306_WHITE); //4
display.drawLine(116,44,125,44,SSD1306_WHITE); //5
display.drawLine(120,32,110,32,SSD1306_WHITE); //6
display.drawLine(41,56,41,61,SSD1306_WHITE);
display.drawLine(31,50,52,50,SSD1306_WHITE);
display.drawLine(58,61,58,50,SSD1306_WHITE);
display.drawLine(34,44,34,36,SSD1306_WHITE);
display.drawLine(46,24,66,24,SSD1306_WHITE);
display.drawLine(46,40,46,50,SSD1306_WHITE);
display.drawLine(46,40,52,40,SSD1306_WHITE);
display.drawLine(52,30,52,40,SSD1306_WHITE);
display.drawLine(52,30,72,30,SSD1306_WHITE);
display.drawLine(72,18,72,30,SSD1306_WHITE);
display.drawLine(72,18,72,30,SSD1306_WHITE);
display.drawLine(52,18,72,18,SSD1306_WHITE);
display.drawLine(52,18,52,6,SSD1306_WHITE);
display.drawLine(58,12,58,6,SSD1306_WHITE);
display.drawLine(80,6,86,6,SSD1306_WHITE);
display.drawLine(58,12,74,12,SSD1306_WHITE);
display.drawLine(46,12,52,12,SSD1306_WHITE);
display.drawLine(64,0,64,6,SSD1306_WHITE);
display.drawLine(70,6,76,6,SSD1306_WHITE);
display.drawLine(0,50,12,50,SSD1306_WHITE);
display.drawLine(58,36,58,38,SSD1306_WHITE);
display.drawLine(58,50,70,50,SSD1306_WHITE);
display.drawLine(70,50,70,44,SSD1306_WHITE);
display.drawLine(76,56,76,41,SSD1306_WHITE);
display.drawLine(76,56,58,56,SSD1306_WHITE);
display.drawLine(58,56,58,61,SSD1306_WHITE);
display.drawLine(52,61,52,56,SSD1306_WHITE);
display.drawLine(58,56,58,43,SSD1306_WHITE);
display.drawLine(58,56,58,38,SSD1306_WHITE);
display.drawLine(70,44,64,44,SSD1306_WHITE);
display.drawLine(83,56,98,56,SSD1306_WHITE);
display.drawLine(98,56,98,44,SSD1306_WHITE);
display.drawLine(110,32,110,18,SSD1306_WHITE); //7
display.drawLine(110,18,120,18,SSD1306_WHITE); //8
display.drawLine(116,25,125,25,SSD1306_WHITE); //9
display.drawLine(120,12,120,18,SSD1306_WHITE); //10
display.drawLine(120,12,104,12,SSD1306_WHITE); //11
display.drawLine(104,18,104,61,SSD1306_WHITE); //12
display.drawLine(120,6,104,6,SSD1306_WHITE); //13
display.drawLine(104,12,104,0,SSD1306_WHITE); //14
display.drawLine(104,18,98,18,SSD1306_WHITE); //15
display.drawLine(98,18,98,6,SSD1306_WHITE); //16
display.drawLine(98,6,86,6,SSD1306_WHITE); //17
display.drawLine(74,6,80,6,SSD1306_WHITE); //18
display.drawLine(80,6,80,12,SSD1306_WHITE); //19
display.drawLine(80,12,74,12,SSD1306_WHITE); //20
display.drawLine(86,12,92,12,SSD1306_WHITE); //21
display.drawLine(92,12,92,18,SSD1306_WHITE); //22
display.drawLine(72,18,92,18,SSD1306_WHITE); //23
display.drawLine(92,24,98,24,SSD1306_WHITE); //24
display.drawLine(98,24,98,44,SSD1306_WHITE); //25
display.drawLine(92,24,92,18,SSD1306_WHITE); //26
display.drawLine(82,44,82,56,SSD1306_WHITE); //31
display.drawLine(82,44,92,44,SSD1306_WHITE); //32
display.drawLine(92,44,92,50,SSD1306_WHITE); //33
display.drawLine(92,50,82,50,SSD1306_WHITE); //34
display.drawLine(64,38,64,30,SSD1306_WHITE); //35
display.drawLine(76,38,76,42,SSD1306_WHITE); //*
display.drawLine(76,38,82,38,SSD1306_WHITE); //27
display.drawLine(78,24,86,24,SSD1306_WHITE); //28
display.drawLine(86,38,86,30,SSD1306_WHITE); //29
display.drawLine(78,24,78,38,SSD1306_WHITE); //30
display.drawLine(92,38,82,38,SSD1306_WHITE); //30*
display.drawLine(82,44,82,56,SSD1306_WHITE); //31
display.drawLine(82,44,92,44,SSD1306_WHITE); //32
display.drawLine(92,44,92,50,SSD1306_WHITE); //33
display.drawLine(92,50,82,50,SSD1306_WHITE); //34
display.drawLine(92,30,86,30,SSD1306_WHITE); //40
display.drawLine(92,30,92,38,SSD1306_WHITE); //41
display.drawLine(78,24,86,24,SSD1306_WHITE); //42
display.drawLine(86,38,82,38,SSD1306_WHITE); //30*
}
// Wygrana
bool checkWin(int x, int y){
if (x > 120 && y > 60) {
return true;
}
return false;
}
// Sprawdzenie czy gracz dotknal scianki labiryntu
bool checkCollision(int x, int y) {
// Sprawdzenie czy piksel obok gracza jest biały
if (display.getPixel(x + 1, y) == SSD1306_WHITE ||
display.getPixel(x - 1, y) == SSD1306_WHITE ||
display.getPixel(x, y + 1) == SSD1306_WHITE ||
display.getPixel(x, y - 1) == SSD1306_WHITE) {
return true; // Kolizja
}
return false; // Brak kolizji
}
// Koniec gry
void endGame() {
// Wyświetlenie komunikatu na ekranie OLED
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println(" Koniec");
display.println(" gry!");
display.display();
// Pętla nieskończona - zatrzymuje działanie programu
while (true) {
// Możesz tutaj dodać dodatkowe czynności po zakończeniu gry
}
}
// Wygrana
void win() {
// Wyświetlenie komunikatu na ekranie OLED
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println("WYGRALES!");
display.display();
// Pętla nieskończona - zatrzymuje działanie programu
while (true) {
// Możesz tutaj dodać dodatkowe czynności po zakończeniu gry
}
}