TETRIS: fix rotation

This commit is contained in:
zvon 2020-09-11 12:28:42 +02:00
parent a10f3cf47e
commit c7f5e834bb

View File

@ -8,8 +8,9 @@
#define BRICK_ID 0x00000002
#define GAME_OVER 0x00000003
#define SHADOW_ID 0x00000004
#define BORDER_ID 0x00000005
#define FLOOR_ID 0x00000006
#define BORDER_LEFT_ID 0x00000005
#define BORDER_RIGHT_ID 0x00000006
#define FLOOR_ID 0x00000007
#define LEFT_BORDER 0.3
#define RIGHT_BORDER 0.7
@ -553,7 +554,7 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) {
scene.addObject( shadow_colider );
auto border = std::make_shared< SDLPP::RectangleRender >( LEFT_BORDER - 1, TOP_BORDER, 1, BOTTOM_BORDER, r);
border->setId( BORDER_ID );
border->setId( BORDER_LEFT_ID );
border->setStatic();
border->centerX();
border->addCollision(SDLPP::Rect( 0, 0, 0.99, 1));
@ -561,7 +562,7 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) {
scene.addObject(border);
border = std::make_shared< SDLPP::RectangleRender >( RIGHT_BORDER, TOP_BORDER, 1, BOTTOM_BORDER, r);
border->setId( BORDER_ID );
border->setId( BORDER_RIGHT_ID );
border->setStatic();
border->centerX();
border->addCollision(SDLPP::Rect( 0.01, 0, 1, 1));
@ -645,86 +646,67 @@ void quitGame() {
quit = true;
}
int crashFlags( std::shared_ptr<TetrisPiece> piece, std::shared_ptr<TetrisBlock> block, SDLPP::Scene &scene, int left, int right, int bottom) {
int retFlags = 0;
auto collisions = scene.getCollisions(*block, {BORDER_LEFT_ID, BORDER_RIGHT_ID, FLOOR_ID});
for(auto &col : collisions) {
switch(col->getId()) {
case BORDER_LEFT_ID:
retFlags |= left;
break;
case BORDER_RIGHT_ID:
retFlags |= right;
break;
case FLOOR_ID:
retFlags |= right;
default:
break;
}
}
collisions = scene.getCollisions(*block, {BRICK_ID});
if(collisions.size() > 1) {
for(auto &col : collisions) {
if(piece->isLeft(*col))
retFlags |= left;
else if(piece->isRight(*col))
retFlags |= right;
else
retFlags |= bottom;
}
}
return retFlags;
}
bool checkRotation( std::shared_ptr<TetrisPiece> piece, SDLPP::Scene &scene ) {
bool ret = true;
bool crash = true;
int left = 0x01;
int right = 0x02;
int bottom = 0x04;
int flags = 0;
// game board limits
while ( crash ) {
crash = false;
flags = 0;
for ( auto &block : piece->getObjects() ) {
auto pos = block->getPos();
if ( pos.first < LEFT_BORDER - 0.01 ) {
flags |= left;
crash = true;
break;
} else if ( pos.first > RIGHT_BORDER - BLOCK_SIZE + 0.01 ) {
crash = true;
flags |= right;
break;
} else if ( pos.second >= BOTTOM_BORDER ) {
crash = true;
flags |= bottom;
break;
}
}
if ( crash ) {
if ( flags & bottom || (flags & left && flags & right) ) {
piece->revert();
ret = false;
} else {
if( flags & left )
piece->movePiece(BLOCK_SIZE, 0);
else if( flags & right )
piece->movePiece(-BLOCK_SIZE, 0);
}
}
}
// blocks
crash = true;
bool was_left = false;
bool was_right = false;
bool is_left = false;
bool is_right = false;
while ( crash ) {
is_left = false;
is_right = false;
crash = false;
int crash = 0;
int cur_left = 0x01;
int cur_right = 0x02;
int was_left = 0x04;
int was_right = 0x08;
int bottom = 0x10;
do {
crash = 0;
for(auto &block : piece->getObjects()) {
auto collisions = scene.getCollisions(*block, {BRICK_ID});
if(collisions.size() == 1)
continue;
for(auto &col : collisions) {
crash = true;
is_left |= piece->isLeft(*col);
is_right |= piece->isRight(*col);
}
crash |= crashFlags(piece, block, scene, cur_left, cur_right, bottom);
}
if(!crash)
break;
if((is_left && is_right) || (is_left && was_right) || (is_right && was_left)) {
if(crash & bottom || (crash & cur_left && crash & cur_right) ||
(crash & cur_left && crash & was_right) || (crash & cur_right && crash & was_left)) {
piece->revert();
ret = false;
break;
return false;
}
was_left = is_left;
was_right = is_right;
if(is_left)
crash &= ~(was_left | was_right);
if(crash & cur_left) {
piece->movePiece(BLOCK_SIZE, 0);
if(is_right)
piece->movePiece(-BLOCK_SIZE, 0);
// either bottom or up
if(!is_left && !is_right) {
piece->revert();
ret = false;
break;
crash &= ~cur_left;
crash |= was_left;
}
}
return ret;
if(crash & cur_right) {
piece->movePiece(-BLOCK_SIZE, 0);
crash &= ~cur_right;
crash |= was_right;
}
} while(crash);
return true;
}
void updateShadow(SDLPP::Scene &scene) {
@ -758,9 +740,7 @@ void updateShadow(SDLPP::Scene &scene) {
bool validPos(SDLPP::Scene &scene, std::shared_ptr<TetrisPiece> piece) {
auto ret = true;
for ( auto &x : piece->getObjects() ) {
if(x->getId() != 2)
std::cout << "ID: " << x->getId() << std::endl;
auto collisions = scene.getCollisions( *x, { BRICK_ID, FLOOR_ID, BORDER_ID } );
auto collisions = scene.getCollisions( *x, { BRICK_ID, FLOOR_ID, BORDER_LEFT_ID, BORDER_RIGHT_ID } );
if ( collisions.size() > 1 ) {
ret = false;
break;