Construye un juego Tetris con Arduino Nano en matriz LED 16x8 DIY
Componentes y suministros
| Arduino Nano R3 | 1 |
| Pulsador 12mm SparkFun | 4 |
| Registro de desplazamiento Texas Instruments SN74HC595 (Serie a Paralelo) | 2 |
| Interruptor deslizante | 1 |
| LED 5 mm: Amarillo | 128 |
Herramientas necesarias
- Soldador (genérico)
Aplicaciones y servicios online
- Arduino IDE
Sobre el proyecto
He construido este juego Tetris con una matriz LED 16x8 casera, Arduino Nano y dos registros de desplazamiento 74HC595. También añadí un sonido beep al pulsar cualquier botón.
Código
Código Tetris Arduino
/* Author: Jae Yeong Bae UBC ECE jocker.tistory.com Date: Jan.18.2013 File: Tetris v2 Changelog: v2: displays score at gameover Purpose: killing time.. + for fun Circuits+Pins: Led Matrix: 2 74HC575 Shift Registers in order: Green,Blue,Red pins: Latch = 3 Clock = 2 Data = 4 Row Anodes = 5 to 13 (8pins) shared between both matrix buttons (as digital): A4 = left A5 = down A6 = right A7 = up (rotate) Comment: This is my second Arduino Project. Code may be messy and inefficient. References from Arduino Library and datasheets. */
unsigned char latchPin = 3; unsigned char clockPin = 2; unsigned char dataPin = 4; unsigned char rowPin = 5;
long delays = 0; short delay_ = 500; long bdelay = 0; short buttondelay = 150; short btdowndelay = 30; short btsidedelay = 80;
unsigned char blocktype; unsigned char blockrotation; int lines = 0;
boolean block[8][18]; boolean pile[8][16]; boolean disp[8][16]; boolean lib[10][5][7];
void setup() {
// Inicialización librería formas piezas (lib)
lib[0][1][0] = 1; lib[0][2][0] = 1; lib[0][3][0] = 1; lib[0][0][1] = 1; lib[0][4][1] = 1; lib[0][3][2] = 1; lib[0][0][2] = 1; lib[0][4][2] = 1; lib[0][2][3] = 1; lib[0][0][3] = 1; lib[0][4][3] = 1; lib[0][1][4] = 1; lib[0][0][4] = 1; lib[0][4][4] = 1; lib[0][0][5] = 1; lib[0][4][5] = 1; lib[0][1][6] = 1; lib[0][2][6] = 1; lib[0][3][6] = 1;
lib[1][2][0] = 1; lib[1][1][1] = 1; lib[1][2][1] = 1; lib[1][2][2] = 1; lib[1][2][3] = 1; lib[1][2][4] = 1; lib[1][2][5] = 1; lib[1][1][6] = 1; lib[1][2][6] = 1; lib[1][3][6] = 1;
lib[2][1][0] = 1; lib[2][2][0] = 1; lib[2][3][0] = 1; lib[2][0][1] = 1; lib[2][4][1] = 1; lib[2][4][2] = 1; lib[2][3][3] = 1; lib[2][2][4] = 1; lib[2][1][5] = 1; lib[2][0][6] = 1; lib[2][1][6] = 1; lib[2][2][6] = 1; lib[2][3][6] = 1; lib[2][4][6] = 1;
lib[3][0][0] = 1; lib[3][1][0] = 1; lib[3][2][0] = 1; lib[3][3][0] = 1; lib[3][4][0] = 1; lib[3][3][1] = 1; lib[3][2][2] = 1; lib[3][3][3] = 1; lib[3][4][4] = 1; lib[3][0][5] = 1; lib[3][4][5] = 1; lib[3][1][6] = 1; lib[3][2][6] = 1; lib[3][3][6] = 1;
lib[4][3][0] = 1; lib[4][2][1] = 1; lib[4][3][1] = 1; lib[4][1][2] = 1; lib[4][3][2] = 1; lib[4][0][3] = 1; lib[4][3][3] = 1; lib[4][0][4] = 1; lib[4][1][4] = 1; lib[4][2][4] = 1; lib[4][3][4] = 1; lib[4][4][4] = 1; lib[4][3][5] = 1; lib[4][3][6] = 1;
lib[5][0][0] = 1; lib[5][1][0] = 1; lib[5][2][0] = 1; lib[5][3][0] = 1; lib[5][4][0] = 1; lib[5][0][1] = 1; lib[5][0][2] = 1; lib[5][1][2] = 1; lib[5][2][2] = 1; lib[5][3][2] = 1; lib[5][4][3] = 1; lib[5][4][4] = 1; lib[5][0][5] = 1; lib[5][4][5] = 1; lib[5][1][6] = 1; lib[5][2][6] = 1; lib[5][3][6] = 1;
lib[6][2][0] = 1; lib[6][3][0] = 1; lib[6][1][1] = 1; lib[6][0][2] = 1; lib[6][0][3] = 1; lib[6][1][3] = 1; lib[6][2][3] = 1; lib[6][3][3] = 1; lib[6][0][4] = 1; lib[6][4][4] = 1; lib[6][0][5] = 1; lib[6][4][5] = 1; lib[6][1][6] = 1; lib[6][2][6] = 1; lib[6][3][6] = 1;
lib[7][0][0] = 1; lib[7][1][0] = 1; lib[7][2][0] = 1; lib[7][3][0] = 1; lib[7][4][0] = 1; lib[7][4][1] = 1; lib[7][3][2] = 1; lib[7][2][3] = 1; lib[7][1][4] = 1; lib[7][1][5] = 1; lib[7][1][6] = 1;
lib[8][1][0] = 1; lib[8][2][0] = 1; lib[8][3][0] = 1; lib[8][0][1] = 1; lib[8][4][1] = 1; lib[8][0][2] = 1; lib[8][4][2] = 1; lib[8][1][3] = 1; lib[8][2][3] = 1; lib[8][3][3] = 1; lib[8][0][4] = 1; lib[8][4][4] = 1; lib[8][0][5] = 1; lib[8][4][5] = 1; lib[8][1][6] = 1; lib[8][2][6] = 1; lib[8][3][6] = 1;
lib[9][1][0] = 1; lib[9][2][0] = 1; lib[9][3][0] = 1; lib[9][0][1] = 1; lib[9][4][1] = 1; lib[9][0][2] = 1; lib[9][4][2] = 1; lib[9][1][3] = 1; lib[9][2][3] = 1; lib[9][3][3] = 1; lib[9][4][3] = 1; lib[9][4][4] = 1; lib[9][3][5] = 1; lib[9][1][6] = 1; lib[9][2][6] = 1;
int seed = (analogRead(0)+1)* (analogRead(1)+1)* (analogRead(2)+1)* (analogRead(3)+1);
randomSeed(seed); random(10,9610806);
seed = seed *random(3336,15679912)+analogRead(random(4)) ; randomSeed(seed); random(10,98046);
cli();
TCCR1A = 0; TCCR1B = 0; TCNT1 = 0;
OCR1A = 259;
TCCR1A |= (1 << WGM01);
TCCR1B |= (1 << CS12) | (1 << CS10);
TIMSK1 |= (1 << OCIE0A);
sei();
pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT);
pinMode(A7, INPUT); pinMode(A6, INPUT); pinMode(A5, INPUT); pinMode(A4, INPUT);
for(int i=0;i<8;i++) pinMode(rowPin+i,OUTPUT);
newBlock(); updateLED(); Serial.begin(9600);
}
void loop() {
if (delays < millis()) { delays = millis() + delay_; movedown(); }
int button = readBut();
if (button == 1) rotate();
if (button == 2) moveright();
if (button == 3) moveleft();
if (button == 4) movedown();
Serial.print(analogRead(A4)); Serial.print(analogRead(A5)); Serial.print(analogRead(A6)); Serial.println(analogRead(A7));
}
boolean moveleft() {
if (space_left()) {
for (int i=0;i<7;i++) for (int j=0;j<16;j++) block[i][j]=block[i+1][j];
for (int j=0;j<16;j++) block[7][j]=0;
updateLED(); return 1;
} return 0;
}
boolean moveright() {
if (space_right()) {
for (int i=7;i>0;i--) for (int j=0;j<16;j++) block[i][j]=block[i-1][j];
for (int j=0;j<16;j++) block[0][j]=0;
updateLED(); return 1;
} return 0;
}
int readBut() {
if (bdelay > millis()) return 0;
if (analogRead(A4) > 500) { bdelay = millis() + btsidedelay; return 3; }
if (analogRead(A5) > 500) { bdelay = millis() + btdowndelay; return 4; }
if (analogRead(A6) > 500) { bdelay = millis() + btsidedelay; return 2; }
if (analogRead(A7) > 500) { bdelay = millis() + buttondelay; return 1; }
return 0;
}
void updateLED() {
for (int i=0;i<8;i++) for (int j=0;j<16;j++) disp[i][j] = block[i][j] | pile[i][j];
}
void rotate() {
if (blocktype == 3) return;
int xi, yi, i, j;
for (i=7;i>=0;i--) for (j=0;j<16;j++) if (block[i][j]) xi = i;
for (i=15;i>=0;i--) for (j=0;j<8;j++) if (block[j][i]) yi = i;
// Lógica rotación para cada tipo de pieza... (código extenso omitido por brevedad, ver original)
updateLED();
}
void movedown() {
if (space_below()) {
for (int i=15;i>=0;i--) for (int j=0;j<8;j++) block[j][i] = block[j][i-1];
for (int i=0;i<7;i++) block[i][0] = 0;
} else {
for (int i=0;i<8;i++) for(int j=0;j<16;j++) if (block[i][j]) { pile[i][j]=1; block[i][j]=0; }
newBlock();
} updateLED();
}
boolean check_overlap() {
for (int i=0;i<16;i++) for (int j=0;j<7;j++) if (block[j][i] && pile[j][i]) return false;
for (int i=16;i<18;i++) for (int j=0;j<7;j++) if (block[j][i]) return false;
return true;
}
void check_gameover() {
for(int i=15;i>=0;i--) {
int cnt=0; for (int j=0;j<8;j++) if (pile[j][i]) cnt++;
if (cnt == 8) {
lines++;
for (int j=0;j<8;j++) pile[j][i]=0;
updateLED(); delay(50);
for(int k=i;k>0;k--) for (int j=0;j<8;j++) pile[j][k] = pile[j][k-1];
for (int j=0;j<8;j++) pile[j][0] = 0;
updateLED(); delay(50); i++;
}
}
for(int i=0;i<8;i++) if (pile[i][0]) gameover();
}
void gameover() {
// Animación cierre y muestra puntuación
// ... (código extenso)
while(true) { /* scroll puntuación */ }
}
void newBlock() {
check_gameover();
blocktype = random(7);
// Inicialización posición pieza según tipo
blockrotation = 0;
}
boolean space_below() {
for (int i=15;i>=0;i--) for (int j=0;j<8;j++)
if (block[j][i]) { if (i == 15) return false; if (pile[j][i+1]) return false; }
return true;
}
// Funciones space_left, space_right, space_left2, space_right2, space_left3, space_right3
// ... (comprobaciones de espacio para rotación)
ISR(TIMER1_COMPA_vect){ LEDRefresh(); }
void LEDRefresh() {
// Refresco matriz LED con corrección por error de cableado pines
boolean tmpdisp[8][16];
for (int k=0;k<16;k++) {
for(int i=1;i<8;i++) tmpdisp[i][k]=disp[i-1][k];
tmpdisp[0][k]=disp[7][k];
}
for(int i=0;i<8;i++) {
int j = (i == 0) ? rowPin+7 : rowPin+i-1;
byte upper = 0, lower = 0;
for(int b=0;b<8;b++) { upper <<= 1; if (!tmpdisp[b][i]) upper |= 1; }
for(int b=0;b<8;b++) { lower <<= 1; if (!tmpdisp[b][i+8]) lower |= 1; }
digitalWrite(j,LOW); digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, lower);
shiftOut(dataPin, clockPin, LSBFIRST, upper);
digitalWrite(latchPin, HIGH); digitalWrite(rowPin+i,HIGH); delay(1);
}
digitalWrite(rowPin+7,LOW);
}
Esquemáticos
Proceso de manufactura
- Construye un Juego Giroscópico en Tiempo Real con Arduino Nano y Sensor MPU-6050
- Proyecto Dados Digitales Arduino: Construye tu Propio Generador de Números Aleatorios con LCD
- TV‑B‑Gone DIY con Arduino: Mando universal para apagar cualquier TV
- Mando USB para juegos DIY con Arduino – Construye tu propio gamepad de alto rendimiento
- Construye una consola Pong 24×16 LED con Arduino Nano y MAX7219
- Pixel Chaser: Juego LED Interactivo de Un Toque con Arduino Nano
- Reloj flip Arduino con matriz LED 8×8: proyecto DIY de reloj en tiempo real
- Pong Neón en Matriz NeoPixel con Arduino Nano
- Contador Geiger Portátil con Arduino Nano: Construye tu Detector de Radiación
- Juego Pong 1D con Arduino Nano y tira LED WS2812: Tutorial paso a paso
- Never Ride Alone: Sistema inteligente de seguridad para bicicletas