Taula de continguts:

Joc de serp OLED Arduino: 3 passos
Joc de serp OLED Arduino: 3 passos

Vídeo: Joc de serp OLED Arduino: 3 passos

Vídeo: Joc de serp OLED Arduino: 3 passos
Vídeo: Baby Kapuzenhandtuch Nähen Handtuch mit Schlappohren Schablone erstellen #UniKati89 2024, De novembre
Anonim
Joc de serp OLED Arduino
Joc de serp OLED Arduino

Hola i benvinguts, als nostres instruccions sobre com fer un joc OLED arduino, aquest projecte va sorgir quan intentàvem fer el nostre primer joc amb un arduino, doncs, vam pensar on era millor començar que el clàssic Nokia Snake (bé a almenys un clon de serp:)).

El que necessitareu

Subministraments

Arduino UNO o clon

Pantalla OLED

4 díodes

500-1k resistència

4 botons de controlador

Zumbador Piezo passiu

opcional

BreadBoard sense soldadura

Tingueu en compte que aquests enllaços són només per exemple

Pas 1: el circuit

El Circuit
El Circuit

A la imatge anterior podeu veure el nostre circuit, fem servir el pin d3 a l’arduino com a pin de sol·licitud d’interrupció perquè l’arduino doni prioritat a la lectura de les entrades del controlador que són d4 d5 d6 d7. El bàsic del circuit és que es prem un botó de direcció que augmenta 5v, activant el pin de sol·licitud d’interrupció (fil morat d3) i un pin de direcció corresponent, la funció d’interrupció crida una funció de direcció d’actualització i aquest codi mou la serp en conseqüència. El pin 9 s'utilitza com a pin de so, ja que és un PWM (~ modulació d'amplada de pols) que es connecta directament a un piezoelèctric de 5v al pin + i el - torna a 0v / terra.

(FYI a l'arduino uno i els clons només d2 i d3 poden actuar com a pins de sol·licitud d'interrupció).

Clavilles de direcció:

d4 Pujar TARONJA

d5 A baix ROSA

d6 Esquerra BLAU

d7 Dret MARRÓ

so d9 GRIS

Cada botó té una entrada de connexió de 5V i una sortida que es connecta primer a la seva entrada digital respectiva a l’arduino, aquesta mateixa sortida de cada botó es connecta al seu propi díode, utilitzem els díodes per aturar la volta de volta a la altres botons i activar-los. A l'extrem càtode (-) de tots els 4 díodes, els unim per crear una unió de sortida que es connecta a d3 i, a continuació, a través de la resistència a 0v / terra per treure els pins d'arduino de manera que no deixin els pins flotants quan no activat.

(FYI un pin flotant pot rebre tensió fantasma i provocar un comportament inusual)

S’utilitzen 2 pins analògics per conduir la pantalla, es tracta dels pins i2c de maquinari arduino.

A5 està connectat a SCL GROC

A4 està connectat a SDA GREEN

La sortida de + 5v i 0v (terra) de l'arduino s'utilitza com a font d'alimentació per a tot el circuit que es pot alimentar mitjançant un carregador de telèfon o usb.

Pas 2: el codi

// ------------------------ ANJAWARE SNAKE Jocs Amb ajuda de la gent de la xarxa --------------- -------

#incloure

#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // display set (width, height) Adafruit_SSD1306 display (128, 64); // defineix els pins d'entrada són els pins de l'arduino que mai canvien, de manera que #define #define INTPIN 3 // només els pins 2 i 3 poden ser interminables a UNO #define UPPIN 4 // són pins connectats tp commutador rellevant #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // defineix direccions #define DIRUP 1 // aquests valors és el que mira la "serp" per decidir- #define DIRDOWN 2 // la direcció de la serp # defineix DIRLEFT 3 #define DIRRIGHT 4

// estableix variables de botó

// volitile cos el necessitem per actualitzar-lo amb la interupt, de manera que pugui tenir qualsevol valor de cicle

// mai és superior a 4, de manera que només necessiteu 8 bits int per estalviar recursos volàtils uint8_t pressionat amb el botó = 0; bool butup = 0; bool butdown = 0; // ho fem servir per establir true per a "detectar" quina direcció es pressiona bool butleft = 0; bool butright = 0;

// ints de serps

byte snakePosX [30]; // matriu per fer cos de byte de serp snakePosY [30];

int serpX = 30; // posició del cap de serp

int serpY = 30; int serp Mida = 1; // recompte de mida de serp limitat a la mida de la matriu

// ints del món

uint8_t worldMinX = 0; // estableixen els límits de l'àrea de joc

uint8_t worldMaxX = 128; uint8_t worldMinY = 10; uint8_t worldMaxY = 63;

