Introduction: Mini Retro Pong Game

About: Músico, matemático, computación, ciencia... insolente y subversivo, pero siempre propositivo

En 1972, Atari desarrolló Pong! a partir de un juego similar de Magnavox, mejoraron la idea de un juego de Ping Pong, y lo incluyeron en un formato de Arcade.

En esa época, el juego era dificil de construir , y no era programado como tal (no existían microprocesadores), sino que consistían en una serie de chips, era un trabajo que solamente expertos en la materia podían desarrollar.

Hoy, gracias a microcontroladores, podemos hacer el juego, sin perder mucho tiempo en hardware, y concentrándonos en la programación. En este instructable, armo un juego de Pong utilzando un Adafruit Feather M0, con una antalla OLED (Featherwing). Acá detallo la construcción, pero también explico la forma de planear y desarrollar el código, y los dejo con un par de retos al final.

Step 1: Materiales

Materiales

  1. Adafruit Feather M0
  2. OLED Featherwing
  3. Cables de silicona (como este)
  4. Trim pots
  5. Batería LiPo

Herramientas

  1. Impresora 3D
  2. Cautín

Aunque utilizamos un Adafruit Feather M0, se puede utilizar cualquier Arduino y pantalla OLED

Step 2: Construyendo El Código

Antes de programar siempre es bueno planear un poco lo que vamos a hacer. Acá algunas consideraciones:

Pantalla y Librería GFX

La pantalla que utilizo es de 128 en la dirección y, y 32 en dirección x (noten que rotamos la posición de la pantalla). Para manipular objetos gráficos utilizamos la librería Adafruit_GFX, que pueden descargar acá. De esta librería utilizamos diferentes funciones:

  • fillRect() para dibujar la bola como un pequeño cuadrado
  • drawLine(), para dibujar los pads y la línea central
  • Varias funciones de texto, para mostrar el marcador de puntos por jugador

Se pueden usar otras funciones, como por ejemplo para hacer la bola redonde, etc, pero esas ya son cosas estéticas más que se las dejo a ustedes.

Elementos del juego

Los principales elementos del juego son:

  1. La bola que se mueve en dos dimensiones y rebota a lo largo del plano "y"
  2. Los pads que se mueven en una dimensión (plano y) y las cuales hacen que la bola rebote
  3. El puntaje, que cambia cuando la bola sale, pues no rebota en el fondo

Datos

Necesitamos varias variables globales. Para la bola:

//ball position and direction
int ballX = 16, ballY = 64;
int dirX = 1, dirY = 1;
int ballSpeed = 1;

Como ven almacenamos la posición de la bola en ballX, ballY, tenemos que saber almacenar la dirección de movimiento (dirX, dirY), 1 para ir hacia adelante y -1 para la dirección opuesta. Noten que almacenamos las componentes x y y pues estamos trabajando en un plano de cartesiano de dos dimensiones. Por ultimo la velocidad de la bola ballSpeed, en pixeles por iteración.

Para los pads:

//pad position
int X1 = 11, X2 = 11;

Simplemente debemos concer la posición en una dimensión.

Para el marcador

//score
int playerA = 0, playerB = 0;

El marcador se va incrementando, y podemos luego utilizar uno de los botones del featherwing para reiniciar el juego.

Funciones

La más importante es el movineinto de la bola que berota en las paredes y en los pads. En el código, todo está en esta función, que luego voy a explicar en detalles:

void bounceBall() {  
  //rebota en los bordes de X  
  (ballX >= 0 && ballX < 30) ? : dirX *= -1; 
  
  //bordes de Y son puntos  
  if (ballY < 0) {    
    playerB++;    
    initBall(); 
  }  
  if (ballY > 124) {    
    playerA++; 
    initBall(); 
  } 

  //revisa si pega en los pads y rebota  
  int d1 = ballX - X1; 
  int d2 = ballX - X2; 
  (ballY == 0 && abs(d1) <= 2) ? : dirY *= -1; 
  (ballY == 124 && abs(d2) <= 2) ? : dirY *= -1;
}

Vamos por partes. La línea,

(ballX >= 0 && ballX < 30) ? : dirX *= -1;

lo que hace es verificar si la posición de la bola excede los límites de 32 pixeles de la pantalla a lo ancho, si lo hace entonces invierte la dirección de movimiento (cambiando el signo de la variable dirX). La sección,

if (ballY < 0) {    <br>    playerB++;    
    initBall(); 
  }  
 if (ballY > 124) {    
    playerA++; 
    initBall(); 
  }

Lo que hace es verificar a lo largo, si se sale del largo de la pantalla entonces suma puntos a un jugador o el otro, dependiendo de si se salió por la izquierda o derecha, luego reinicia la bola en el centro. Por último, la porción de código,

int d1 = ballX - X1; <br>int d2 = ballX - X2; 
(ballY == 0 && abs(d1) <= 2) ? : dirY *= -1; 
(ballY == 124 && abs(d2) <= 2) ? : dirY *= -1;

Simplemente mide la distancia de la bola a cada uno de los pads, y si está cerca (dentro de un límite), rebota cambiando el signo de la variable dirY.

Código completo

Hay más detalles en el código que son fáciles de entender. El código lo mantengo al mínimo para que ustedes puedan adaptarlo, modificarlo y mejorarlo. El código completo lo pueden obtener en este GitHub.

Step 3: Imprimiendo La Mini Mesa

Adjunto el archivo de impresión 3D. Recomiendo imprimir a 100 micras para que los trim pots queden bien ajustados.

Step 4: Conectando

La conexiones son sencillas. Parto del hecho de que el Feather M0 que tengan tienen headers hembra, y que la pantalla OLED featherwing tiene headers macho, de esa manera se pueden conectar uno a otro fácilmente.

Como se ve en la primera foto, hay que soldar los trim pots a los pines A0 y A1 del featherwing, también 3.3v y GND, los cuales comparten ambos trimpots. Luego de soldar se deberían ver como en las fotos siguientes.

Para ensamblar con la mesa:

  1. Pasar los cables por el hueco del centro (ver foto)
  2. Acoplar el feather M0 al featherwing (foto)
  3. Meter lo trim pots en los huecos respectivos
  4. Conectar batería

Para la batería por el momento la estoy pegando con un tape de doble adhesivo.

Eso es todo!

Step 5: Funcionando Y Retos

Listo, ahora a jugar!!!!

Retos

  • Hacer que la bola se acelera a medida que progresa el juego
  • Que los pads cambien la dirección de bola según el movimiento del pad al tocarla
  • Mejorar los gráficos
  • Hacer la bola redonda
  • Hacer una "zona muerta" donde el pad no pueda alcanzar la bola.