Witam,
Nazywam się Rafał i chciałbym przedstawić projekt sławnej gry Snake na Arduino. W drugiej części pokażę wam jak zrobić fajną obudowę na grę.
Co nam będzie potrzebne:
– Arduino, w moim przypadku Uno,
– Wyświetlacz LCD graficzny 84x48px – Nokia 5110,
Wszystkie potrzebne elementy widać na zdjęciu.
Od czego zacząć?
Ściągamy i instalujemy wszystkie potrzebne biblioteki:
Teraz czas złożyć nasz układ:
Podłączenie LCD:
pin 7 – Serial clock out (CLK)
pin 6 – Serial data out (DIN)
pin 5 – Data/Command select (DC)
pin 4 – LCD chip select (CE)
pin 3 – LCD reset (RST)
Buzzer podłączyłem przez rezystor 100Ω, aby nie był byt głośny.
Wgrywanie sketcha
Aby na wyświetlaczu zobaczyć wszystko dokładnie należy pamiętać o dobrym ustawieniu kontrastu- display.setContrast(25); w moim przypadku jest to 20.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
#include <EEPROM.h> //Biblioteki #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); //LCD Nokia #define LEFT 8 //Piny #define DOWN 10 #define RIGHT 11 #define UP 12 #define PAUSE 9 #define MAX_WIDTH 84 //Lcd 84x48 #define MAX_HEIGHT 48 #define speakerPin 2 boolean dl=false,dr=false,du=false,dd=false; //Kierunki ruchu //Zmienne int x[200], y[200], i, slength, tempx=10, tempy=10, xx, yy; uint8_t bh,bl; int xegg,yegg; int freq,tb; int l, r, u, d, p; unsigned long time=280,beeptime=50; int score=0, flag=0; void setup() { Serial.begin(9600); //Ustawienie prędkości display.begin(); display.clearDisplay(); //Czyszczenie ekranu pinMode(LEFT, INPUT); //Wejśćia pinMode(RIGHT, INPUT); pinMode(UP, INPUT); pinMode(DOWN, INPUT); pinMode(PAUSE, INPUT); pinMode(speakerPin, OUTPUT); //Buzzer pin digitalWrite(LEFT, HIGH); digitalWrite(RIGHT, HIGH); digitalWrite(UP, HIGH); digitalWrite(DOWN, HIGH); digitalWrite(PAUSE, HIGH); display.setContrast(20); //Ustawienie kontrastu slength=8; //Początkowa długość węża 8 xegg=(display.width())/2; yegg=(display.height())/2; //Intro display.setTextSize(2); //Rozmiar display.setTextColor(BLACK); //Kolor display.setCursor(10,10); //Ustawienie kursora display.print("SNAKE "); //Tekst display.setTextSize(1); //Rozmiar display.setTextColor(WHITE, BLACK); //Kolor display.println(" game "); //Tekst display.display(); delay(4000); //Długość wyświetlania display.clearDisplay(); //Czyszczenie ekranu for(i=0;i<=slength;i++) //Współrzędne węża { x[i]=25-3*i; y[i]=10; } for(i=0;i<slength;i++) { display.drawCircle(x[i],y[i],1,BLACK); } display.display(); dr=true; //Ruch w prawo } void loop() { movesnake(); } void movesnake() //Ruchy { l=digitalRead(LEFT); //Kierunki d=digitalRead(DOWN); r=digitalRead(RIGHT); u=digitalRead(UP); p=digitalRead(PAUSE); if(flag==0) { direct(); } if(millis()%time==0) //Stany { if(flag==0) { if(dr==true){tempx=x[0]+3;tempy=y[0];} if(dl==true){tempx=x[0]-3;tempy=y[0];} if(du==true){tempy=y[0]-3;tempx=x[0];} if(dd==true){tempy=y[0]+3;tempx=x[0];} } flag=0; checkgame(); checkegg(); if(tempx<=0){tempx=84+tempx;} if(tempx>=84){tempx=tempx-84;} if(tempy<=0){tempy=48+tempy;} if(tempy>=48){tempy=tempy-48;} for(i=0;i<=slength;i++) //Zmiana współrzędnych { xx=x[i]; yy=y[i]; x[i]=tempx; y[i]=tempy; tempx=xx; tempy=yy; } drawsnake(); //Nowe współrzędne wężą } } void checkgame() //Kontrola gry { for(i=1;i<slength;i++) { if(x[i]==x[0] && y[i]==y[0]) { bh=EEPROM.read(1); bl=EEPROM.read(0); display.clearDisplay(); display.setTextColor(BLACK); display.setTextSize(1); display.setCursor(15, 12); display.print("Game Over"); display.setCursor(15, 30); display.print("Wynik: "); display.print(score); display.setCursor(15, 40); display.display(); beep(20, 5000); display.clearDisplay(); //Czyszczenie ekranu slength=8; //Restart wartośći score=0; time=280; redraw(); //Restart gry } } } void checkegg() //Jedzenie { if(x[0]==xegg or x[0]==(xegg+1) or x[0]==(xegg+2) or x[0]==(xegg-1)) { if(y[0]==yegg or y[0]==(yegg+1) or y[0]==(yegg+2) or y[0]==(yegg-1)) { score+=1; //Wynik slength+=1; if(time>=90) {time-=20;} display.fillRect(xegg,yegg,3,3,WHITE); //Usuwanie zjedzonego jajka display.display(); beep(35, beeptime); //Dzwięk xegg=random(1, 80); //Nowe jedzenie losowo yegg=random(1, 40); } } } void direct() //Kierunki { if(l==LOW and dr==false) //Lewy { dl=true;du=false;dd=false; tempx=x[0]-3; tempy=y[0]; flag=1; } else if(r==LOW and dl==false) //Prawy { dr=true;du=false;dd=false; tempx=x[0]+3; tempy=y[0]; flag=1; } else if(u==LOW and dd==false) { du=true;dl=false;dr=false; //Góra tempy=y[0]-3; tempx=x[0]; flag=1; } else if(d==LOW and du==false) { dd=true;dl=false;dr=false; //Dół tempy=y[0]+3; tempx=x[0]; flag=1; } else if(p==LOW) //Pauza gry na 5 sekund { display.clearDisplay(); display.setTextColor(BLACK); for(i=5;i>0;i--) { display.setCursor(30,10); display.setTextSize(1); display.print("PAUZA"); display.setCursor(40,30); display.print(i); display.display(); delay(1000); display.clearDisplay(); } redraw(); //Ta sama pozycja } } void drawsnake() //Nowe pozycje węża i jedzenia { display.fillRect(xegg,yegg,3,3,BLACK); //Nowe jedzenie display.drawCircle(x[0],y[0],1,BLACK); //Nowa głowa display.drawCircle(x[slength],y[slength],1,WHITE); //Usuwanie nadmiaru ogona display.display(); } void redraw() //Pozycja jedzenia i węża { display.fillRect(xegg,yegg,3,3,BLACK); for(i=0;i<slength;i++) { display.drawCircle(x[i],y[i],1,BLACK); } display.display(); } void beep (int freq,long tb) //Dzwięki { int x; long delayAmount = (long)(500/freq); long loopTime = (long)(tb/(delayAmount*2)); for (x=0;x<loopTime;x++) { digitalWrite(speakerPin, HIGH); delay(delayAmount); digitalWrite(speakerPin, LOW); delay(delayAmount); } delay(2); //Krótka przerwa } |
Sterowanie
Sterowanie jest bardzo proste 4 przyciski odpowiadają za kierunek poruszania się węża(góra, dół, prawo, lewo), natomiast 5 przycisk pełni funkcję pauzy.
Mechanika gry
Gra jest bardzo prosta, poruszasz się wężem i zjadasz pokarm za który otrzymujesz 1 punkt i się powiększasz. Gra staje się trudniejsza wraz z ilością zjadanego pokarmu.
Gotowe!
Jeśli zrobiłeś wszystko dobrze możesz cieszyć się grą.
Myślę, że poradnik się przyda, pozdrawiam RaV:)
Źródła: SnakeDuino, Snake Game, Nokia 5110.
Fajne:) 5-teczka!!!
bobimen: dzięki
Witaj,
Fajnie opisane. Plus za to, że analizowałeś kod. Chociaż:
digitalWrite(LEFT, HIGH); //Stany
Nie oznacza ustawienie “stanów” na pinach, ale rezystorów podciągających (PULL_UP). Tylko dzięki temu Twoje klawisze nie szaleją:)
Wydaje mi się, że trochę zatrzymałeś się w pół kroku… W stosunku do oryginalnych projektów (i tu chwała Ci za podanie źródeł) można było wiele zrobić. Dla przykładu – podłączenie buzzera. To nie jest najszczęśliwszy sposób na rozwiązanie tego problemu. Buzzer potrafi “wyciągnąć” trochę prądu i przez to zasilanie go z pinu cyfrowego nie jest… zalecane – nawet jeżeli dodałeś rezystor. Lepiej to zrobić na tranzystorze – jeden element i 3 kabelki więcej, a zrobi różnicę. A może joystick? Jakaś obudowa?
Kod też można usprawnić – jak pewnie zauważyłeś po skompilowaniu zajmuje 80% pamięci zmiennych. Są tam duże tablice, brzmi jak wyzwanie!
Podsumowując – doceniam Twoje zaangażowanie, widać, że popracowałeś nad tekstem, plus za podanie źródeł – przydałoby się więcej Twojej inwencji:) Ten tekst traktuję jak wstęp, czekam na część #2:)
Pozdrawiam.
@Elektronika Bez Spięcia: Cześć, słuszne uwagi, pomyślę nad 2 częścią. Pozdrawiam.
“Kod też można usprawnić – jak pewnie zauważyłeś po skompilowaniu zajmuje 80% pamięci zmiennych.”
Z tym by optymalizować różne kody, zgodzę się w 100%
Jednak nie widzę problemu w tym, by pamięć wykorzystywać do tego do czego została stworzona
Mówienie, że to źle, że 80% pamięci jest zapełnione w końcowym projekcie jest przerostem formy nad treścią
Gdyby to było w połowie projektu – to tutaj był by problem, jednak przy skończonym projekcie nie widzę w tym nic złego
Już jutro druga część- obudowa!
Witam,
artykuł bardzo dobry chociaż pragnę zwrócić Ci uwagę na jedną rzecz – wyświetlacz z nokia 5110 powinien być zasilany napięciem 2,7-3,3V. Ty tutaj podłączasz go pod 5V (poza podświetleniem). Mimo że na Arduino UNO masz możliwość zasilenia 3,3V to mimo wszystko polecam zastosowanie rezystorów. Wiem po sobie bo niedawno kupiłem właśnie taki wyświetlacz i w sumie nie podziałał mi dłużej niż 24 godziny :/ Cała reszta cacy i gratulacje artykułu! Pozdrawiam!
Można zamienić płytkę na nano? Bo jeżeli można je zamienić, to spoko, bo widzę, że to fajny projekt jak na początek zabawy z arduino. Tak. Jak mi przyjdzie arduino, zacznę się w to bawić jako kompletny laik
oczywiście że można(https://majsterkowo.pl/snake-na-arduino-2-obudowa/)
Mam już Arduino. Wgrałem program, i teoretycznie działa. Nie mam rezystorów, więc praca zostaje zawieszona. Nie chcę zepsuć na starcie, bo nie będę wiedział co jest przyczyną. Nie mam też niestety multiszlifierki, ale to też mam w planach kupić. Także pomału do celu dążę. Dziękuję ci za pomoc ;)
Spaliłem arduino. Powie ktoś, jak podłączyć nano r3? atmega 328p?
Jak podłączyłeś? Pokaż dokładne zdjęcie.
Załóż temat na forum, w kategorii “projekty z bloga”. Tam będzie łatwiej pomóc
Założyłem temat i dodałem zdjęcia
Witam, czy buzzer musi być podłączony czy nie koniecznie ?