mirror of
https://github.com/wled/WLED.git
synced 2025-04-27 08:17:17 +00:00
128 lines
3.2 KiB
C++
128 lines
3.2 KiB
C++
/******************************************************************************
|
|
* @file : gridbw.h
|
|
* @brief : contains the tetris grid as binary so black and white version
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* Copyright (c) muebau 2023
|
|
* All rights reserved.</center></h2>
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef __GRIDBW_H__
|
|
#define __GRIDBW_H__
|
|
|
|
#include <iterator>
|
|
#include <vector>
|
|
#include "pieces.h"
|
|
|
|
using namespace std;
|
|
|
|
class GridBW
|
|
{
|
|
private:
|
|
public:
|
|
uint8_t width;
|
|
uint8_t height;
|
|
std::vector<uint32_t> pixels;
|
|
|
|
GridBW(uint8_t width, uint8_t height):
|
|
width(width),
|
|
height(height),
|
|
pixels(height)
|
|
{
|
|
if (width > 32)
|
|
{
|
|
this->width = 32;
|
|
}
|
|
}
|
|
|
|
void placePiece(Piece* piece, uint8_t x, uint8_t y)
|
|
{
|
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
|
{
|
|
pixels[y + (row - (4 - piece->getRotation().height))] |= piece->getGridRow(x, row, width);
|
|
}
|
|
}
|
|
|
|
void erasePiece(Piece* piece, uint8_t x, uint8_t y)
|
|
{
|
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
|
{
|
|
pixels[y + (row - (4 - piece->getRotation().height))] &= ~piece->getGridRow(x, row, width);
|
|
}
|
|
}
|
|
|
|
bool noCollision(Piece* piece, uint8_t x, uint8_t y)
|
|
{
|
|
//if it touches a wall it is a collision
|
|
if (x > (this->width - piece->getRotation().width) || y > this->height - piece->getRotation().height)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (uint8_t row = 4 - piece->getRotation().height; row < 4; row++)
|
|
{
|
|
if (piece->getGridRow(x, row, width) & pixels[y + (row - (4 - piece->getRotation().height))])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void findLandingPosition(Piece* piece)
|
|
{
|
|
// move down until the piece bumps into some occupied pixels or the 'wall'
|
|
while (noCollision(piece, piece->x, piece->landingY))
|
|
{
|
|
piece->landingY++;
|
|
}
|
|
|
|
//at this point the positon is 'in the wall' or 'over some occupied pixel'
|
|
//so the previous position was the last correct one (clamped to 0 as minimum).
|
|
piece->landingY = piece->landingY > 0 ? piece->landingY - 1 : 0;
|
|
}
|
|
|
|
void cleanupFullLines()
|
|
{
|
|
uint8_t offset = 0;
|
|
|
|
//from "height - 1" to "0", so from bottom row to top
|
|
for (uint8_t row = height; row-- > 0; )
|
|
{
|
|
//full line?
|
|
if (isLineFull(row))
|
|
{
|
|
offset++;
|
|
pixels[row] = 0x0;
|
|
continue;
|
|
}
|
|
|
|
if (offset > 0)
|
|
{
|
|
pixels[row + offset] = pixels[row];
|
|
pixels[row] = 0x0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isLineFull(uint8_t y)
|
|
{
|
|
return pixels[y] == (uint32_t)((1 << width) - 1);
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
if (width > 32)
|
|
{
|
|
width = 32;
|
|
}
|
|
|
|
pixels.clear();
|
|
pixels.resize(height);
|
|
}
|
|
};
|
|
|
|
#endif /* __GRIDBW_H__ */ |