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