Pong Neón en Matriz NeoPixel con Arduino Nano
Componentes y materiales
- 1x Tira NeoPixel (LED direccionables individualmente)
- 1x Cables jumper (genéricos)
- 1x Arduino Nano R3
- 1x Header hembra 8 posiciones 1 fila (0.1")
- 1x Placa Perma-Proto media tamaño
- 1x Joystick analógico (genérico)
- 1x Potenciómetro rotativo (genérico)
Herramientas necesarias
- Soldador (genérico)
Aplicaciones y servicios online
- Arduino IDE
Sobre el proyecto
La Matriz
No, no la película, ¡la matriz NeoPixel! Para hacer una matriz, compra una tira de LEDs NeoPixel direccionables individualmente. Desenróllala y fíjate en las flechas: solo se pueden conectar en UNA DIRECCIÓN; si la orientación es errónea, los puedes dañar.
Usé una tira de 30 LED/m, 5 metros, y la corté en tiras de 10 LEDs cada una. Luego coloqué las tiras sobre cartulina, alternando orientaciones. Corté cables a medida y los soldé a los terminales NeoPixel. Tras 14 soldaduras, ¡la matriz estaba lista! Comprobé con multímetro que no hubiera cortocircuitos (un cortocircuito fríe el Nano, la matriz y quizá el puerto USB —lo sé por experiencia). Subí el sketch de prueba neomatrix con parámetros NEO_BOTTOM + NEO_LEFT + NEO_COLUMNS + NEO_ZIGZAG. Si desplaza "howdy" por la pantalla, ¡la matriz funciona!
La Lógica
Un juego Pong tiene varios objetos: pala, paredes y bola. El código usa variables ballX y ballY para la posición de la bola. La dirección se maneja asignando 1 o -1 a variables de dirección. La pala es un rectángulo controlado por un potenciómetro mapeado a 0-15. La coordenada Y de la pala no cambia. Al iniciar, la bola empieza en (1,1) y el jugador debe dejar que rebote una vez para comenzar. La física considera la dirección de la bola y dónde impacta en la pala.
¡A jugar!
Conecta la matriz NeoPixel al Arduino Nano, el +5V del joystick a 5V, GND a GND del Arduino, y el eje X a A0. ¡Diviértete con tu nuevo Pong! Prueba añadir más jugadores y mejor física para mayor reto.
Código
Código principal para Arduino (C/C++):
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(15, 10, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800);
int paddleX = 0, paddleY = 0;
int oldPaddleX, oldPaddleY;
int ballDirectionX = 1, ballDirectionY = 1;
int score = 0;
int ballSpeed = 10; // menor = más rápido
int ballX, ballY, oldBallX, oldBallY;
void setup() {
Serial.begin(9600);
matrix.begin();
matrix.fillScreen(0);
matrix.setTextColor(matrix.Color(0,255,0));
matrix.print("GO");
matrix.show();
delay(2000);
matrix.fillScreen(0);
matrix.show();
}
void loop() {
int myWidth = matrix.width();
int myHeight = matrix.height();
paddleX = map(analogRead(A0), 0, 1023, 0, 12);
paddleY = 8;
if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
matrix.fillRect(oldPaddleX, oldPaddleY, 4, 1, matrix.Color(0,0,0));
}
matrix.fillRect(paddleX, paddleY, 4, 1, matrix.Color(0,0,255));
oldPaddleX = paddleX;
oldPaddleY = paddleY;
matrix.show();
if (millis() % ballSpeed < 2) {
moveBall();
}
matrix.show();
if (ballY > 8 && (millis() > 10000)) {
score += 1;
matrix.fillScreen(0);
matrix.setTextColor(matrix.Color(255,0,0));
matrix.setCursor(0,2);
matrix.print(String(score));
matrix.show();
delay(4000);
ballX = random(3,11);
ballY = random(1,1);
matrix.fillScreen(0);
matrix.show();
delay(1000);
}
delay(5);
}
void moveBall() {
if (ballX > matrix.width() - 1 || ballX < 0) ballDirectionX = -ballDirectionX;
if (ballY > matrix.height() || ballY < 0) ballDirectionY = -ballDirectionY;
if (inPaddle(ballX, ballY, paddleX, paddleY, 4, 1)) {
if (ballX == paddleX && ballY == paddleY) {
ballDirectionX = -ballDirectionX; ballDirectionY = -ballDirectionY;
} else if (ballX == paddleX + 3 && ballY == paddleY) {
ballDirectionX = ballDirectionX; ballDirectionY = -ballDirectionY;
} else if (ballX == paddleX + 1 && ballY == paddleY) {
ballDirectionX = -ballDirectionX; ballDirectionY = -ballDirectionY;
} else if (ballX == paddleX + 2 && ballY == paddleY) {
ballDirectionX = ballDirectionX; ballDirectionY = -ballDirectionY;
}
}
ballX += ballDirectionX;
ballY += ballDirectionY;
if (oldBallX != ballX || oldBallY != ballY) {
matrix.drawPixel(oldBallX, oldBallY, matrix.Color(0,0,0));
}
matrix.drawPixel(ballX, ballY, matrix.Color(150,150,0));
oldBallX = ballX;
oldBallY = ballY;
}
boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
boolean result = false;
if ((x >= rectX && x <= (rectX + rectWidth)) && (y >= rectY && y <= (rectY + rectHeight)))
result = true;
return result;
}
Esquemáticos
Diagrama de conexiones disponible en la documentación del proyecto.
Proceso de manufactura
- Detector de idiomas TinyML con Edge Impulse en Arduino Nano 33 BLE Sense
- 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
- Construye un Iron Man animado con Arduino: componentes, sensores y guía paso a paso
- Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
- Controlador de Humidificador DIY con Arduino y Relé: Configuración Segura de Alto Voltaje
- Medición de Distancia en Tiempo Real con Sonar Arduino y Visualización en Processing
- MobBob: Robot Arduino Impreso en 3D, Controlado por Smartphone Android
- Construir una lámpara de escritorio reactiva al audio con Arduino Nano
- Construye un volante joystick personalizado con Arduino para gaming
- Arduino 101: Construye un Podómetro con Sensor DHT11 y Pantalla LCD