ATtiny85 Mini Arcade : Snake – Construire une console de jeu portable OLED
Composants et fournitures
| Composant | Quantité |
|---|---|
| Microcontrôleur ATtiny85 (Microchip Technology) | 1 |
| Écran OLED graphique 128 x 64 | 1 |
| Module USB microB SparkFun (breakout) | 1 |
| Arduino Nano R3 (pour programmer l'ATtiny85) | 1 |
Outils et machines nécessaires
- Fer à souder (générique)
- Imprimante 3D (générique)
Applications et services en ligne
- Autodesk Fusion 360
- Arduino IDE
À propos de ce projet
Inspiration et projet antérieur
En décembre 2017, j'ai créé une console portable Arduino Pong avec un Arduino Nano, un écran OLED et deux boutons.
Elle fonctionnait mais était trop encombrante. Récemment, j'ai voulu recréer certains de mes anciens projets, mais cette fois en très petit : une console miniature pour jouer à Snake.
Les composants choisis
Pour la miniaturisation, impossible d'utiliser une carte de développement Arduino standard → choix de l'ATtiny85.
Il offre assez d'entrées/sorties : deux pins ADC, un port I2C et un GPIO. J'ai opté pour un module joystick 2 axes avec bouton, facile à interfacer (3 pins de signal).
Pour l'affichage, l'écran OLED 128 x 64 de DFRobot offre une bonne résolution dans un format réduit.
Soudure du système
- Soudez l'ATtiny85 sur un adaptateur SOP-8 vers DIP-8, puis sur un morceau de perfboard.
- Ajoutez deux connecteurs : un pour la programmation, un pour l'écran.
- Soudez les pins du joystick analogique et câblez-le.
- Câblez une carte breakout micro USB pour l'alimentation.
Conception de l'enceinte
L'enceinte a été conçue dans Fusion 360 : création des composants réels, puis boîtier autour. Objectif : évoquer une borne d'arcade des années 80 tout en restant minuscule.
Programmation du jeu
Snake est simple à programmer. Longueur max du serpent fixée à 30 pour économiser la RAM : au-delà de 29 segments mangés, le joueur gagne. Pour suivre les segments, j'utilise un tableau 2D stockant les coordonnées (x,y) de chaque segment.
À chaque déplacement de la tête, les positions précédentes se décalent. À chaque pomme mangée, un nouveau segment apparaît aléatoirement. La détection de collision parcourt les coordonnées de chaque segment pour voir si la tête les chevauche. Toucher les bords fait aussi perdre.
Jouer à Snake
Allumez la console, attendez l'affichage de la première pomme et du premier segment. Pilotez le serpent avec le joystick. C'est amusant, un excellent tueur d'ennui dans un format minuscule.
Code
- Code ATTiny85
Code ATTiny85 C/C++
Installez d'abord la bibliothèque U8g2lib
//#include <TinyWireM.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g(U8G2_R0, /* clock=*/ 2, /* data=*/ 0, /* reset=*/ U8X8_PIN_NONE);
#define MAX_LENGTH 30
#define X 0
#define Y 1
#define JOYSTICK_X 2
#define JOYSTICK_Y 3
#define DIR_THRESH 300
uint8_t segmentPositions[MAX_LENGTH][2];
uint8_t headPosition[2] = {63, 31};
uint8_t foodPosition[2];
uint8_t tempPosition0[2];
uint8_t tempPosition1[2];
int segmentLength = 1;
void gameUpdate();
enum DIRECTIONS { RIGHT, DOWN, LEFT, UP } currentDirection;
void setup() {
u8g.begin();
u8g.setPowerSave(0);
pinMode(JOYSTICK_X, INPUT);
pinMode(JOYSTICK_Y, INPUT);
randomSeed(analogRead(0));
beginGame();
}
void loop() {
u8g.firstPage();
do {
gameUpdate();
u8g.setColorIndex(1);
} while(u8g.nextPage());
}
void beginGame(){
currentDirection = RIGHT;
spawnFood();
delay(1000);
}
bool checkCollisions(){
for(int i=1; i<segmentLength; i++){
if(segmentPositions[i][X] == headPosition[X]){
if(segmentPositions[i][Y] == headPosition[Y]) return 1;
}
}
if(headPosition[X] <= 0 || headPosition[X] >= 128) return 1;
else if(headPosition[Y] <= 0 || headPosition[Y] >= 64) return 1;
return false;
}
void spawnFood(){
int randomX = random(5, 123);
int randomY = random(5, 60);
foodPosition[X] = randomX;
foodPosition[Y] = randomY;
}
void checkFoodEaten(){
if(headPosition[X] == foodPosition[X] || headPosition[Y] == foodPosition[Y]){
segmentLength += 1;
spawnFood();
}
}
void updateDirection(){
int joy_x_val = analogRead(JOYSTICK_X);
int joy_y_val = analogRead(JOYSTICK_Y);
if(joy_x_val <= DIR_THRESH) currentDirection = LEFT;
else if(joy_x_val >= 1023-DIR_THRESH) currentDirection = RIGHT;
else if(joy_y_val <= DIR_THRESH) currentDirection = UP;
else if(joy_y_val >= 1023-DIR_THRESH) currentDirection = DOWN;
}
void displaySegments(){
for(int segment=0; segment < segmentLength; segment++){
u8g.drawPixel(segmentPositions[segment][X], segmentPositions[segment][Y]);
}
u8g.drawPixel(foodPosition[X], foodPosition[Y]);
}
void gameUpdate(){
updateDirection();
tempPosition0[X] = headPosition[X];
tempPosition0[Y] = headPosition[Y];
switch(currentDirection){
case UP: headPosition[Y] -= 1; break;
case DOWN: headPosition[Y] += 1; break;
case LEFT: headPosition[X] -= 1; break;
case RIGHT: headPosition[X] += 1; break;
}
for(int segment=1; segment < segmentLength; segment+= 2){
tempPosition1[X] = segmentPositions[segment][X];
tempPosition1[Y] = segmentPositions[segment][Y];
segmentPositions[segment][X] = tempPosition0[X];
segmentPositions[segment][Y] = tempPosition0[Y];
tempPosition0[X] = segmentPositions[segment+1][X];
tempPosition0[Y] = segmentPositions[segment+1][Y];
segmentPositions[segment+1][X] = tempPosition1[X];
segmentPositions[segment+1][Y] = tempPosition1[Y];
}
displaySegments();
checkFoodEaten();
if(checkCollisions()) endGame();
if(segmentLength >= MAX_LENGTH) endGame();
delay(50);
}
void endGame(){
segmentLength = 1;
headPosition[0] = 63;
headPosition[1] = 31;
beginGame();
}
Pièces personnalisées et boîtiers
(Fichiers STL disponibles dans le dépôt du projet)
Schémas

Processus de fabrication
- Détecteur de langue TinyML avec Edge Impulse sur Arduino Nano 33 BLE Sense
- Construire un jeu gyroscopique temps réel avec Arduino Nano et capteur MPU-6050
- Dé numérique Arduino sur écran LCD 16x2 – Générateur aléatoire à bouton poussoir
- Créer votre propre jeu de roulette à 37 LED avec Arduino Nano
- Détecteur de distance portable – Kit DIY Arduino Nano avec HC-SR04, alimentation 18650 et boîtier imprimé 3D
- Construire une lampe de bureau réactive à l'audio avec Arduino Nano
- Projet de galvanoplastie au cuivre : Construisez un système intelligent avec Arduino UNO
- Jeu Pong sur Matrice NeoPixel avec Arduino Nano
- Créez des séquences lumineuses époustouflantes avec un registre à décalage Arduino