ArkaPix

en: Hormiga Azul

Dificultad:

Avanzado

Plataforma:

Arduino

Categoria:

Arduino

Favoritos:

favorite4

reportReportar

Descripción:

El famoso juego Arkanoid implementado en una matríz Neopixel.

Licencia: Sin Licencia


Tags:

juegos
Arkanoid

Componentes:

  • Neo Pixel Matrix 8x8 x 1
  • Arduino Uno x 1
  • Joystick x 1
  • Protoboard x 1
  • Jumpers x 7
  • IDE Arduino

Paso 0:

Decargar e instalar las librerías requeridas. Para utilizar el Neo Pixel Matrix en Arduino, es necesario descargar e instalar las siguientes tres librerías.

Adafruit NeoPixel

Adafruit NeoMatrix

Adafruit GFX

Paso 1:

Probar matríz de Neopixel y ubicar el primer pixel.

Código:

                                    
                                            #include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
 #define PSTR // Make Arduino Due happy
#endif

#define PIN 6

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
  NEO_GRB            + NEO_KHZ800);

const uint16_t colors[] = {
  matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255) };

void setup() {
  matrix.begin();
  matrix.setBrightness(40);
  matrix.fillScreen(0);
  matrix.show();
}

void loop() {
  for(int color=0;color <3;color++)
  {
    matrix.fillScreen(0);
    for(int i =0;i<8;i+=2)
    {
      matrix.drawPixel(i,i, colors[color]);
    }
  matrix.show();
  delay(100);
  }
}
                                    
                                

Paso 2:

Crear un arreglo de memoria que almacene el estado de los pixeles que representarán los ladrillos a destruir, llenarlos a su estado inicial y desplegar dichos pixeles a partir de dicho arreglo.

Código:

                                    
                                            uint16_t estados[8][3];

void llenar()
{
  for(int i=0;i<8;i++)
  {
    estados[i][0]=rojo;
    estados[i][1]=rojo;
    estados[i][2]=rojo;
  }
}
                                    
                                

Paso 3:

Desplegar la barra en la cual rebotará la pelota de vuelta hacia los ladrillos.

Código:

                                    
                                            void barra(int inicial) 
{
  for(int i = 0;i<8;i++) //Limpiar barra
  {
    matrix.drawPixel(i,0,0);
  }
  matrix.drawPixel(inicial, 0, blanco);
  matrix.drawPixel(inicial+1, 0, blanco);
  matrix.drawPixel(inicial+2, 0, blanco);
  //matrix.show();
}
                                    
                                

Paso 4:

Controlar el desplazamiento de la barra mediante la lectura de los valores analógicos que genera el potenciómetro del joystick.

Código:

                                    
                                            int lectura = analogRead(A0);
  if(lectura<100)
  {
    if(barraInicial>0)
      barraInicial--;
  }
  else if(lectura>900)
  {
    if(barraInicial<5)
      barraInicial++;
  }
                                    
                                

Paso 5:

Desplegar la pelota y hacer el código para que rebote en los límites de la matriz y en los ladrillos cambiando el estado del ladrillo golpeado. Se ajusta para que los ladrillos inicien de color rojo, el primer golpe los vuelve verdes, el segundo azules y el tercer golpe los elimina.

Código:

                                    
                                            //Variables globales 

const uint16_t blanco = matrix.Color(255,255,255);
const uint16_t rojo = matrix.Color(255, 0, 0);
const uint16_t verde = matrix.Color(0, 255, 0);
const uint16_t azul = matrix.Color(0,0,255);

int retraso = 500;
bool diagonal=false;
bool golpe = false;
bool dirX;
bool dirY;
int xx=0, yy=1;


void rebotar()
{
  int limite = 5;
  if(estados[xx][yy-5]==0)
  {
    limite=yy+1;
    if(limite>7)
      limite=7;
  }
  if(!((7>xx)&&(xx>0)))
    dirX=!dirX;
  if(!((limite>yy)&&(yy>1)))
    dirY=!dirY;
  if(yy==1)
  {
    if(xx==(barraInicial+1))
    {
      //No rebotar hacia los lados
      diagonal=false;
    }
    else if((xx<barraInicial)||(xx>(barraInicial+2)))
    {
      //afuera
      blink();
    }
    else
    {
      diagonal=true;
      if(dirX)
        xx++;
      else
        xx--;
      if(xx<0)
        xx=0;
   }
  }
  if(diagonal)
  {
    if(dirX)
      xx++;
    else
      xx--;
    if(xx<0)
      xx=0;
  }
  if(dirY)
    yy++;
  else
    yy--;
  pelota(xx,yy,limite);
}

