Files
wordclock/include/tetris.h

199 lines
4.7 KiB
C++

/**
* @file tetris.h
* @author techniccontroller (mail[at]techniccontroller.com)
* @brief Class definition for tetris game
* @version 0.1
* @date 2022-03-05
*
* @copyright Copyright (c) 2022
*
* main tetris code originally written by Klaas De Craemer, Ing. David Hrbaty
*
*/
#ifndef TETRIS_H
#define TETRIS_H
#include <Arduino.h>
#include "led_matrix.h"
#include "udp_logger.h"
#ifdef DEBOUNCE_TIME
#undef DEBOUNCE_TIME
#endif
#define DEBOUNCE_TIME 100
#define RED_END_TIME 1500
#define GAME_STATE_RUNNING 1
#define GAME_STATE_END 2
#define GAME_STATE_INIT 3
#define GAME_STATE_PAUSED 4
#define GAME_STATE_READY 5
// common
#define DIR_UP 1
#define DIR_DOWN 2
#define DIR_LEFT 3
#define DIR_RIGHT 4
// Maximum size of bricks. Individual bricks can still be smaller (eg 3x3)
#define GREEN 0x008000
#define RED 0xFF0000
#define BLUE 0x0000FF
#define YELLOW 0xFFFF00
#define CHOCOLATE 0xD2691E
#define PURPLE 0xFF00FF
#define WHITE 0XFFFFFF
#define AQUA 0x00FFFF
#define HOTPINK 0xFF1493
#define DARKORANGE 0xFF8C00
#define MAX_BRICK_SIZE 4
#define BRICKOFFSET -1 // Y offset for new bricks
#define INIT_SPEED 800 // Initial delay in ms between brick drops
#define SPEED_STEP 10 // Factor for speed increase between levels, default 10
#define LEVELUP 4 // Number of rows before levelup, default 5
#define WIDTH 11
#define HEIGHT 11
class Tetris
{
// Playing field
struct Field
{
uint8_t pix[MATRIX_WIDTH][MATRIX_HEIGHT + 1]; // Make field one larger so that collision detection with bottom of field can be done in a uniform way
uint32_t color[MATRIX_WIDTH][MATRIX_HEIGHT];
};
// Structure to represent active brick on screen
struct Brick
{
boolean enabled; // Brick is disabled when it has landed
int xpos, ypos;
int yOffset; // Y-offset to use when placing brick at top of field
uint8_t siz;
uint8_t pix[MAX_BRICK_SIZE][MAX_BRICK_SIZE];
uint32_t col;
};
// Struct to contain the different choices of blocks
struct AbstractBrick
{
int yOffset; // Y-offset to use when placing brick at top of field
uint8_t siz;
uint8_t pix[MAX_BRICK_SIZE][MAX_BRICK_SIZE];
uint32_t col;
};
public:
Tetris();
Tetris(LEDMatrix *myledmatrix, UDPLogger *mylogger);
void ctrlStart();
void ctrlPlayPause();
void ctrlRight();
void ctrlLeft();
void ctrlUp();
void ctrlDown();
void setSpeed(int32_t i);
void loopCycle();
private:
void resetLEDs();
void tetrisInit();
void printField();
/* *** Game functions *** */
void newActiveBrick();
boolean checkFieldCollision(struct Brick *brick);
boolean checkSidesCollision(struct Brick *brick);
void rotateActiveBrick();
void shiftActiveBrick(int dir);
void addActiveBrickToField();
void moveFieldDownOne(uint8_t startRow);
void checkFullLines();
void clearField();
void everythingRed();
void showscore();
LEDMatrix *_ledmatrix;
UDPLogger *_logger;
Brick _activeBrick = {0};
Field _field;
bool _allowdrop = false;
bool _tetrisGameOver = false;
int _gameState = GAME_STATE_INIT;
int _score = 0;
unsigned int _speedtetris = 80;
unsigned long _brickSpeed = 0;
unsigned long _droptime = 0;
unsigned long _lastButtonClick = 0;
unsigned long _lastButtonClickr = 0;
unsigned long _nbRowsThisLevel = 0;
unsigned long _nbRowsTotal = 0;
unsigned long _prevUpdateTime = 0;
unsigned long _tetrisshowscore = 0;
// color library
uint32_t _colorLib[10] = {RED, GREEN, BLUE, YELLOW, CHOCOLATE, PURPLE, WHITE, AQUA, HOTPINK, DARKORANGE};
// Brick "library"
AbstractBrick _brickLib[7] = {
{1, // yoffset when adding brick to field
4,
{{0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}},
WHITE},
{0,
4,
{{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}},
GREEN},
{1,
3,
{{0, 0, 0, 0},
{1, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}},
BLUE},
{1,
3,
{{0, 0, 1, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}},
YELLOW},
{1,
3,
{{0, 0, 0, 0},
{1, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}},
AQUA},
{1,
3,
{{0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}},
HOTPINK},
{1,
3,
{{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}},
RED}};
};
#endif /* TETRIS_H */