Sommario:
Video: Gioco del serpente OLED Arduino: 3 passaggi
2024 Autore: John Day | [email protected]. Ultima modifica: 2024-01-30 10:02
Ciao e benvenuto, ai nostri istruttori su come creare e Arduino OLED Game, questo progetto è nato mentre stavamo tentando di realizzare il nostro primo gioco in assoluto con un Arduino, quindi, abbiamo pensato quale fosse migliore per iniziare rispetto al classico Nokia Snake (beh a almeno un clone di serpente:)).
Di cosa avrai bisogno
Forniture
Arduino UNO o clone
Display OLED
4 diodi
Resistenza da 500-1k
4 pulsanti del controller
Cicalino piezo passivo
opzionale
Pane senza saldatura
Si prega di notare che questi collegamenti sono solo per esempio
Passaggio 1: il circuito
Nell'immagine sopra puoi vedere il nostro circuito, usiamo il pin d3 su arduino come pin di richiesta di interrupt in modo che l'arduino dia priorità alla lettura degli ingressi del controller che sono d4 d5 d6 d7. Le basi del circuito sono che viene premuto un pulsante di direzione che va alto 5v questo attiva il pin di richiesta di interruzione (filo viola d3) e un pin di direzione corrispondente, la funzione di interruzione chiama una funzione di direzione di aggiornamento e quel codice sposta il serpente di conseguenza. Il pin 9 viene utilizzato come pin del suono in quanto è un PWM (~ modulazione di larghezza di impulso) che è collegato direttamente a un piezo 5v sul pin + e il - torna a 0v/massa.
(Cordiali saluti su arduino uno e cloni solo d2 e d3 possono fungere da pin di richiesta di interruzione).
Perni di direzione:
d4 Su ARANCIO
d5 Giù ROSA
d6 BLU sinistro
d7 MARRONE destro
d9 suono GRIGIO
Ogni pulsante ha un ingresso di connessione in 5v e un'uscita che è collegata prima al rispettivo ingresso digitale sull'arduino, questa stessa uscita di ogni pulsante è poi collegata al proprio diodo, utilizziamo i diodi per interrompere il ritorno di tensione attraverso il altri pulsanti e attivandoli. All'estremità del catodo (-) di tutti e 4 i diodi li uniamo insieme per creare una giunzione di uscita che si collega a d3 e quindi attraverso un resistore a 0v/terra per abbassare i pin di arduino in modo da non lasciare i pin flottanti quando non sono attivato.
(Cordiali saluti, un pin flottante può ricevere una tensione fantasma e causare un comportamento insolito)
2 pin analogici vengono utilizzati per pilotare il display, questi sono i pin i2c dell'hardware arduino.
A5 è collegato a SCL GIALLO
A4 è collegato a SDA GREEN
L'uscita +5v e 0v (terra) dall'arduino viene utilizzata come fonte di alimentazione per l'intero circuito che può essere alimentato tramite usb o caricatore del telefono.
Passaggio 2: il codice
//--------- Giochi ANJAWARE SNAKE Con l'aiuto dei popoli della rete --------------- -------
#includere
#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // display set (larghezza, altezza) Adafruit_SSD1306 display(128, 64); // definisci i pin di input questi sono i pin sull'arduino non cambiano mai quindi #define #define INTPIN 3 // solo i pin 2 e 3 possono essere pin di interruzione su UNO #define UPPIN 4 // questi sono pin collegati all'interruttore pertinente #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // definisce le direzioni #define DIRUP 1 // questi valori sono ciò che il "serpente" guarda per decidere- #define DIRDOWN 2 // la direzione in cui viaggerà il serpente # define DIRLEFT 3 #define DIRRIGHT 4
// imposta le variabili del pulsante
// volitile cos abbiamo bisogno che si aggiorni con l'interrupt, quindi può essere qualsiasi bit del valore del ciclo
// non è mai maggiore di 4 quindi necessita solo di 8bit int per risparmiare risorse volatile uint8_t buttonpressed=0; bool butup=0; bool butdown=0; // usiamo questo per impostare true per "rilevare" quale direzione ha premuto bool butleft=0; bool butright=0;
// interi serpente
byte snakePosX[30]; // array per creare il corpo del byte snake snakePosY[30];
int serpenteX=30; // posizione della testa di serpente
int serpenteY=30; int dimensione serpente=1; // conteggio delle dimensioni del serpente limitato alla dimensione dell'array
// mondo intero
uint8_t worldMinX=0; // questi fissano i limiti dell'area di gioco
uint8_t worldMaxX=128; uint8_t worldMinY=10; uint8_t worldMaxY=63;
// raccoglie scran(cibo) e la posizione di scran
bool scranAte =0; uint8_t scranPosX=0; uint8_t scranPosY=0;
// variabili di punteggio
punteggio lungo=0; punteggio lungo=30; // imposta il punteggio più alto su 3 collect come punto di partenza
//------------- questo è ciò che esegue l'interrupt all'aumento di tensione ------------ -------------
void interruptpressed() { delay(150); // leggero ritardo per l'aggiunta della protezione "rimbalzo" updatedirection(); } // ------------------ aggiorna il valore della direzione dalla pressione del pulsante ------------------ void updaterection() { // Serial.println("direzione aggiornamento"); butup=digitalRead(UPPIN); // controlla quale input è andato alto e imposta il bool pertinente true butdown=digitalRead(DWNPIN); butleft=digitalRead(LFTPIN); butright=digitalRead(RHTPIN); // queste istruzioni if controllano quale input è andato alto e inserisce il valore pertinente nella variabile "buttonpressed" //, questa variabile determina la direzione del movimento if(butup==true) { buttonpressed=DIRUP; // Serial.println("SU premuto"); // Serial.println(buttonpressed); butup=falso; tono(SND, 1500, 10); } if(butdown==true) { buttonpressed=DIRDOWN; // Serial.println("GI premuto"); // Serial.println(buttonpressed); butdown=false; tono(SND, 1500, 10); }
if(butleft==true)
{ buttonpressed=DIRLEFT; // Serial.println("SINISTRO premuto"); // Serial.println(buttonpressed); butleft=false; tono(SND, 1500, 10); } if(butright==true) { buttonpressed=DIRRIGHT; // Serial.println("premuto a DESTRA"); // Serial.println(buttonpressed); butright=false; tono(SND, 1500, 10); } }
//------------disegna le routine di visualizzazione---- -----------------
void updateDisplay() // disegna punteggi e contorni
{ // Serial.println("Aggiorna visualizzazione");
display.fillRect(0, 0, display.width()-1, 8, NERO);
display.setTextSize(0); display.setTextColor(BIANCO); // disegna i punteggi display.setCursor(2, 1); display.print("Punteggio:"); display.print(String(playscore, DEC)); display.setCursor(66, 1); display.print("Alto:"); display.print(String(punteggio alto, DEC)); // disegna l'area di gioco // pos 1x, 1y, 2x, 2y, color display.drawLine(0, 0, 127, 0, WHITE); // bordo in alto display.drawLine(63, 0, 63, 9, WHITE); // separatore di punteggio display.drawLine(0, 9, 127, 9, WHITE); // sotto il bordo del testo display.drawLine(0, 63, 127, 63, WHITE); // bordo inferiore display.drawLine(0, 0, 0, 63, WHITE); // bordo sinistro display.drawLine(127, 0, 127, 63, WHITE); //bordo destro
}
//------------------------------------ aggiorna l'area di gioco ------------------------- --------------------
void updateGame() // questo aggiorna la visualizzazione dell'area di gioco
{ display.clearDisplay();
display.drawPixel(scranPosX, scranPosY, WHITE);
scranAte = scranFood();
// controlla le routine del serpente
if (outOfArea()||selfCollision())
{ game Over(); }
// mostra serpente
for(int i=0;i0;i--) { snakePosX = snakePosX[i-1]; serpentePosY = serpentePosY[i-1]; } // aggiunge un pixel in più al serpente if(scranAte) { snakeSize+=1; snakePosX[snakeSize-1]=snakeX; snakePosY[snakeSize-1]=serpenteY; }
switch (pulsante premuto) // era snakeDirection
{ case DIRUP: snakeY-=1; rottura; caso DIRDOWN: serpenteY+=1; rottura; caso DIRLEFT: snakeX-=1; rottura; case DIRRIGHT: snakeX+=1; rottura; } snakePosX[0] = snakeX; serpentePosY[0] = serpenteY; updateDisplay(); display.display(); // --------------------- posiziona lo scran -------------------
vuoto placeScran()
{ scranPosX=random(worldMinX+1, worldMaxX-1); scranPosY=random(worldMinY+1, worldMaxY-1); } //--------- SCRAN ATE POINT UP ---------------- bool scranFood() { if(snakeX==scranPosX&&snakeY==scranPosY) { playcore=playscore+10; tono(SND, 2000, 10); updateDisplay(); placeScran(); ritorno 1; } else { restituisce 0; } } //--------------------- fuori zona---------------------- bool outOfArea() { return snakeX =worldMaxX ||snakeY=worldMaxY; } //---------------------- game Over----------------------- --- void gameOver() { uint8_t rectX1, rectY1, rectX2, rectY2; rectX1=38; rectY1=28; rectX2=58; rectY2=12; display.clearDisplay(); display.setCursor(40, 30); display.setTextSize(1); tono (SND, 2000, 50); display.print("GIOCO"); tono(SND, 1000, 50); display.print("SOPRA"); if(playscore>=highscore) //controlla se il punteggio è più alto del punteggio più alto { highscore=playscore; // istruzione single if per aggiornare il punteggio più alto } for(int i=0;i<=16;i++) // questo serve per disegnare i rettangoli intorno al game over { display.drawRect(rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println("se ciclo"); display.display(); rectX1-=2; // sposta di 2 pixel rectY1-=2; rectX2+=4; // sposta di 2 pixel dall'ultimo punto rectY2+=4; tono(SND, i*200, 3); } display.display(); //Cancella schermo dopo la fama su rectX1=0; // imposta la posizione iniziale della riga rectY1=0; rectX2=0; rectY2=63; for (int i =0;i<=127;i++) { uint8_t cnt=0; display.drawLine(rectX1, rectY1, rectX2, rectY2, BLACK); rectX1++; rectX2++; display.display(); } display.clearDisplay(); punteggio di riproduzione=0; // resetta i dettagli del serpente e del giocatore snakeSize=1; snakeX=display.width()/2; serpenteY=display.altezza()/2; waitForPress(); // aspetta che il giocatore inizi il gioco } //-----------attendere il ciclo delle pressioni ---------- --------------- void waitForPress() { bool in attesa=0; // il ciclo termina quando questo è vero display.clearDisplay(); while(attesa==0) { drawALineForMe(WHITE); // disegna una linea bianca casuale drawALineForMe(BLACK); // traccia una linea nera casuale in modo che lo schermo non riempia completamente il bianco display.fillRect(19, 20, 90, 32, BLACK); // sfondo vuoto per il testo display.setTextColor(WHITE); display.setCursor(35, 25); display.setTextSize(2); // carattere più grande display.println("SNAKE"); // x y w h r col display.drawRoundRect(33, 22, 62, 20, 4, WHITE); // border Snake display.drawRect(19, 20, 90, 32, WHITE); // riquadro del bordo - 3 display.setCursor(28, 42); display.setTextSize(0); // font torna al normale display.println("premi un tasto qualsiasi"); display.display(); in attesa = digitalRead(INTPIN); // controlla se il tasto premuto in attesa cambierà in 1 mentre si preme il pulsante = 0; // pulsante di ripristino premere } } //------DRAW un colore di input di riga casuale uint8_t-------------- ----- void drawALineForMe(uint8_t clr) { uint8_t riga1X, riga1Y, riga2X, riga2Y=0; // imposta le coordinate casuali per una linea e poi disegnala // variabile non meno non più line1X = random(worldMinX+1, worldMaxX-1); line1Y = random(worldMinY+1, worldMaxY-1); riga2X = random(worldMinX+1, worldMaxX-1); riga2Y = random(worldMinY+1, worldMaxY-1); display.drawLine(riga1X, riga1Y, riga2X, riga2Y, clr); } //------------------------------------- rilevamento delle collisioni -------- -----------------------
for(byte i=4;i<snakeSize;i++) { if(snakeX==snakePosX&&snakeY==snakePosy) { return 1; tono(SND, 2000, 20); tono(SND, 1000, 20); } restituisce 0; }
//-------------------------------- IMPOSTARE--------------- -----------------
void setup() { delay(100); // basta dare agli oggetti la possibilità di "avviarsi" // Serial.begin(9600); // deseleziona questo se vuoi vedere le uscite seriali display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // inizia con un display pulito display.setTextColor(WHITE); // imposta la dimensione della rotazione del colore del testo ecc. display.setRotation(0); display.setTextWrap(false); display.dim(0); // imposta la luminosità del display pinMode(INTPIN, INPUT); // imposta le porte corrette agli input pinMode(UPPIN, INPUT); pinMode(DWNPIN, INPUT); pinMode(LFTPIN, INGRESSO); pinMode(RHTPIN, INPUT); // questo è il comando di interrupt questo "ferma" l'arduino per leggere gli input //comando-funzione-pin-funzione per eseguire-condizione sul pin attachInterrupt(digitalPinToInterrupt(INTPIN), interruptpressed, RISING); // Serial.println("Installazione superata"); waitForPress(); // mostra la schermata di avvio del serpente placeScran(); // posiziona il primo pezzo di cibo } //-------MAIN LOOP--- ---------------------- void loop() { updateGame(); // questa funzione è ciò che porta il codice principale }
Passaggio 3:
Consigliato:
NeoPixel Matrix:Gioco del serpente: 4 passaggi
NeoPixels Matrix:Snake Game: Ricordi ancora il gioco del serpente che abbiamo giocato sulla nostra scatola di gioco o sul cellulare durante la nostra infanzia? Oggi impareremo come creare un gioco di serpenti con NeoPixel Matrix 8*8. Scegliamo Arduino uno come centro di controllo e modulo di breakout Joystick per co
Controller di gioco fai-da-te basato su Arduino - Controller di gioco Arduino PS2 - Giocare a Tekken con il gamepad Arduino fai da te: 7 passaggi
Controller di gioco fai-da-te basato su Arduino | Controller di gioco Arduino PS2 | Giocare a Tekken con il gamepad Arduino fai da te: Ciao ragazzi, giocare è sempre divertente, ma giocare con il tuo controller di gioco personalizzato fai-da-te è più divertente. Quindi creeremo un controller di gioco usando arduino pro micro in queste istruzioni
Gioco del serpente: 4 passaggi
Snake Game: Ciao ragazzi, oggi vi mostrerò come creare un semplice gioco di serpenti in Python e stupire gli amici in questa vacanza. Questo è molto semplice, basta installare Python 3 e pygame. In questo tutorial ho aggiunto un video su come installare pygame. Dopo
Controller di gioco Arduino + Gioco Unity: 5 passaggi
Controller di gioco Arduino + Gioco Unity: in questo tutorial ti mostrerò come costruire/programmare un controller di gioco Arduino che può connettersi a unity
Gioco del serpente in C: 8 passaggi
Gioco di Snake in C: Il gioco Snake era popolare nei vecchi telefoni cellulari che possono essere facilmente sviluppati usando il programma c. Per costruire questo progetto è necessaria una conoscenza di base della sintassi c. Esempio: ciclo for, ciclo while, ecc. Con la creazione di questo tipo di progetto di gioco, la tua programmazione