void golpear(int x, int y)
{
  if(estados[x][y-5]==rojo)
  {
    estados[x][y-5]=azul;
  }
  else if(estados[x][y-5]==azul)
  {
    estados[x][y-5]=verde;
  }
  else if(estados[x][y-5]==verde)
  {
    estados[x][y-5]=0;
  }
}

 void pelota(int x, int y,int limite)
{
  for(int i = 0;i<8;i++)
  {
    if((y>4)&&(i==x))
    {
      if((estados[x][y-5]!=0)&&(golpe==false))
      {
        Serial.print("Golpe: ");
        Serial.print(x);
        Serial.print(", ");
        Serial.println(y);
        golpear(x,y);
        golpe=true;
      }
    }
    for(int j=1;j<=limite;j++)
    {
      if((i==x)&&(j==y))
      {
        matrix.drawPixel(x,y,blanco);
        Serial.print("Pelota: ");
        Serial.print(x);
        Serial.print(", ");
        Serial.print(y);
        Serial.print(", ");
        Serial.println(limite);
        if(j<limite)
          golpe=false;
      }
      else
        if(j<5)
          matrix.drawPixel(i,j,0);
        else
        {
          if(estados[i][j-5]==0)
            matrix.drawPixel(i,j,0);
        } 
    }
  }
  matrix.show();
  delay(retraso);
}
                                    
                                

Paso 6:

Crear las funciones que se despliegan en caso de ganar o perder.

Código:

                                    
                                            void blink()
{
  while(1)
  {
    matrix.fillScreen(0);
    matrix.show();
    delay(500);
    matrix.fillScreen(matrix.Color(255,0,0));
    matrix.show();
    delay(500);
  }
}

void showGanar()
{
  while(1)
  {
    matrix.fillScreen(0);
    matrix.show();
    delay(500);
    matrix.fillScreen(matrix.Color(0,255,0));
    matrix.show();
    delay(500);
  }
}
                                    
                                

Paso 7:

Generar un código que cada determinado tiempo, aumente la velocidad a la que se desplaza la pelota por la pantalla.

Código:

                                    
                                            //En globales
#define PERIODO 15000

long tiempo;

//Al final del setup
tiempo=millis();

//Al comienzo de main
if(millis()-tiempo>=PERIODO)
  {
    retraso -= 75;
    if(retraso<50)
      retraso=50;
    Serial.println(retraso);
    tiempo=millis();
  }
                                    
                                

Paso 8:

Detectar cuando se destruye el último ladrillo y desplegar la pantalla de victoria. Así mismo, llamar a las funciones previamente creadas.

Código:

                                    
                                            //Al final de main

bool ganar = true;

  for(int i =0;i<8;i++)
  {
    matrix.drawPixel(i,5, estados[i][0]);
    matrix.drawPixel(i,6, estados[i][1]);
    matrix.drawPixel(i,7, estados[i][2]);
    if(estados[i][0]!=0)
      ganar = false;
    if(estados[i][1]!=0)
      ganar = false;
    if(estados[i][2]!=0)
      ganar = false;
  }
  if(ganar)
    showGanar();
  barra(barraInicial);
  matrix.show();
  rebotar();
  delay(50);
                                    
                                

Paso 9:

Código:

                                    
                                            #include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
 #define PSTR // Make Arduino Due happy
#endif

#define PIN 6

#define PERIODO 15000
#define BRILLO 25

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, PIN,
  NEO_MATRIX_BOTTOM     + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
  NEO_GRB            + NEO_KHZ800);

const uint16_t blanco = matrix.Color(255,255,255);
const uint16_t rojo = matrix.Color(255, 0, 0);
const uint16_t verde = matrix.Color(0, 255, 0);
const uint16_t azul = matrix.Color(0,0,255);

uint16_t estados[8][3];

long tiempo;
int retraso = 500;

bool diagonal=false;
bool golpe = false;
bool dirX;
bool dirY;
int barraInicial=0;
int xx=0, yy=1;

void setup() {
  matrix.begin();
  matrix.setBrightness(BRILLO);
  matrix.fillScreen(0);
  matrix.show();
  llenar();
  Serial.begin(9600);
  pinMode(A1,INPUT_PULLUP);
  tiempo=millis();
}

void loop() {
  if(millis()-tiempo>=PERIODO)
  {
    retraso -= 75;
    if(retraso<50)
      retraso=50;
    Serial.println(retraso);
    tiempo=millis();
  }
  bool ganar = true;
  int lectura = analogRead(A0);
  //Serial.println(lectura);
  if(lectura<100)
  {
    if(barraInicial>0)
      barraInicial--;
  }
  else if(lectura>900)
    if(barraInicial<5)
      barraInicial++;
  for(int i =0;i<8;i++)
  {
    matrix.drawPixel(i,5, estados[i][0]);
    matrix.drawPixel(i,6, estados[i][1]);
    matrix.drawPixel(i,7, estados[i][2]);
    if(estados[i][0]!=0)
      ganar = false;
    if(estados[i][1]!=0)
      ganar = false;
    if(estados[i][2]!=0)
      ganar = false;
  }
  if(ganar)
    showGanar();
  barra(barraInicial);
  matrix.show();
  rebotar();
  delay(50);
}