// recollir scran (aliment) i posició de scran

bool scranAte = 0; uint8_t scranPosX = 0; uint8_t scranPosY = 0;

// puntuacions variables

playcore llarg = 0; puntuació màxima llarga = 30; // estableix la puntuació màxima en 3 punts com a punt de partida

// --------------------------- Això és el que executa la interupt en augmentar la tensió ------------ -------------

void interruptpressed () {delay (150); // lleuger retard per a la protecció "rebot" afegida updatedirection (); } // ------------------ actualitza el valor de direcció des de prémer el botó ----------------- anul·la la direcció actualitzada () { // Serial.println ("updatingdirection"); butup = digitalRead (UPPIN); // comproveu quina entrada ha augmentat i configureu bool true butdown rellevant = digitalRead (DWNPIN); butleft = digitalRead (LFTPIN); butright = DigitalRead (RHTPIN); // si els estatemes visualitzen quina entrada ha augmentat i introdueix el valor rellevant a la variable "pulsat" // aquesta variable dicta la direcció del moviment si (butup == true) {buttonpressed = DIRUP; // Serial.println ("UP pressionat"); // Serial.println (premut amb botó); butup = fals; to (SND, 1500, 10); } if (butdown == true) {buttonpressed = DIRDOWN; // Serial.println ("DOWN pressionat"); // Serial.println (premut amb botó); butdown = fals; to (SND, 1500, 10); }

if (butleft == true)

{buttonpressed = DIRLEFT; // Serial.println ("ESQUERRA premuda"); // Serial.println (pulsat); butleft = fals; to (SND, 1500, 10); } if (butright == true) {buttonpressed = DIRRIGHT; // Serial.println ("Dret premut"); // Serial.println (pulsat); butright = fals; to (SND, 1500, 10); }}

// -------------------------- dibuixar les rutines de visualització ------------------ -----------------

void updateDisplay () // dibuixa partitures i esquemes

{// Serial.println ("Actualització de la pantalla");

display.fillRect (0, 0, display.width () - 1, 8, NEGRE);

display.setTextSize (0); display.setTextColor (BLANC); // dibuixar puntuacions display.setCursor (2, 1); display.print ("Puntuació:"); display.print (String (playscore, DEC)); display.setCursor (66, 1); display.print ("Alt:"); display.print (String (highscore, DEC)); // dibuixar àrea de joc // pos 1x, 1y, 2x, 2y, color display.drawLine (0, 0, 127, 0, BLANC); // vora molt superior display.drawLine (63, 0, 63, 9, BLANC); // separador de puntuació display.drawLine (0, 9, 127, 9, BLANC); // sota la vora del text display.drawLine (0, 63, 127, 63, BLANC); // vora inferior display.drawLine (0, 0, 0, 63, BLANC); // vora esquerra display.drawLine (127, 0, 127, 63, BLANC); // vora dreta

}

// ----------------------------------- Actualitza l'àrea de joc ---------- --------------------

void updateGame () // actualitza la visualització de l'àrea de joc

{display.clearDisplay ();

display.drawPixel (scranPosX, scranPosY, BLANC);

scranAte = scranFood ();

// comproveu les rutines de les serps

if (outOfArea () || selfCollision ())

{ fi del joc(); }

// mostrar serp

for (int i = 0; i0; i--) {snakePosX = snakePosX [i-1]; snakePosY = snakePosY [i-1]; } // afegiu un píxel addicional a la serp if (scranAte) {snakeSize + = 1; snakePosX [snakeSize-1] = serpX; snakePosY [snakeSize-1] = serpY; }

commutador (premut amb el botó) // era snakeDirection

{cas DIRUP: serp Y- = 1; trencar; cas DIRDOWN: serpY + = 1; trencar; cas DIRLEFT: serpX- = 1; trencar; cas DIRECCIÓ: serpX + = 1; trencar; } snakePosX [0] = serpX; snakePosY [0] = serpY; updateDisplay (); display.display (); // --------------------- col·loqueu el scran -------------------

void placeScran ()

{scranPosX = aleatori (worldMinX + 1, worldMaxX-1); scranPosY = aleatori (worldMinY + 1, worldMaxY-1); } // ------------------------ SCRAN ATE POINT UP ---------------- bool scranFood () {if (snakeX == scranPosX && snakeY == scranPosY) {playscore = playscore + 10; to (SND, 2000, 10); updateDisplay (); placeScran (); retorn 1; } else {return 0; }} // --------------------- fora de l'àrea ---------------------- bool outOfArea () {return snakeX = worldMaxX || snakeY = worldMaxY; } //---------------------- fi del joc----------------------- --- 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); to (SND, 2000, 50); display.print ("JOC"); to (SND, 1000, 50); display.print ("OVER"); if (playscore> = puntuació més alta) // comproveu si la puntuació és superior a la puntuació més alta {puntuació = puntuació més alta; // single if statment to update high score} for (int i = 0; i <= 16; i ++) // es tracta de dibuixar rectanlges al voltant del joc sobre {display.drawRect (rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println ("si bucle"); display.display (); rectX1- = 2; // canvieu 2 píxels rectY1- = 2; rectX2 + = 4; // canvia més de 2 píxels des del darrer punt rectY2 + = 4; to (SND, i * 200, 3); } display.display (); // Neteja la pantalla després de la fama per rectX1 = 0; // estableix la posició inicial de la línia rectY1 = 0; rectX2 = 0; rectY2 = 63; for (int i = 0; i <= 127; i ++) {uint8_t cnt = 0; display.drawLine (rectX1, rectY1, rectX2, rectY2, NEGRE); rectX1 ++; rectX2 ++; display.display (); } display.clearDisplay (); playscore = 0; // restablir detalls de la serp i del jugador snakeSize = 1; serpX = display.width () / 2; serpY = display.height () / 2; waitForPress (); // espera que el jugador comenci el joc} // ------------------------- espera que prems el bucle ---------- --------------- void waitForPress () {bool esperant = 0; // el bucle finalitza quan això és cert display.clearDisplay (); while (esperant == 0) {drawALineForMe (BLANC); // dibuixa una línia blanca aleatòria drawALineForMe (NEGRE); // dibuixeu una línia negra aleatòria perquè la pantalla no ompli completament la pantalla blanca.fillRect (19, 20, 90, 32, NEGRE); // fons en blanc per al text display.setTextColor (BLANC); display.setCursor (35, 25); display.setTextSize (2); // font més gran display.println ("SERP"); // x y w h r r display.drawRoundRect (33, 22, 62, 20, 4, BLANC); // border Snake display.drawRect (19, 20, 90, 32, BLANC); // quadre de vora - 3 display.setCursor (28, 42); display.setTextSize (0); // tornar al tipus de lletra normal a display.println ("premeu qualsevol tecla"); display.display (); esperant = Llegir digital (INTPIN); // comproveu si la tecla en espera espera canviarà a 1 final mentre es prem el botó = 0; // botó de restabliment premeu}} // -------------------- DIBUIXA una línia d'entrada aleatòria color uint8_t -------------- ----- void drawALineForMe (uint8_t clr) {uint8_t línia1X, línia1Y, línia2X, línia2Y = 0; // estableix coordenades aleatòries per a una línia i dibuixa-la // variable ni més ni menys línia1X = aleatori (worldMinX + 1, worldMaxX-1); línia1Y = aleatòria (worldMinY + 1, worldMaxY-1); línia2X = aleatòria (worldMinX + 1, worldMaxX-1); línia2Y = aleatòria (worldMinY + 1, worldMaxY-1); display.drawLine (line1X, line1Y, line2X, line2Y, clr); } // ------------------------------------- detecció de col·lisions -------- -----------------------

for (byte i = 4; i <snakeSize; i ++) {if (snakeX == snakePosX && snakeY == snakePosy ) {return 1; to (SND, 2000, 20); to (SND, 1000, 20); } retorn 0; }

// -------------------------------- CONFIGURACIÓ --------------- -------------------------------

void setup () {delay (100); // simplement doneu a les coses l'oportunitat de "arrencar" // Serial.begin (9600); // desmarqueu aquesta opció si voleu veure les sortides en sèrie display.begin (SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay (); // Comenceu amb una pantalla neta display.setTextColor (BLANC); // configureu la mida de rotació del color del text, etc. display.setRotation (0); display.setTextWrap (fals); display.dim (0); // configureu la brillantor de la pantalla pinMode (INTPIN, INPUT); // configureu els ports correctes a les entrades pinMode (UPPIN, INPUT); pinMode (DWNPIN, INPUT); pinMode (LFTPIN, INPUT); pinMode (RHTPIN, INPUT); // aquesta és l'ordre interupt que "atura" l'arduino per llegir les entrades // command-function- pin-function to execute-condition on pin attachInterrupt (digitalPinToInterrupt (INTPIN), interruptpressed, RISING); // Serial.println ("Configuració superada"); waitForPress (); // mostra la pantalla d'inici de la serp placeScran (); // col·loqueu el primer menjar} // --------------------- LLAÇ PRINCIPAL ----------------- ---------------------- bucle buit () {updateGame (); // aquesta funció és la que porta el codi principal}

Pas 3:

Recomanat: