Tetris con VGA en Arduino
¿Qué es ArduBoy?
Arduboy es una «consola» nos permite jugar al tetris. Es perfecto para todas las edades puesto que ArduBoy se adapta a cualquier pantalla que tenga VGA. Esto está pensado para todas aquellas personas que tengan problemas con su vista, puesto que no tendrá que jugar en una reducida pantalla donde dejarse los ojos. Además es perfecto para jugar en cualquier lugar donde exista una pantalla, por lo que puedes llevártelo a donde quieras.
¿Cómo funciona?
ArduBoy funciona gracias a un VGA que tenemos en nuestra cajita que se usa como mando a través del cual, con el cable VGA, lo podemos conectar a cualquier pantalla. Para usarlo simplemente tenemos que conectarlo a la pantalla y cuando pulsemos uno de los 4 botones empezará el juego. Si vas a realizar este proyecto, te recomiendo que utilices la librería desarrollada por Sandro Maffiodo para VGA puesto que podrás encontrar ejemplos y viene información acerca de los pixeles de la pantalla y como utilizarlos.
A continuación de tejo el enlace donde poder encontrar esta librería en Github: https://github.com/smaffer/vgax
¿Qué necesitamos para que ArduBoy funcione?
- Arduino Uno
Esta placa es de la marca Elegoo pero funciona igual que Arduino Uno, puedes conectar leds, resistencias, pulsadores, lcds y todo lo que te imagines. Solo tienes que conectarlo al ordenador mediante el cable y subir el Sketch.
- Caja de madera y pulsadores
La caja la utilizamos para que haga a modo de mando y además podamos guardar ahí todas las conexiones sin que los cables sueltos nos molesten, se enganchen o queden desprotegidos. Los pulsadores nos servirán para poder rotar las figuras, desplazarlas tanto a la derecha como a la izquierda y hacer que bajen más rápido.
- Cables y estaño
Necesitamos cables para poder realizar las distintas uniones entre los botones, el VGA, las resistencias… con la placa del Arduino Uno, así como necesitaremos el estaño para que estas uniones sean fijas y duraderas.
- Resistencias
Necesitaremos múltiples resistencias para disminuir la electricidad, de este modo utilizaremos dos resistencias de 470 ohmnios para los pines 1 y 2 del VGA y dos resistencias de 68 ohmnios en los pines 13 y 14 del VGA; también necesitaremos 4 resistencias de 2K ohmnios, una para cada uno de los pulsadores.
- Cabeza VGA hembra para chasis
Imprescindible para poder conectar nuestro Sketch en Arduino con cualquier pantalla mediante un cable VGA.
El presupuesto del proyecto es el siguiente:
¿Cómo llegamos al producto final?
Circuito y código
El sketch utilizado es el siguiente:
#include <VGAXUtils.h>
#include <math.h>
#define FNT_NANOFONT_HEIGHT 6
#define FNT_NANOFONT_SYMBOLS_COUNT 95
VGAX vga;
VGAXUtils vgaU;
//data size=570 bytes
const unsigned char fnt_nanofont_data[FNT_NANOFONT_SYMBOLS_COUNT][1+FNT_NANOFONT_HEIGHT] PROGMEM={
{ 1, 128, 128, 128, 0, 128, 0, }, //glyph '!' code=0
{ 3, 160, 160, 0, 0, 0, 0, }, //glyph '"' code=1
//{ 5, 80, 248, 80, 248, 80, 0, }, //glyph '#' code=2
{ 5, 248, 248, 248, 248, 248, 0, }, //glyph '#' code=2
{ 5, 120, 160, 112, 40, 240, 0, }, //glyph '$' code=3
{ 5, 136, 16, 32, 64, 136, 0, }, //glyph '%' code=4
{ 5, 96, 144, 104, 144, 104, 0, }, //glyph '&' code=5
{ 2, 128, 64, 0, 0, 0, 0, }, //glyph ''' code=6
{ 2, 64, 128, 128, 128, 64, 0, }, //glyph '(' code=7
{ 2, 128, 64, 64, 64, 128, 0, }, //glyph ')' code=8
{ 3, 0, 160, 64, 160, 0, 0, }, //glyph '*' code=9
{ 3, 0, 64, 224, 64, 0, 0, }, //glyph '+' code=10
{ 2, 0, 0, 0, 0, 128, 64, }, //glyph ',' code=11
{ 3, 0, 0, 224, 0, 0, 0, }, //glyph '-' code=12
{ 1, 0, 0, 0, 0, 128, 0, }, //glyph '.' code=13
{ 5, 8, 16, 32, 64, 128, 0, }, //glyph '/' code=14
{ 4, 96, 144, 144, 144, 96, 0, }, //glyph '0' code=15
{ 3, 64, 192, 64, 64, 224, 0, }, //glyph '1' code=16
{ 4, 224, 16, 96, 128, 240, 0, }, //glyph '2' code=17
{ 4, 224, 16, 96, 16, 224, 0, }, //glyph '3' code=18
{ 4, 144, 144, 240, 16, 16, 0, }, //glyph '4' code=19
{ 4, 240, 128, 224, 16, 224, 0, }, //glyph '5' code=20
{ 4, 96, 128, 224, 144, 96, 0, }, //glyph '6' code=21
{ 4, 240, 16, 32, 64, 64, 0, }, //glyph '7' code=22
{ 4, 96, 144, 96, 144, 96, 0, }, //glyph '8' code=23
{ 4, 96, 144, 112, 16, 96, 0, }, //glyph '9' code=24
{ 1, 0, 128, 0, 128, 0, 0, }, //glyph ':' code=25
{ 2, 0, 128, 0, 0, 128, 64, }, //glyph ';' code=26
{ 3, 32, 64, 128, 64, 32, 0, }, //glyph '<' code=27
{ 3, 0, 224, 0, 224, 0, 0, }, //glyph '=' code=28
{ 3, 128, 64, 32, 64, 128, 0, }, //glyph '>' code=29
{ 4, 224, 16, 96, 0, 64, 0, }, //glyph '?' code=30
{ 4, 96, 144, 176, 128, 112, 0, }, //glyph '@' code=31
{ 4, 96, 144, 240, 144, 144, 0, }, //glyph 'A' code=32
{ 4, 224, 144, 224, 144, 224, 0, }, //glyph 'B' code=33
{ 4, 112, 128, 128, 128, 112, 0, }, //glyph 'C' code=34
{ 4, 224, 144, 144, 144, 224, 0, }, //glyph 'D' code=35
{ 4, 240, 128, 224, 128, 240, 0, }, //glyph 'E' code=36
{ 4, 240, 128, 224, 128, 128, 0, }, //glyph 'F' code=37
{ 4, 112, 128, 176, 144, 112, 0, }, //glyph 'G' code=38
{ 4, 144, 144, 240, 144, 144, 0, }, //glyph 'H' code=39
{ 3, 224, 64, 64, 64, 224, 0, }, //glyph 'I' code=40
{ 4, 240, 16, 16, 144, 96, 0, }, //glyph 'J' code=41
{ 4, 144, 160, 192, 160, 144, 0, }, //glyph 'K' code=42
{ 4, 128, 128, 128, 128, 240, 0, }, //glyph 'L' code=43
{ 5, 136, 216, 168, 136, 136, 0, }, //glyph 'M' code=44
{ 4, 144, 208, 176, 144, 144, 0, }, //glyph 'N' code=45
{ 4, 96, 144, 144, 144, 96, 0, }, //glyph 'O' code=46
{ 4, 224, 144, 224, 128, 128, 0, }, //glyph 'P' code=47
{ 4, 96, 144, 144, 144, 96, 16, }, //glyph 'Q' code=48
{ 4, 224, 144, 224, 160, 144, 0, }, //glyph 'R' code=49
{ 4, 112, 128, 96, 16, 224, 0, }, //glyph 'S' code=50
{ 3, 224, 64, 64, 64, 64, 0, }, //glyph 'T' code=51
{ 4, 144, 144, 144, 144, 96, 0, }, //glyph 'U' code=52
{ 3, 160, 160, 160, 160, 64, 0, }, //glyph 'V' code=53
{ 5, 136, 168, 168, 168, 80, 0, }, //glyph 'W' code=54
{ 4, 144, 144, 96, 144, 144, 0, }, //glyph 'X' code=55
{ 3, 160, 160, 64, 64, 64, 0, }, //glyph 'Y' code=56
{ 4, 240, 16, 96, 128, 240, 0, }, //glyph 'Z' code=57
{ 2, 192, 128, 128, 128, 192, 0, }, //glyph '[' code=58
{ 5, 128, 64, 32, 16, 8, 0, }, //glyph '\' code=59
{ 2, 192, 64, 64, 64, 192, 0, }, //glyph ']' code=60
{ 5, 32, 80, 136, 0, 0, 0, }, //glyph '^' code=61
{ 4, 0, 0, 0, 0, 240, 0, }, //glyph '_' code=62
{ 2, 128, 64, 0, 0, 0, 0, }, //glyph '`' code=63
{ 3, 0, 224, 32, 224, 224, 0, }, //glyph 'a' code=64
{ 3, 128, 224, 160, 160, 224, 0, }, //glyph 'b' code=65
{ 3, 0, 224, 128, 128, 224, 0, }, //glyph 'c' code=66
{ 3, 32, 224, 160, 160, 224, 0, }, //glyph 'd' code=67
{ 3, 0, 224, 224, 128, 224, 0, }, //glyph 'e' code=68
{ 2, 64, 128, 192, 128, 128, 0, }, //glyph 'f' code=69
{ 3, 0, 224, 160, 224, 32, 224, }, //glyph 'g' code=70
{ 3, 128, 224, 160, 160, 160, 0, }, //glyph 'h' code=71
{ 1, 128, 0, 128, 128, 128, 0, }, //glyph 'i' code=72
{ 2, 0, 192, 64, 64, 64, 128, }, //glyph 'j' code=73
{ 3, 128, 160, 192, 160, 160, 0, }, //glyph 'k' code=74
{ 1, 128, 128, 128, 128, 128, 0, }, //glyph 'l' code=75
{ 5, 0, 248, 168, 168, 168, 0, }, //glyph 'm' code=76
{ 3, 0, 224, 160, 160, 160, 0, }, //glyph 'n' code=77
{ 3, 0, 224, 160, 160, 224, 0, }, //glyph 'o' code=78
{ 3, 0, 224, 160, 160, 224, 128, }, //glyph 'p' code=79
{ 3, 0, 224, 160, 160, 224, 32, }, //glyph 'q' code=80
{ 3, 0, 224, 128, 128, 128, 0, }, //glyph 'r' code=81
{ 2, 0, 192, 128, 64, 192, 0, }, //glyph 's' code=82
{ 3, 64, 224, 64, 64, 64, 0, }, //glyph 't' code=83
{ 3, 0, 160, 160, 160, 224, 0, }, //glyph 'u' code=84
{ 3, 0, 160, 160, 160, 64, 0, }, //glyph 'v' code=85
{ 5, 0, 168, 168, 168, 80, 0, }, //glyph 'w' code=86
{ 3, 0, 160, 64, 160, 160, 0, }, //glyph 'x' code=87
{ 3, 0, 160, 160, 224, 32, 224, }, //glyph 'y' code=88
{ 2, 0, 192, 64, 128, 192, 0, }, //glyph 'z' code=89
{ 3, 96, 64, 192, 64, 96, 0, }, //glyph '{' code=90
{ 1, 128, 128, 128, 128, 128, 0, }, //glyph '|' code=91
{ 3, 192, 64, 96, 64, 192, 0, }, //glyph '}' code=92
{ 3, 96, 192, 0, 0, 0, 0, }, //glyph '~' code=93
{ 4, 48, 64, 224, 64, 240, 0, }, //glyph '£' code=94
};
static const char str10[] PROGMEM="#";
static const char str11[] PROGMEM="ArduBoy";
static const char str12[] PROGMEM="Pulsa para empezar";
static const char str13[] PROGMEM="Game";
static const char str14[] PROGMEM="Over!";
boolean button = 0;
boolean button_1 = 0;
boolean button_2 = 0;
boolean button_3 = 0;
boolean button_4 = 0;
int block[4][2]={{0,0},{0,0},{0,0},{0,0}}; //va a ser para las fichas
int blockExt[4][2]={{0,0},{0,0},{0,0},{0,0}}; //para los monitores 4:3
int blockOld[4][2]={{0,0},{0,0},{0,0},{0,0}}; //las fichas antiguas que ya están en la pantalla
int blockTmp[4][2]={{0,0},{0,0},{0,0},{0,0}};
int blockTr[4][2]={{0,0},{0,0},{0,0},{0,0}};
int yLine[4] = {0,0,0,0};
int yLineTmp[4] = {0,0,0,0};
int yCounter = 0;
int x = 60;
int y = 6;
int z = 10;
int score; //la puntuacion
int noLoop = (-1);
int clock = 1;
int delta = 0;
int color = 1;
int colorOld;
int blockN;
int blockNext;
int busy;
int noDelete = 0;
int k = 0;
int a = 40;
int b = 10;
int counterMenu = 0;
unsigned long time = 0;
int fast = 14; //14;
void processInputs() { //para que sirve esto
if(button_1 == 1) {
button_2 = digitalRead(A2);
button_3 = digitalRead(A3);
button_4 = digitalRead(A4);
button_1 = 0;
vga.delay(25);
}
else{
if(button_2 == 1) {
button_1 = digitalRead(A1);
button_3 = digitalRead(A3);
button_4 = digitalRead(A4);
button_2 = 0;
vga.delay(25);
}
else{
if(button_3 == 1) {
button_1 = digitalRead(A1);
button_2 = digitalRead(A2);
button_4 = digitalRead(A4);
button_3 = 0;
vga.delay(25);
}
else{
if(button_4 == 1) {
button_1 = digitalRead(A1);
button_2 = digitalRead(A2);
button_3 = digitalRead(A3);
button_4 = 0;
//vga.delay(25);
}
else{
button_1 = digitalRead(A1);
button_2 = digitalRead(A2);
button_3 = digitalRead(A3);
button_4 = digitalRead(A4);
}
}
}
}
button = button_2 || button_4;
}
void clearInputs() { //cuando se usa
button_1 = 0;
button_2 = 0;
button_3 = 0;
button_4 = 0;
button = 0;
}
void drawMenu() {
while (button_1 == 0 && button_2 == 0 && button_3 == 0 && button_4 == 0) { //Mientras que no pulsemos ningun botón
processInputs();
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str11, 26, 16, (counterMenu%3) + 1);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str12, 28, 28, (counterMenu%3) + 1);
vga.delay(1000);
counterMenu++;
}
vga.clear(0);
drawGameScreen();
drawScore(score);
}
void drawScore(int i) {
if (i > 39){
score = 0;
i = 0;
fast = fast - 4;
if (fast < 3){
fast = 2;
}
}
vgaU.draw_line(20, 10, 20, 50, 3);
vgaU.draw_line(20, 50, 20, 50 - i, 1);
vgaU.draw_line(19, 10, 22, 10, 3);
vgaU.draw_line(19, 50, 22, 50, 3);
}
void drawGameScreen() { //Dibujamos el borde de la pantalla del tetris
vgaU.draw_line(44,0,78,0,3);
vgaU.draw_line(44,59,78,59,3);
vgaU.draw_line(44,0,44,59,3);
vgaU.draw_line(78,0,78,60,3);
}
void blockDef(int i) { //Definición de las fichas
if (i == 1){ //El cuadrado
block[0][0] = 0;
block[0][1] = 0;
block[1][0] = 1;
block[1][1] = 0;
block[2][0] = 0;
block[2][1] = 1;
block[3][0] = 1;
block[3][1] = 1;
color = 1;
}
if (i == 2){ //La L
block[0][0] = -1;
block[0][1] = 0;
block[1][0] = 0;
block[1][1] = 0;
block[2][0] = 1;
block[2][1] = 0;
block[3][0] = -1;
block[3][1] = 1;
color = 2;
}
if (i == 3){ //La J
block[0][0] = -1;
block[0][1] = 0;
block[1][0] = 0;
block[1][1] = 0;
block[2][0] = 1;
block[2][1] = 0;
block[3][0] = 1;
block[3][1] = 1;
color = 3;
}
if (i == 4){ //El palo
block[0][0] = -1;
block[0][1] = 0;
block[1][0] = 0;
block[1][1] = 0;
block[2][0] = 1;
block[2][1] = 0;
block[3][0] = 2;
block[3][1] = 0;
color = 1;
}
if (i == 5){ //La S
block[0][0] = -1;
block[0][1] = 0;
block[1][0] = 0;
block[1][1] = 0;
block[2][0] = 0;
block[2][1] = 1;
block[3][0] = 1;
block[3][1] = 1;
color = 2;
}
if (i == 6){ //La Z
block[0][0] = -1;
block[0][1] = 1;
block[1][0] = 0;
block[1][1] = 1;
block[2][0] = 0;
block[2][1] = 0;
block[3][0] = 1;
block[3][1] = 0;
color = 3;
}
if (i == 7){ //La T
block[0][0] = -1;
block[0][1] = 0;
block[1][0] = 0;
block[1][1] = 0;
block[2][0] = 0;
block[2][1] = 1;
block[3][0] = 1;
block[3][1] = 0;
color = 1;
}
}
void blockExtension() { //Extension para los monitores 4:3 porque sino no se ve correctamente
for (int i = 0; i < 4; i++){
blockExt[0][0] = block[0][0]*3;
blockExt[0][1] = block[0][1]*2;
blockExt[1][0] = block[1][0]*3;
blockExt[1][1] = block[1][1]*2;
blockExt[2][0] = block[2][0]*3;
blockExt[2][1] = block[2][1]*2;
blockExt[3][0] = block[3][0]*3;
blockExt[3][1] = block[3][1]*2;
}
}
void blockRotation(int clock){ //Para los giros guardamos la información actual en la variable
for (int i = 0; i < 4; i++){
blockOld[0][0] = block[0][0];
blockOld[0][1] = block[0][1];
blockOld[1][0] = block[1][0];
blockOld[1][1] = block[1][1];
blockOld[2][0] = block[2][0];
blockOld[2][1] = block[2][1];
blockOld[3][0] = block[3][0];
blockOld[3][1] = block[3][1];
}
for (int i = 0; i < 4; i++){ //Modificamos la información actual de acuerdo a la información de la variable almacenada
block[0][0] = blockOld[0][1]*clock;
block[0][1] = -blockOld[0][0]*clock;
block[1][0] = blockOld[1][1]*clock;
block[1][1] = -blockOld[1][0]*clock;
block[2][0] = blockOld[2][1]*clock;
block[2][1] = -blockOld[2][0]*clock;
block[3][0] = blockOld[3][1]*clock;
block[3][1] = -blockOld[3][0]*clock;
}
}
void blockTranslation(int x, int y) { //Para las traslaciones
for (int i = 0; i < 4; i++){
blockTr[0][0] = blockExt[0][0] + x;
blockTr[0][1] = blockExt[0][1] + y;
blockTr[1][0] = blockExt[1][0] + x;
blockTr[1][1] = blockExt[1][1] + y;
blockTr[2][0] = blockExt[2][0] + x;
blockTr[2][1] = blockExt[2][1] + y;
blockTr[3][0] = blockExt[3][0] + x;
blockTr[3][1] = blockExt[3][1] + y;
}
}
void delBlock(){
if (noDelete == 1) {noDelete = 0;}
else {
for (int i = 0; i < 4; i++){
vgaU.draw_line(blockTr[i][0],blockTr[i][1],blockTr[i][0] + 3,blockTr[i][1],0);
vgaU.draw_line(blockTr[i][0],blockTr[i][1] + 1,blockTr[i][0] + 3,blockTr[i][1] + 1,0);
}
}
}
void drawBlock(){ //Para darle color a la ficha
for (int i = 0; i < 4; i++){
vgaU.draw_line(blockTr[i][0],blockTr[i][1],blockTr[i][0] + 3,blockTr[i][1], color);
vgaU.draw_line(blockTr[i][0],blockTr[i][1] + 1,blockTr[i][0] + 3,blockTr[i][1] + 1, color);
}
for (int i = 0; i < 4; i++){
blockTmp[0][0] = blockTr[0][0];
blockTmp[0][1] = blockTr[0][1];
blockTmp[1][0] = blockTr[1][0];
blockTmp[1][1] = blockTr[1][1];
blockTmp[2][0] = blockTr[2][0];
blockTmp[2][1] = blockTr[2][1];
blockTmp[3][0] = blockTr[3][0];
blockTmp[3][1] = blockTr[3][1];
}
}
void drawBlockTmp(){ //Para que la copia tambien tenga color
for (int i = 0; i < 4; i++){
vgaU.draw_line(blockTmp[i][0],blockTmp[i][1],blockTmp[i][0] + 3,blockTmp[i][1], color);
vgaU.draw_line(blockTmp[i][0],blockTmp[i][1] + 1,blockTmp[i][0] + 3,blockTmp[i][1] + 1, color);
}
}
void checkBlock(){ //Para ver si esta bien el bloque
busy = 0;
for (int i = 0; i < 4; i++){
busy = busy + vga.getpixel(blockTr[i][0], blockTr[i][1]) + vga.getpixel(blockTr[i][0] + 2, blockTr[i][1]);
}
}
void replaceBlock(){
blockExtension();
blockTranslation(x, y);
checkBlock();
if (busy == 0){
drawBlock();
}
else
{
drawBlockTmp();
checkForFullLine();
noLoop = 0;
noDelete = 1;
if (y < 6) {
gameOver();
}
}
vga.delay(50);
}
void gameOver(){ //Reestablece los parametros cuando hemos perdido
noLoop = -1;
score = 0;
fast = 14;
clearInputs();
time = 0;
while (button_1 == 0 && button_2 == 0 && button_3 == 0 && button_4 == 0) {
processInputs();
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str13, 92, 30, 1);
vga.printPROGMEM((byte*)fnt_nanofont_data, FNT_NANOFONT_SYMBOLS_COUNT, FNT_NANOFONT_HEIGHT, 3, 1, str14, 92, 38, 1);
vga.delay(200);
}
vga.clear(0);
}
void drawBlockNext(){ //Dibuja la siguiente dicha en la derecha
blockExtension();
blockTranslation(100, 10);
vgaU.draw_line(95, 8, 112, 8, 0);
vgaU.draw_line(95, 9, 112, 9, 0);
vgaU.draw_line(95, 10, 112, 10, 0);
vgaU.draw_line(95, 11, 112, 11, 0);
vgaU.draw_line(95, 12, 112, 12, 0);
vgaU.draw_line(95, 13, 112, 13, 0);
vgaU.draw_line(95, 14, 112, 14, 0);
vgaU.draw_line(95, 15, 112, 15, 0);
drawBlock();
}
void checkBlockTranslation(){
x = x + delta;
blockExtension();
blockTranslation(x, y);
checkBlock();
if (busy == 0){
drawBlock();
}
else
{
x = x - delta;
blockExtension();
blockTranslation(x, y);
drawBlock();
}
vga.delay(50);
}
void checkBlockRotation(){
blockExtension();
blockTranslation(x, y);
checkBlock();
if (busy == 0){
drawBlock();
}
else
{
clock = +1;
blockRotation(clock);
blockExtension();
blockTranslation(x, y);
drawBlock();
}
vga.delay(50);
}
void checkForFullLine() { //Mira si la linea está completa
for (int i = 0; i < 4; i++){
for (int j = 45; j < 76; j += 3) {
if (vga.getpixel(j, blockTmp[i][1]) >0){k++; }
}
if (k == 11) { //si está completa la borra
vgaU.draw_line(45, blockTmp[i][1], 78, blockTmp[i][1], 0);
vgaU.draw_line(45, blockTmp[i][1] + 1, 78, blockTmp[i][1] + 1, 0);
yLineTmp[yCounter] = blockTmp[i][1];
yLine[yCounter] = blockTmp[i][1];
yCounter++;
}
k = 0;
}
if (yLineTmp[yCounter - 1] < yLine[0]) {
for (int i = 0; i < yCounter; i++) {
yLine[i] = yLineTmp[yCounter - i - 1];
}
}
for (int i = 0; i < yCounter; i++){ //Mueve las fichas una linea abajo
for (int y = yLine[i] - 2; y > 0; y = y - 2) {
for (int x = 45; x < 76; x += 3) {
colorOld = vga.getpixel(x, y);
if (colorOld > 0) {
vgaU.draw_line(x, y , x + 3, y , 0);
vgaU.draw_line(x, y + 1, x + 3, y + 1, 0);
vgaU.draw_line(x, y + 2, x + 3, y + 2, colorOld);
vgaU.draw_line(x, y + 3, x + 3, y + 3, colorOld);
}
}
}
}
if (yCounter != 0) {score = score + 2*int(pow(2, yCounter));}
drawScore(score);
yCounter = 0;
}
void setup() {
pinMode(A1, INPUT); //Para que vaya a la derecha/izquierda
pinMode(A2, INPUT); //Para girar la figura
pinMode(A3, INPUT); //Para que vaya a la derecha/izquierda
pinMode(A4, INPUT); //Para que bajen más rapido
vga.begin();
randomSeed(analogRead(A5));
}
void loop() { //Programa principal
processInputs();
if (noLoop < 1){ // Generamos nuevas fichas
blockN = blockNext;
if (noLoop == -1 ) { //Solo ocurre al principio del juego
drawMenu();
while (button_1 == 0 && button_2 == 0 && button_3 == 0 && button_4 == 0) {
blockN = int(random(7)) + 1;
processInputs();
}
}
drawGameScreen();
drawScore(score);
blockNext = int(random(8));
blockDef(blockNext);
drawBlockNext();
blockDef(blockN);
x = 57;
y = 3;
button_1 = 1;
noLoop = 1;
}
if (button_2 == 1){ //Rotar
if (button_2 == 1){clock = -1;}
delBlock();
blockRotation(clock);
checkBlockRotation();
}
if (button_1 == 1 || button_3 == 1){ //Trasladar
if (button_1 == 1){delta = 3;}
if (button_3 == 1){delta = -3;}
delBlock();
checkBlockTranslation();
}
time++;
if (time % fast > fast - 2 || button_4 == 1){ //Caida de las fichas
if (fast < 3) {fast = 2;}
y = y + 2;
delBlock();
replaceBlock();
}
vga.delay(10 + 2*fast);
}
Para realizar la petición y poder utilizar la API son necesarias las siguientes librerías:
#include <VGAXUtils.h>
#include <math.h>
Algunas dificultades que he encontrado mientras hacía el ArduBoy han sido:
A la hora de colocar las cosas en la pantalla fue bastante complicado al principio el como colocar los pixeles pero, por suerte, en la librería mencionada anteriormente viene muy bien explicado.
Futuras mejoras:
- Incluir más juegos al ArduBoy para que exista una mayor variedad.
- Ponerle un color distinto a cada ficha del tetris.




