restructure code and add simple collision detection
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -10,6 +10,10 @@ CTAGS_CMD = $(CTAGS_PATH) -auef
 | 
			
		||||
TAGS_FILE = TAGS
 | 
			
		||||
 | 
			
		||||
all:
 | 
			
		||||
	$(ARDUINO) --verify tetris.ino
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
upload:
 | 
			
		||||
	$(ARDUINO) --upload tetris.ino
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										179
									
								
								tetris.ino
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								tetris.ino
									
									
									
									
									
								
							@@ -2,42 +2,53 @@
 | 
			
		||||
#include <TFT_eSPI.h>
 | 
			
		||||
#include <SPI.h>
 | 
			
		||||
 | 
			
		||||
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
 | 
			
		||||
// pins are defined un User_Setup.h
 | 
			
		||||
// We assume the size of the screen 120x160
 | 
			
		||||
#define GRID_WIDTH   12
 | 
			
		||||
#define GRID_HEIGHT  16
 | 
			
		||||
#define BLOCK_SIZE   10
 | 
			
		||||
#define BLOCK_MARGIN  2
 | 
			
		||||
 | 
			
		||||
const int BTN1_PIN = 25;
 | 
			
		||||
volatile bool btn1_pressed = false;
 | 
			
		||||
const int BTN2_PIN = 33;
 | 
			
		||||
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
 | 
			
		||||
void IRAM_ATTR isr1();
 | 
			
		||||
void IRAM_ATTR isr2();
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
// the main board and the offboard, to check for dirty squares
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
draw_board()
 | 
			
		||||
{
 | 
			
		||||
@@ -59,43 +81,108 @@ draw_board()
 | 
			
		||||
      {
 | 
			
		||||
        if (main_board[i][j] == offboard[i][j]) continue; // no need to redraw
 | 
			
		||||
        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,
 | 
			
		||||
                     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.
 | 
			
		||||
// Updates the main_board directly
 | 
			
		||||
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++)
 | 
			
		||||
    {
 | 
			
		||||
      int v = blocks[type][i];
 | 
			
		||||
      int dx = 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 py = 0, cy = 0;
 | 
			
		||||
// Type of the active block. Should be 0 <= cblokc_ty < BLOCKS_COUNT
 | 
			
		||||
int cblock_ty = 0;
 | 
			
		||||
// Color of the current block
 | 
			
		||||
int cblock_color = TFT_RED;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
new_block()
 | 
			
		||||
{
 | 
			
		||||
  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 (dy == 0) {
 | 
			
		||||
  //   dx = map(esp_random(), 0, 0xFFFFFFFF, 0, 128/5);
 | 
			
		||||
  // }
 | 
			
		||||
  cy++;
 | 
			
		||||
  if (cy >= GRID_HEIGHT) {
 | 
			
		||||
    cy = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
    {
 | 
			
		||||
@@ -108,19 +195,9 @@ void loop() {
 | 
			
		||||
      cx++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // clear the previous block
 | 
			
		||||
  if (cy != py || cx != px)
 | 
			
		||||
    {
 | 
			
		||||
      draw_block(px, py, cblock_ty, TFT_BLACK);
 | 
			
		||||
    }
 | 
			
		||||
  draw_block(cx, cy, cblock_ty, TFT_RED);
 | 
			
		||||
 | 
			
		||||
  draw_board();
 | 
			
		||||
  cy++;
 | 
			
		||||
 | 
			
		||||
  delay(350);
 | 
			
		||||
 | 
			
		||||
  px = cx;
 | 
			
		||||
  py = cy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IRAM_ATTR
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user