restructure code and add simple collision detection
This commit is contained in:
parent
afeabd81e7
commit
bd05d23800
4
Makefile
4
Makefile
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
179
tetris.ino
179
tetris.ino
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue