Table des matières:
Vidéo: Arduino OLED Snake Game : 3 étapes
2024 Auteur: John Day | [email protected]. Dernière modifié: 2024-01-30 09:07
Salut et bienvenue, dans nos instructables sur la façon de créer un jeu arduino OLED, ce projet a vu le jour alors que nous essayions de créer notre tout premier jeu avec un arduino, soooo, nous avons pensé par où mieux commencer que le classique de nokia Snake (enfin à au moins un clone de serpent:)).
Ce dont vous aurez besoin
Fournitures
Arduino UNO ou clone
Affichage OLED
4 diodes
Résistance 500-1k
4 boutons de manette
Buzzer piézo passif
optionnel
Planche à pain sans soudure
Veuillez noter que ces liens sont à titre d'exemple seulement
Étape 1: Le circuit
Dans l'image ci-dessus, vous pouvez voir notre circuit, nous utilisons la broche d3 sur l'arduino comme broche de demande d'interruption afin que l'arduino donne la priorité à la lecture des entrées du contrôleur qui sont d4 d5 d6 d7. Les bases du circuit sont qu'un bouton de direction est enfoncé qui passe à 5v élevé, cela active la broche de demande d'interruption (fil violet d3) et une broche de direction correspondante, la fonction d'interruption appelle une fonction de direction de mise à jour et ce code déplace le serpent en conséquence. La broche 9 est utilisée comme broche du son car il s'agit d'un PWM (~ modulation de largeur d'impulsion) qui est connecté directement à un piézo 5v sur la broche + et le - revient à 0v/masse.
(Pour info sur l'arduino uno et les clones, seuls d2 et d3 peuvent servir de broches de demande d'interruption).
Goupilles de direction:
d4 vers le haut ORANGE
d5 Bas ROSE
d6 Gauche BLEU
d7 Droite MARRON
d9 son GRIS
Chaque bouton a une entrée de connexion en 5v et une sortie qui est connectée d'abord à leur entrée numérique respective sur l'arduino, cette même sortie de chaque bouton est ensuite connectée à sa propre diode, nous utilisons les diodes pour arrêter le retour de tension vers le d'autres boutons et en les activant. À l'extrémité cathode (-) des 4 diodes, nous les joignons ensemble pour créer une jonction de sortie qui se connecte à d3, puis à travers la résistance a à 0v/terre pour tirer les broches arduino bas afin de ne pas laisser de broches flottantes lorsqu'elles ne sont pas activé.
(Pour info, une broche flottante peut recevoir une tension fantôme et provoquer un comportement inhabituel)
2 broches analogiques sont utilisées pour piloter l'affichage, ce sont les broches matérielles arduino i2c.
A5 est connecté à SCL JAUNE
A4 est connecté à SDA GREEN
La sortie +5v et 0v (terre) de l'arduino est utilisée comme source d'alimentation pour l'ensemble du circuit qui peut être alimenté par USB ou par chargeur de téléphone.
Étape 2: le code
//------------------------- ANJAWARE SNAKE Games Avec l'aide des peuples du net --------------- -------
#comprendre
#include // https://github.com/adafruit/Adafruit-GFX-Library #include // https://github.com/adafruit/Adafruit-GFX-Library // ensemble d'affichage (largeur, hauteur) Adafruit_SSD1306 display(128, 64); // définir les broches d'entrée ce sont les broches de l'arduino elles ne changent jamais donc #define #define INTPIN 3 // seules les broches 2 et 3 peuvent être des broches d'interruption sur UNO #define UPPIN 4 // ce sont des broches connectées au commutateur pertinent #define DWNPIN 5 #define LFTPIN 6 #define RHTPIN 7 #define SND 9 // définit les directions #define DIRUP 1 // ces valeurs sont ce que le "serpent" regarde pour décider- #define DIRDOWN 2 // la direction dans laquelle le serpent se déplacera # définir DIRLEFT 3 #définir DIRRIGHT 4
// définir les variables du bouton
// volitile car nous avons besoin qu'il soit mis à jour avec l'interruption, il peut donc s'agir de n'importe quel bit de valeur de cycle
// n'est jamais supérieur à 4 donc n'a besoin que de 8 bits int pour économiser les ressources volatile uint8_t buttonpressed=0; bool butup=0; bool butdown=0; // nous l'utilisons pour définir true pour "détecter" la direction enfoncée bool butleft=0; bool butright=0;
// ints de serpent
octet snakePosX[30]; // tableau pour créer le corps de l'octet serpent snakePosY[30];
int serpentX=30; // position de la tête de serpent
int serpentY=30; int SnakeSize=1; // nombre de tailles de serpent limité à la taille du tableau
// monde entier
uint8_t worldMinX=0; // ceux-ci définissent les limites de l'aire de jeu
uint8_t worldMaxX=128; uint8_t worldMinY=10; uint8_t worldMaxY=63;
// collecte le scran (nourriture) et la position du scran
bool scranAte =0; uint8_t scranPosX=0; uint8_t scranPosY=0;
// note les variables
score de jeu long=0; long meilleur score = 30; // définir le score élevé sur 3 collecter comme point de départ
//--------------------------- c'est ce que l'interruption exécute sur la montée en tension ------------ -------------
void interruptpressed() { delay(150); // léger délai pour l'ajout de la protection "rebond" updatedirection(); } // ------------------ mettre à jour la valeur de direction en appuyant sur le bouton ----------------- void updatedirection() { // Serial.println("updatingdirection"); butup=digitalRead(UPPIN); // vérifie quelle entrée est élevée et définit le bool pertinent true butdown=digitalRead(DWNPIN); butleft=digitalRead(LFTPIN); butright=digitalRead(RHTPIN); // ces instructions if regardent quelle entrée est élevée et entrent la valeur appropriée dans la variable "buttonpressed" // cette variable dicte la direction du mouvement if(butup==true) { buttonpressed=DIRUP; // Serial.println("UP enfoncé"); // Serial.println (bouton pressé); butup=false; tonalité (SND, 1500, 10); } if(butdown==true) { buttonpressed=DIRDOWN; // Serial.println("DOWN appuyé"); // Serial.println (bouton pressé); butdown=false; tonalité (SND, 1500, 10); }
if(butleft==true)
{ bouton enfoncé = DIRECTION GAUCHE; // Serial.println("GAUCHE enfoncé"); // Serial.println (bouton pressé); butleft=false; tonalité (SND, 1500, 10); } if(butright==true) { buttonpressed=DIRRIGHT; // Serial.println("DROITE enfoncé"); // Serial.println (bouton pressé); butright=false; tonalité (SND, 1500, 10); } }
//-------------------------- dessine les routines d'affichage------------------ -----------------
void updateDisplay() // dessine les partitions et les contours
{ // Serial.println("Mettre à jour l'affichage");
display.fillRect(0, 0, display.width()-1, 8, NOIR);
display.setTextSize(0); display.setTextColor(BLANC); // dessine les scores display.setCursor(2, 1); display.print("Score:"); display.print(String(playscore, DEC)); display.setCursor(66, 1); display.print("Élevé:"); display.print(String(meilleur score, DEC)); // dessiner la zone de jeu // pos 1x, 1y, 2x, 2y, color display.drawLine(0, 0, 127, 0, WHITE); // bordure supérieure display.drawLine(63, 0, 63, 9, WHITE); // séparateur de scores display.drawLine(0, 9, 127, 9, WHITE); // sous la bordure de texte display.drawLine(0, 63, 127, 63, WHITE); // bordure inférieure display.drawLine(0, 0, 0, 63, WHITE); // bordure gauche display.drawLine(127, 0, 127, 63, WHITE); // bordure droite
}
//----------------------------------- mise à jour de la zone de jeu ---------- --------------------
void updateGame() // ceci met à jour l'affichage de la zone de jeu
{ display.clearDisplay();
display.drawPixel(scranPosX, scranPosY, BLANC);
scranAte = scranNourriture();
// vérifier les routines de serpent
if (outOfArea()||selfCollision())
{ jeu terminé(); }
// affiche le serpent
for(int i=0;i0;i--) { SnakePosX = SnakePosX[i-1]; serpentPosY = serpentPosY[i-1]; } // ajoute un pixel supplémentaire au serpent if(scranAte) { snakeSize+=1; SnakePosX[snakeSize-1]=snakeX; SnakePosY[snakeSize-1]=serpentY; }
switch (bouton pressé) // était snakeDirection
{ cas DIRUP: snakeY-=1; Pause; cas DIRDOWN: serpentY+=1; Pause; cas VERS LA GAUCHE: serpentX-=1; Pause; cas DIRRIGHT: serpentX+=1; Pause; } serpentPosX[0] = serpentX; serpentPosY[0] = serpentY; mise à jourAffichage(); display.display(); // --------------------- place le scran -------------------
void placeScran()
{ scranPosX=random(worldMinX+1, worldMaxX-1); scranPosY=random(worldMinY+1, worldMaxY-1); } //------------------------ POINT DE SCRAN AT UP ---------------- bool scranFood() { if(snakeX==scranPosX&&snakeY==scranPosY) { playscore=playscore+10; tonalité (SND, 2000, 10); mise à jourAffichage(); placeScran(); retour 1; } else { return 0; } } //--------------------- hors de la zone---------------------- bool outOfArea() { return snakeX =worldMaxX ||snakeY=worldMaxY; } //---------------------- jeu terminé----------------------- --- 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); tonalité (SND, 2000, 50); display.print("JEU "); tonalité (SND, 1000, 50); display.print("OVER"); if(playscore>=highscore) //vérifier si le score est supérieur au score élevé { highscore=playscore; //instruction if unique pour mettre à jour le score élevé } for(int i=0;i<=16;i++) // ceci consiste à dessiner des rectanlges autour de la partie { display.drawRect(rectX1, rectY1, rectX2, rectY2, WHITE); Serial.println("si boucle"); display.display(); rectX1-=2; // décalage de 2 pixels rectY1-=2; rectX2+=4; // décalage de plus de 2 pixels à partir du dernier point rectY2+=4; tonalité (SND, i*200, 3); } display.display(); //Effacer l'écran après la célébrité sur rectX1=0; // définit la position de départ de la ligne rectY1=0; rectX2=0; rectY2=63; for (int i =0;i<=127;i++) { uint8_t cnt=0; display.drawLine(rectX1, rectY1, rectX2, rectY2, NOIR); rectX1++; rectX2++; display.display(); } display.clearDisplay(); score de lecture=0; // réinitialiser les détails du serpent et du joueur snakeSize=1; snakeX=display.width()/2; serpentY=affichage.hauteur ()/2; waitForPress(); // attend que le joueur commence le jeu } //------------------------ attend la boucle de presse ---------- --------------- void waitForPress() { bool wait=0; // la boucle se termine quand c'est vrai display.clearDisplay(); while(en attente==0) { drawALineForMe(WHITE); // dessine une ligne blanche aléatoire drawALineForMe(BLACK); // dessine une ligne noire aléatoire pour que l'écran ne remplisse pas complètement le blanc display.fillRect(19, 20, 90, 32, BLACK); // arrière-plan vide pour le texte display.setTextColor(WHITE); display.setCursor(35, 25); display.setTextSize(2); // police plus 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); // cadre de bordure - 3 display.setCursor(28, 42); display.setTextSize(0); // la police revient à la normale display.println("appuyez sur n'importe quelle touche"); display.display(); en attente = digitalRead(INTPIN); // vérifie si l'attente de la touche enfoncée passe à 1 et se termine lorsque buttonpressed=0; // bouton de réinitialisation appuyez sur } } //----------------------------------- DESSINEZ une couleur d'entrée de ligne aléatoire uint8_t -------------- ----- void drawAlineForMe(uint8_t clr) { uint8_t line1X, line1Y, line2X, line2Y=0; // définir des coordonnées aléatoires pour une ligne puis la dessiner // variable pas moins pas plus line1X = random(worldMinX+1, worldMaxX-1); line1Y = random(worldMinY+1, worldMaxY-1); line2X = random(worldMinX+1, worldMaxX-1); line2Y = random(worldMinY+1, worldMaxY-1); display.drawLine(line1X, line1Y, line2X, line2Y, clr); } //------------------------------------- détection de collision -------- -----------------------
for(byte i=4;i<snakeSize;i++) { if(snakeX==snakePosX&&snakeY==snakePosy) { return 1; tonalité (SND, 2000, 20); tonalité (SND, 1000, 20); } renvoie 0; }
//-------------------------------- METTRE EN PLACE--------------- -------------------------------
void setup() { delay(100); // juste donner aux choses une chance de "démarrer" // Serial.begin(9600); // décochez cette case si vous voulez voir les sorties série display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // commencer avec un affichage propre display.setTextColor(WHITE); // configurer la taille de rotation de la couleur du texte, etc. display.setRotation(0); display.setTextWrap(false); display.dim(0); // définit la luminosité de l'affichage pinMode(INTPIN, INPUT); // définit les ports corrects sur les entrées pinMode(UPPIN, INPUT); pinMode(DWNPIN, INPUT); pinMode(LFTPIN, INPUT); pinMode(RHTPIN, INPUT); // il s'agit de la commande d'interruption qui "arrête" l'arduino pour lire les entrées // commande-fonction-pin-fonction à exécuter-condition sur la broche attachInterrupt(digitalPinToInterrupt(INTPIN), interruptpressed, RISING); // Serial.println("Configuration réussie"); waitForPress(); // affiche l'écran de démarrage du serpent placeScran(); // place le premier morceau de nourriture } //--------------------- BOUCLE PRINCIPALE----------------- ---------------------- boucle vide() { updateGame(); // cette fonction est ce qui porte le code principal }
Étape 3:
Conseillé:
Reckless Racer Arduino OLED Game, AdafruitGFX et Bitmaps Basics: 6 Steps
Reckless Racer Arduino OLED Game, AdafruitGFX et Bitmaps Basics: Dans ce didacticiel, nous verrons comment utiliser les bitmaps à l'aide de la bibliothèque Adafruit_GFX.c comme une sorte de sprites dans un jeu. Le jeu le plus simple auquel nous puissions penser est un jeu de voiture à changement de voie à défilement latéral, à la fin notre bêta-testeur et assistant codeur de
Snake : la machine inutile : 5 étapes
Snake : la machine inutile : Vous savez quand vous étiez enfant et que vous jouiez au serpent sur votre Nokia ? À un certain moment, le serpent commençait à courir après sa propre queue, et c'est à ce moment-là que vous saviez que le jeu était sur le point de se terminer. On a décidé d'en faire un robot, seulement, le jeu jamais
ESP32 VGA Snake : 5 étapes
ESP32 VGA Snake : dans ce instructable je vais montrer comment reproduire un jeu d'arcade classique - Snake - avec un ESP32, avec la sortie pour un moniteur VGA. La résolution est de 640x350 pixels, en 8 couleurs. J'ai déjà fait une version avec un Arduino Uno (voir ici), mais
Arduino Snake sur un moniteur VGA : 5 étapes
Arduino Snake sur un moniteur VGA : Eh bien… j'ai acheté un Arduino. Au départ, l'investissement était motivé par quelque chose qui intéresserait ma fille à la programmation. Cependant, il s'est avéré que cette chose était plus amusante à jouer pour moi. Après avoir joué avec la fabrication de LED
Comment connecter une table de mixage et un microphone Snake à un système audio : 3 étapes
Comment connecter une table de mixage et un microphone Snake à un système de son : La vidéo couvre les bases de la connexion d'une table de mixage audio (table de mixage ou console) à un système de son à l'aide d'un câble de microphone Snake. Il couvre le microphone et les connexions d'envoi. Pour plus d'informations : http://proaudiotraining.com