From e6bf3def99e54630af7a494eec503dee6a1dcba1 Mon Sep 17 00:00:00 2001 From: zvon Date: Mon, 24 Aug 2020 16:36:24 +0200 Subject: [PATCH] Check surroundings before rotation --- tetris.cpp | 142 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 52 deletions(-) diff --git a/tetris.cpp b/tetris.cpp index 255b0a3..0c6f459 100644 --- a/tetris.cpp +++ b/tetris.cpp @@ -58,6 +58,15 @@ public: ~TetrisBlock() { bag[_index]++; } + bool isSamePos(const SDLPP::RenderObject &other) const { + auto mypos = getPos(); + auto otherpos = other.getPos(); + auto diff1 = mypos.first - otherpos.first; + diff1 = (diff1 < 0) * (-1) * diff1 + (diff1 > 0) * diff1; + auto diff2 = mypos.second - otherpos.second; + diff2 = (diff2 < 0) * (-1) * diff2 + (diff2 > 0) * diff2; + return diff1 < 0.0001 && diff2 < 0.0001; + } private: int _index = 0; @@ -68,7 +77,7 @@ public: TetrisPiece() { original_pos.reserve( 4 ); } - void addPiece( std::shared_ptr< SDLPP::RectangleRender > piece, int x, + void addPiece( std::shared_ptr< TetrisBlock > piece, int x, int y ) { pieces.push_back( piece ); pieces_rel_position.push_back( { 0, 0, 0, 0 } ); @@ -110,7 +119,7 @@ public: pieces[i]->setPos( original_pos[i].first, original_pos[i].second ); } } - std::vector< std::shared_ptr< SDLPP::RectangleRender > > &getObjects() { + std::vector< std::shared_ptr< TetrisBlock > > &getObjects() { return pieces; } void setPos( double x, double y ) { @@ -139,10 +148,30 @@ public: bool isDescending() { return descend; } + bool isLeft(const SDLPP::RenderObject &block) const { + return isPosition(block, 0); + } + bool isRight(const SDLPP::RenderObject &block) const { + return isPosition(block, 1); + } + void movePiece(double x, double y) { + for ( auto &block : getObjects() ) { + auto pos = block->getPos(); + block->setPos( pos.first + x, pos.second + y ); + } + } private: + bool isPosition(const SDLPP::RenderObject &block, int pos) const { + for(int i = 0; i < 4; i++) { + if(pieces[i]->isSamePos(block)) { + return pieces_rel_position[i][pos] != 0; + } + } + return false; + } std::vector< std::vector< int > > pieces_rel_position; - std::vector< std::shared_ptr< SDLPP::RectangleRender > > pieces; + std::vector< std::shared_ptr< TetrisBlock > > pieces; std::vector< std::pair< double, double > > original_pos; double default_x; double default_y; @@ -159,7 +188,7 @@ bool quit = false; std::mutex movement_mutex; -std::shared_ptr< SDLPP::RectangleRender > +std::shared_ptr< TetrisBlock > createTetrisBlock( double x, double y, const std::string &color, const std::string &outline, int index, std::shared_ptr< SDLPP::Renderer > renderer, @@ -459,6 +488,7 @@ void checkRotation( std::shared_ptr piece, SDLPP::Scene &scene ) { int right = 0x02; int bottom = 0x04; int flags = 0; + // game board limits while ( crash ) { crash = false; flags = 0; @@ -482,20 +512,51 @@ void checkRotation( std::shared_ptr piece, SDLPP::Scene &scene ) { if ( flags == bottom ) { piece->revert(); } else { - for ( auto &block : piece->getObjects() ) { - auto pos = block->getPos(); - switch ( flags ) { - case 1: - block->setPos( pos.first + BLOCK_SIZE, pos.second ); - break; - case 2: - block->setPos( pos.first - BLOCK_SIZE, pos.second ); - break; - } - } + 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) { + crash = true; + is_left |= piece->isLeft(*col); + is_right |= piece->isRight(*col); + } + } + if(!crash) + break; + if((is_left && is_right) || (is_left && was_right) || (is_right && was_left)) { + piece->revert(); + break; + } + was_left = is_left; + was_right = is_right; + if(is_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(); + break; + } + } } void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { @@ -512,49 +573,32 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { case SDLK_a: if(!cur_object) break; - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - // 0.01 because doubles - if ( pos.first < ( LEFT_BORDER + 0.01 ) ) - crash = true; - x->setPos( pos.first - BLOCK_SIZE, pos.second ); - } + cur_object->movePiece(-BLOCK_SIZE, 0); + for ( auto &x : cur_object->getObjects() ) { auto collisions = scene.getCollisions( *x, { BRICK_ID } ); - if ( collisions.size() > 1 ) + auto pos = x->getPos(); + if ( collisions.size() > 1 || pos.first < ( LEFT_BORDER - 0.01 ) ) crash = true; } - if ( crash ) { - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - x->setPos( pos.first + BLOCK_SIZE, pos.second ); - } - } + if ( crash ) + cur_object->movePiece(BLOCK_SIZE, 0); break; case SDLK_RIGHT: case SDLK_d: if(!cur_object) break; - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - // 0.01 because doubles - if ( pos.first > RIGHT_BORDER - BLOCK_SIZE - 0.01 ) { - crash = true; - } - x->setPos( pos.first + BLOCK_SIZE, pos.second ); - } + cur_object->movePiece(BLOCK_SIZE, 0); + for ( auto &x : cur_object->getObjects() ) { auto collisions = scene.getCollisions( *x, { BRICK_ID } ); - if ( collisions.size() > 1 ) { + auto pos = x->getPos(); + if ( collisions.size() > 1 || pos.first > RIGHT_BORDER - BLOCK_SIZE + 0.01 ) { crash = true; } } - if ( crash ) { - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - x->setPos( pos.first - BLOCK_SIZE, pos.second ); - } - } + if ( crash ) + cur_object->movePiece(-BLOCK_SIZE, 0); break; case SDLK_DOWN: case SDLK_s: @@ -688,10 +732,7 @@ void moveThem( std::shared_ptr< SDLPP::Scene > scene, int ticks ) { } ticks_till_fall = TICKS_TILL_FALL; fall: - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - x->setPos( pos.first, pos.second + BLOCK_SIZE ); - } + cur_object->movePiece(0, BLOCK_SIZE); bool fell = false; for ( auto &x : cur_object->getObjects() ) { auto collisions = scene->getCollisions( *x, { BRICK_ID } ); @@ -705,10 +746,7 @@ fall: } } if ( fell ) { - for ( auto &x : cur_object->getObjects() ) { - auto pos = x->getPos(); - x->setPos( pos.first, pos.second - BLOCK_SIZE ); - } + cur_object->movePiece(0, -BLOCK_SIZE); for ( auto &block : cur_object->getObjects() ) { if ( scene->getCollisions( *block, { GAME_OVER } ).size() > 0 ) { std::cout << "You lost" << std::endl;