Le jeu Tetris sur Arduino Uno avec écran OLED i2c 128×64 et boutons est un projet simple pour les débutants. Le schéma d’assemblage du jeu Tetris sur Arduino Uno avec écran est aussi simple que possible, de sorte que n’importe quel débutant sera en mesure de le répéter. Nous avons placé ici le schéma de connexion de l’écran au microcontrôleur Arduino, ainsi que le programme de création d’un jeu Tetris sur display SSD1306 OLED i2c.
Pour cette activité, nous aurons besoin:
- Arduino Uno / Arduino Nano / Arduino Mega
- oled display 128×64 i2c
- boutons-poussoirs
- buzzer
- breadboard
- fils de connexion
- librairies Adafruit_SSD1306.h, Adafruit_GFX.h
Matériel supplémentaire sur ce sujet:
Jeu Tetris Arduino avec écran OLED 128×64

| OLED i2c 0,96 | Arduino Uno | Arduino Nano | Arduino Mega |
| GND | GND | GND | GND |
| VDD | 5V | 5V | 5V |
| SDA | A4 | A4 | 20 |
| SCL | A5 | A5 | 21 |
L’écran OLED est connecté à la carte Arduino via le protocole i2c (voir le tableau de connexion de l’écran à Arduino Mega). Les boutons sont connectés aux broches numériques de la carte et les broches peuvent être modifiées si nécessaire. Les broches des boutons sont configurées en mode input_pullup, donc aucune résistance n’est nécessaire pour la connexion. Après avoir assemblé le circuit, téléchargez le code « Tetris » sur l’Arduino Uno / Nano.
Programme pour jeu Tetris Arduino avec OLED i2c
#include "Wire.h" #include "Adafruit_GFX.h" #include "Adafruit_SSD1306.h" #define WIDTH 64 // largeur de l'écran en pixels #define HEIGHT 128 // hauteur de l'écran en pixels #define BUZZER 12 // port de connexion du buzzer #define left 2 // port de connexion du boutons #define right 5 #define change 3 #define down 4 Adafruit_SSD1306 display(HEIGHT, WIDTH, &Wire, -1); // matrice de la forme "S" const char pieces_S_l[2][2][4] = {{ {0, 0, 1, 1}, {0, 1, 1, 2} }, { {0, 1, 1, 2}, {1, 1, 0, 0} }}; // matrice de la forme "S" const char pieces_S_r[2][2][4] = {{ {1, 1, 0, 0}, {0, 1, 1, 2} }, { {0, 1, 1, 2}, {0, 0, 1, 1} }}; // matrice de la forme "L" const char pieces_L_l[4][2][4] = {{ {0, 0, 0, 1}, {0, 1, 2, 2} }, { {0, 1, 2, 2}, {1, 1, 1, 0} }, { {0, 1, 1, 1}, {0, 0, 1, 2} }, { {0, 0, 1, 2}, {1, 0, 0, 0} }}; // matrice de la forme "carrée" const char pieces_Sq[1][2][4] = {{ {0, 1, 0, 1}, {0, 0, 1, 1} }}; // matriz de forma "T" const char pieces_T[4][2][4] = {{ {0, 0, 1, 0}, {0, 1, 1, 2} }, { {0, 1, 1, 2}, {1, 0, 1, 1} }, { {1, 0, 1, 1}, {0, 1, 1, 2} }, { {0, 1, 1, 2}, {0, 0, 1, 0} }}; // matrice de la forme "I" const char pieces_l[2][2][4] = {{ {0, 1, 2, 3}, {0, 0, 0, 0} }, { {0, 0, 0, 0}, {0, 1, 2, 3}}}; const short MARGIN_TOP = 19; const short MARGIN_LEFT = 3; const short SIZE = 5; const short TYPES = 6; const int MELODY_LENGTH = 10; const int MELODY_NOTES[MELODY_LENGTH] = {262, 294, 330, 262}; const int MELODY_DURATIONS[MELODY_LENGTH] = {500, 500, 500, 500}; int click[] = { 1047 }; int click_duration[] = { 100 }; int erase[] = { 2093 }; int erase_duration[] = { 100 }; word currentType, nextType, rotation; short pieceX, pieceY; short piece[2][4]; int interval = 20, score; long timer, delayer; boolean grid[10][18]; boolean b1, b2, b3; void checkLines() { boolean full; for (short y = 17; y >= 0; y--) { full = true; for (short x = 0; x < 10; x++) { full = full && grid[x][y]; } if (full) { breakLine(y); y++; } } } void breakLine(short line) { tone(BUZZER, erase[0], 1000 / erase_duration[0]); delay(100); noTone(BUZZER); for (short y = line; y >= 0; y--) { for (short x = 0; x < 10; x++) { grid[x][y] = grid[x][y - 1]; } } for (short x = 0; x < 10; x++) { grid[x][0] = 0; } display.invertDisplay(true); delay(50); display.invertDisplay(false); score += 10; } void refresh() { display.clearDisplay(); drawLayout(); drawGrid(); drawPiece(currentType, 0, pieceX, pieceY); display.display(); } void drawGrid() { for (short x = 0; x < 10; x++) for (short y = 0; y < 18; y++) if (grid[x][y]) display.fillRect(MARGIN_LEFT + (SIZE + 1)*x, MARGIN_TOP + (SIZE + 1)*y, SIZE, SIZE, WHITE); } boolean nextHorizontalCollision(short piece[2][4], int amount) { for (short i = 0; i < 4; i++) { short newX = pieceX + piece[0][i] + amount; if (newX > 9 || newX < 0 || grid[newX][pieceY + piece[1][i]]) return true; } return false; } boolean nextCollision() { for (short i = 0; i < 4; i++) { short y = pieceY + piece[1][i] + 1; short x = pieceX + piece[0][i]; if (y > 17 || grid[x][y]) return true; } return false; } void generate() { currentType = nextType; nextType = random(TYPES); if (currentType != 5) pieceX = random(9); else pieceX = random(7); pieceY = 0; rotation = 0; copyPiece(piece, currentType, rotation); } void drawPiece(short type, short rotation, short x, short y) { for (short i = 0; i < 4; i++) display.fillRect(MARGIN_LEFT + (SIZE + 1) * (x + piece[0][i]), MARGIN_TOP + (SIZE + 1) * (y + piece[1][i]), SIZE, SIZE, WHITE); } void drawNextPiece() { short nPiece[2][4]; copyPiece(nPiece, nextType, 0); for (short i = 0; i < 4; i++) display.fillRect(50 + 3 * nPiece[0][i], 4 + 3 * nPiece[1][i], 2, 2, WHITE); } void copyPiece(short piece[2][4], short type, short rotation) { switch (type) { case 0: //L_l for (short i = 0; i < 4; i++) { piece[0][i] = pieces_L_l[rotation][0][i]; piece[1][i] = pieces_L_l[rotation][1][i]; } break; case 1: //S_l for (short i = 0; i < 4; i++) { piece[0][i] = pieces_S_l[rotation][0][i]; piece[1][i] = pieces_S_l[rotation][1][i]; } break; case 2: //S_r for (short i = 0; i < 4; i++) { piece[0][i] = pieces_S_r[rotation][0][i]; piece[1][i] = pieces_S_r[rotation][1][i]; } break; case 3: //Sq for (short i = 0; i < 4; i++) { piece[0][i] = pieces_Sq[0][0][i]; piece[1][i] = pieces_Sq[0][1][i]; } break; case 4: //T for (short i = 0; i < 4; i++) { piece[0][i] = pieces_T[rotation][0][i]; piece[1][i] = pieces_T[rotation][1][i]; } break; case 5: //l for (short i = 0; i < 4; i++) { piece[0][i] = pieces_l[rotation][0][i]; piece[1][i] = pieces_l[rotation][1][i]; } break; } } short getMaxRotation(short type) { if (type == 1 || type == 2 || type == 5) return 2; else if (type == 0 || type == 4) return 4; else if (type == 3) return 1; else return 0; } boolean canRotate(short rotation) { short piece[2][4]; copyPiece(piece, currentType, rotation); return !nextHorizontalCollision(piece, 0); } void drawLayout() { display.drawLine(0, 15, WIDTH, 15, WHITE); display.drawRect(0, 0, WIDTH, HEIGHT, WHITE); drawNextPiece(); char text[6]; itoa(score, text, 10); drawText(text, getNumberLength(score), 7, 4); } short getNumberLength(int n) { short counter = 1; while (n >= 10) { n /= 10; counter++; } return counter; } void drawText(char text[], short length, int x, int y) { display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(x, y); display.cp437(true); for (short i = 0; i < length; i++) display.write(text[i]); } void setup() { pinMode(left, INPUT_PULLUP); pinMode(right, INPUT_PULLUP); pinMode(change, INPUT_PULLUP); pinMode(down, INPUT_PULLUP); pinMode(BUZZER, OUTPUT); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.setRotation(1); display.clearDisplay(); display.setTextColor(SSD1306_WHITE); display.setCursor(18, 40); display.println("TETRIS"); display.setCursor(15, 60); display.println("ARDUINO"); display.display(); // appuyer sur le bouton "change" pour démarrer le jeu while (true) { if (!digitalRead(change)) { if (b3) { break; } b3 = false; } else { b3 = true; } } display.clearDisplay(); drawLayout(); display.display(); randomSeed(analogRead(0)); nextType = random(TYPES); generate(); timer = millis(); } void loop() { if (millis() - timer > interval) { checkLines(); refresh(); if (nextCollision()) { for (short i = 0; i < 4; i++) grid[pieceX + piece[0][i]][pieceY + piece[1][i]] = 1; generate(); } else pieceY++; timer = millis(); } // en cas d'appui sur le bouton "left" if (!digitalRead(left)) { tone(BUZZER, click[0], 1000 / click_duration[0]); delay(100); noTone(BUZZER); if (b1) { if (!nextHorizontalCollision(piece, -1)) { pieceX--; refresh(); } b1 = false; } } else { b1 = true; } // en cas d'appui sur le bouton "right" if (!digitalRead(right)) { tone(BUZZER, click[0], 1000 / click_duration[0]); delay(100); noTone(BUZZER); if (b2) { if (!nextHorizontalCollision(piece, 1)) { pieceX++; refresh(); } b2 = false; } } else { b2 = true; } // en cas d'appui sur le bouton "down" if (!digitalRead(down)) { interval = 20; } else { interval = 400; } // en cas d'appui sur le bouton "change" if (!digitalRead(change)) { tone(BUZZER, click[0], 1000 / click_duration[0]); delay(100); noTone(BUZZER); if (b3) { if (rotation == getMaxRotation(currentType) - 1 && canRotate(0)) { rotation = 0; } else if (canRotate(rotation + 1)) { rotation++; } copyPiece(piece, currentType, rotation); refresh(); b3 = false; delayer = millis(); } } else if (millis() - delayer > 50) { b3 = true; } }
Explication du code pour jeu Tetris sur Arduino avec OLED i2c:
- les ports de connexion des boutons-poussoirs et du buzzer sont spécifiés dans le programme à l’aide de la directive #define;
- après le chargement du programme Tetris sur OLED SSD1306, pour démarrer le jeu, vous devez appuyer sur le bouton du haut (change).
Conclusion. Le but du jeu est de placer des blocs tombants de différentes formes sur le terrain de jeu de telle sorte qu’après chaque déplacement, vous obteniez une ligne régulière sans trous. Lorsque la ligne est entièrement remplie, elle disparaît et le joueur marque des points. Le but du jeu est de marquer le plus de points possible avant que toute la ligne ne soit remplie. Si vous avez des questions sur le projet Arduino, laissez-les dans les commentaires.








Est-il possible de faire ceci avec un ILI9341 2,8 pouces 240×320
Je n’ai pas encore essayé, mais si cela fonctionne, n’oubliez pas d’en parler.
C’est possible de le faire avec le ssh1106 1,3″ en 128×64 ?
Bonjour.
Je n’ai pas travaillé avec ce module, je ne peux donc pas me prononcer.
Mais il me semble qu’il est possible de faire du tetris sur cet écran