#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
}
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 ?