restructure code and add simple collision detection

This commit is contained in:
Dan Frumin 2019-09-01 18:31:04 +02:00
parent afeabd81e7
commit bd05d23800
2 changed files with 133 additions and 52 deletions

View File

@ -10,6 +10,10 @@ CTAGS_CMD = $(CTAGS_PATH) -auef
TAGS_FILE = TAGS TAGS_FILE = TAGS
all: all:
$(ARDUINO) --verify tetris.ino
upload:
$(ARDUINO) --upload tetris.ino $(ARDUINO) --upload tetris.ino

View File

@ -2,42 +2,53 @@
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
#include <SPI.h> #include <SPI.h>
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library // We assume the size of the screen 120x160
// pins are defined un User_Setup.h #define GRID_WIDTH 12
#define GRID_HEIGHT 16
#define BLOCK_SIZE 10
#define BLOCK_MARGIN 2
const int BTN1_PIN = 25; const int BTN1_PIN = 25;
volatile bool btn1_pressed = false; volatile bool btn1_pressed = false;
const int BTN2_PIN = 33; const int BTN2_PIN = 33;
volatile bool btn2_pressed = false; volatile bool btn2_pressed = false;
// I am using ST7735S, a very cheap display from aliexpress
TFT_eSPI tft = TFT_eSPI();
// pins are defined un User_Setup.h
// forward declarations // forward declarations
void IRAM_ATTR isr1(); void IRAM_ATTR isr1();
void IRAM_ATTR isr2(); void IRAM_ATTR isr2();
void setup() { // the main board and the offboard, to check for dirty squares
tft.init(); // initialize a ST7735S chip
// set up the buttons and the interrupts
pinMode(BTN1_PIN, INPUT_PULLUP);
attachInterrupt(BTN1_PIN, isr1, FALLING);
pinMode(BTN2_PIN, INPUT_PULLUP);
attachInterrupt(BTN2_PIN, isr2, FALLING);
init_board();
delay(100);
}
#define GRID_WIDTH 12
#define GRID_HEIGHT 18
#define BLOCK_SIZE 10
#define BLOCK_MARGIN 2
#define BLOCK_WIDTH 20
#define BLOCK_HEIGHT 30
uint32_t main_board[GRID_WIDTH][GRID_HEIGHT], offboard[GRID_WIDTH][GRID_HEIGHT]; uint32_t main_board[GRID_WIDTH][GRID_HEIGHT], offboard[GRID_WIDTH][GRID_HEIGHT];
/*
The value (i,j) on the board is given by main_board[i][j].
if board(i,j) = 0, then the space there is empty
otherwise board(i,j)'s first bit determines whether the block is "old" or not, and the rest denotes a color
*/
/* Blocks are defined in grids of 4x4:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
*/
#define BLOCKS_COUNT 2
uint8_t blocks[BLOCKS_COUNT][4] =
{
{0,1,2,3},{0,1,4,5}
};
#define COLORS_SIZE 6
uint32_t block_colors[COLORS_SIZE] = { TFT_NAVY, TFT_DARKGREEN, TFT_RED, TFT_YELLOW, TFT_GREEN, TFT_PINK };
// Graphics-related functions
void void
init_board() init_board()
{ {
@ -51,6 +62,17 @@ init_board()
} }
} }
void
set_board(int i, int j, int color, bool old)
{
int v = color<<1;
if (old)
{
v = v|1;
}
main_board[i][j] = v;
}
void void
draw_board() draw_board()
{ {
@ -59,43 +81,108 @@ draw_board()
{ {
if (main_board[i][j] == offboard[i][j]) continue; // no need to redraw if (main_board[i][j] == offboard[i][j]) continue; // no need to redraw
offboard[i][j] = main_board[i][j]; offboard[i][j] = main_board[i][j];
int color = main_board[i][j]>>1;
tft.fillRect(i*BLOCK_SIZE+BLOCK_MARGIN,j*BLOCK_SIZE+BLOCK_MARGIN, tft.fillRect(i*BLOCK_SIZE+BLOCK_MARGIN,j*BLOCK_SIZE+BLOCK_MARGIN,
BLOCK_SIZE-BLOCK_MARGIN,BLOCK_SIZE-BLOCK_MARGIN, BLOCK_SIZE-BLOCK_MARGIN,BLOCK_SIZE-BLOCK_MARGIN,
main_board[i][j]); color);
} }
} }
uint8_t blocks[2][4] =
{
{0,1,2,3},{0,1,4,5}
};
// Draw a block of type TYPE with color COLOR, starting at coordinates X, Y. // Draw a block of type TYPE with color COLOR, starting at coordinates X, Y.
// Updates the main_board directly // Updates the main_board directly
void void
draw_block(int x, int y, int type, int color) draw_block(int x, int y, int type, int color, bool old)
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
int v = blocks[type][i]; int v = blocks[type][i];
int dx = v%4; int dx = v%4;
int dy = v/4; int dy = v/4;
main_board[x+dx][y+dy] = color; set_board(x+dx, y+dy, color, old);
} }
} }
// Game logic
// Current and previous positions of the active block
int px = 0, cx = 0; int px = 0, cx = 0;
int py = 0, cy = 0; int py = 0, cy = 0;
// Type of the active block. Should be 0 <= cblokc_ty < BLOCKS_COUNT
int cblock_ty = 0; int cblock_ty = 0;
void loop() { // Color of the current block
// if (dy == 0) { int cblock_color = TFT_RED;
// dx = map(esp_random(), 0, 0xFFFFFFFF, 0, 128/5);
// } void
cy++; new_block()
if (cy >= GRID_HEIGHT) { {
cy = 0; px = 0; cx = 0;
py = 0; cy = 0;
cblock_ty = 0;
cblock_color = TFT_RED;
}
bool
check_collision()
{
for (int i = 0; i < 4; i++)
{
int v = blocks[cblock_ty][i];
int dx = v%4;
int dy = v/4;
if (cy+dy >= GRID_HEIGHT)
{
return true;
} }
int is_old = main_board[cx+dx][cy+dy]&1;
if (is_old)
{
return true;
}
}
return false;
}
// Setup
void setup() {
tft.init(); // initialize a ST7735S chip
Serial.begin(115200);
// set up the buttons and the interrupts
pinMode(BTN1_PIN, INPUT_PULLUP);
attachInterrupt(BTN1_PIN, isr1, FALLING);
pinMode(BTN2_PIN, INPUT_PULLUP);
attachInterrupt(BTN2_PIN, isr2, FALLING);
init_board();
new_block();
delay(100);
}
void loop() {
if (check_collision ())
{
// designate the block as "old" and leave it there
draw_block(px, py, cblock_ty, cblock_color, true);
new_block();
return;
}
// clear the previous block
if (cy != py || cx != px)
{
draw_block(px, py, cblock_ty, TFT_BLACK, false);
}
draw_block(cx, cy, cblock_ty, cblock_color, false);
draw_board();
px = cx;
py = cy;
if (btn1_pressed) if (btn1_pressed)
{ {
@ -108,19 +195,9 @@ void loop() {
cx++; cx++;
} }
// clear the previous block cy++;
if (cy != py || cx != px)
{
draw_block(px, py, cblock_ty, TFT_BLACK);
}
draw_block(cx, cy, cblock_ty, TFT_RED);
draw_board();
delay(350); delay(350);
px = cx;
py = cy;
} }
void IRAM_ATTR void IRAM_ATTR