void llenar()
{
  for(int i=0;i<8;i++)
  {
    estados[i][0]=rojo;
    estados[i][1]=rojo;
    estados[i][2]=rojo;
  }
}

void golpear(int x, int y)
{
  if(estados[x][y-5]==rojo)
  {
    estados[x][y-5]=azul;
  }
  else if(estados[x][y-5]==azul)
  {
    estados[x][y-5]=verde;
  }
  else if(estados[x][y-5]==verde)
  {
    estados[x][y-5]=0;
  }
}

void blink()
{
  while(1)
  {
    matrix.fillScreen(0);
    matrix.show();
    delay(500);
    matrix.fillScreen(matrix.Color(255,0,0));
    matrix.show();
    delay(500);
  }
}

void showGanar()
{
  while(1)
  {
    matrix.fillScreen(0);
    matrix.show();
    delay(500);
    matrix.fillScreen(matrix.Color(0,255,0));
    matrix.show();
    delay(500);
  }
}

void barra(int inicial) 
{
  for(int i = 0;i<8;i++) //Limpiar barra
  {
    matrix.drawPixel(i,0,0);
  }
  matrix.drawPixel(inicial, 0, blanco);
  matrix.drawPixel(inicial+1, 0, blanco);
  matrix.drawPixel(inicial+2, 0, blanco);
  //matrix.show();
}

void pelota(int x, int y,int limite)
{
  for(int i = 0;i<8;i++)
  {
    if((y>4)&&(i==x))
    {
      if((estados[x][y-5]!=0)&&(golpe==false))
      {
        Serial.print("Golpe: ");
        Serial.print(x);
        Serial.print(", ");
        Serial.println(y);
        golpear(x,y);
        golpe=true;
      }
    }
    for(int j=1;j<=limite;j++)
    {
      if((i==x)&&(j==y))
      {
        matrix.drawPixel(x,y,blanco);
        Serial.print("Pelota: ");
        Serial.print(x);
        Serial.print(", ");
        Serial.print(y);
        Serial.print(", ");
        Serial.println(limite);
        if(j<limite)
          golpe=false;
      }
      else
        if(j<5)
          matrix.drawPixel(i,j,0);
        else
        {
          if(estados[i][j-5]==0)
            matrix.drawPixel(i,j,0);
        } 
    }
  }
  matrix.show();
  delay(retraso);
}

void rebotar()
{
  int limite = 5;
  if(estados[xx][yy-5]==0)
  {
    limite=yy+1;
    if(limite>7)
      limite=7;
  }
  if(!((7>xx)&&(xx>0)))
    dirX=!dirX;
  if(!((limite>yy)&&(yy>1)))
    dirY=!dirY;
  if(yy==1)
  {
    if(xx==(barraInicial+1))
    {
      //No rebotar hacia los lados
      diagonal=false;
    }
    else if((xx<barraInicial)||(xx>(barraInicial+2)))
    {
      //afuera
      blink();
    }
    else
    {
      diagonal=true;
      if(dirX)
        xx++;
      else
        xx--;
      if(xx<0)
        xx=0;
   }
  }
  if(diagonal)
  {
    if(dirX)
      xx++;
    else
      xx--;
    if(xx<0)
      xx=0;
  }
  if(dirY)
    yy++;
  else
    yy--;
  pelota(xx,yy,limite);
}
                                    
                                

Comentarios:

  • Mrhofflich Mrhofflich

    Tendrán algún video del proyecto funcionando?

    01/07/2016

  • DariusLau DariusLau

    Y una lista de lo necesario para el proyecto! :D Básico para entender qué compone el proyecto desde el principio

    01/07/2016

  • ViriCruz ViriCruz

    muy buen tuto, con muchos pasos para no perderse en el camino, lo único que si les sugiero es que comenten el código, aparte de que nos sirve para saber que es lo que hace cada línea, les servirá a ustedes en un futuro por si olvidan como funciona el código. Por ahi vi un link de fb con el video, no lo abre la red aqui, pero que bien que hayan subido un video de demostración para saber que es lo que vamos a tener como producto final al terminar de seguir su tutorial :D. Se la rifaron!, también ayudaría que explicaran como funciona la matriz de leds :D

    01/07/2016

  • Vero4100 Vero4100

    Hola :) Nuestros videos están en el paso 9. La lista de los materiales en el paso 0. Comentaremos el código para explicarlo.

    09/07/2016

mode_edit