Check surroundings before rotation

This commit is contained in:
zvon 2020-08-24 16:36:24 +02:00
parent 9daf4b373d
commit e6bf3def99

View File

@ -58,6 +58,15 @@ public:
~TetrisBlock() { ~TetrisBlock() {
bag[_index]++; 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: private:
int _index = 0; int _index = 0;
@ -68,7 +77,7 @@ public:
TetrisPiece() { TetrisPiece() {
original_pos.reserve( 4 ); 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 ) { int y ) {
pieces.push_back( piece ); pieces.push_back( piece );
pieces_rel_position.push_back( { 0, 0, 0, 0 } ); 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 ); 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; return pieces;
} }
void setPos( double x, double y ) { void setPos( double x, double y ) {
@ -139,10 +148,30 @@ public:
bool isDescending() { bool isDescending() {
return descend; 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: 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::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; std::vector< std::pair< double, double > > original_pos;
double default_x; double default_x;
double default_y; double default_y;
@ -159,7 +188,7 @@ bool quit = false;
std::mutex movement_mutex; std::mutex movement_mutex;
std::shared_ptr< SDLPP::RectangleRender > std::shared_ptr< TetrisBlock >
createTetrisBlock( double x, double y, const std::string &color, createTetrisBlock( double x, double y, const std::string &color,
const std::string &outline, int index, const std::string &outline, int index,
std::shared_ptr< SDLPP::Renderer > renderer, std::shared_ptr< SDLPP::Renderer > renderer,
@ -459,6 +488,7 @@ void checkRotation( std::shared_ptr<TetrisPiece> piece, SDLPP::Scene &scene ) {
int right = 0x02; int right = 0x02;
int bottom = 0x04; int bottom = 0x04;
int flags = 0; int flags = 0;
// game board limits
while ( crash ) { while ( crash ) {
crash = false; crash = false;
flags = 0; flags = 0;
@ -482,18 +512,49 @@ void checkRotation( std::shared_ptr<TetrisPiece> piece, SDLPP::Scene &scene ) {
if ( flags == bottom ) { if ( flags == bottom ) {
piece->revert(); piece->revert();
} else { } 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()) { for(auto &block : piece->getObjects()) {
auto pos = block->getPos(); auto collisions = scene.getCollisions(*block, {BRICK_ID});
switch ( flags ) { if(collisions.size() == 1)
case 1: continue;
block->setPos( pos.first + BLOCK_SIZE, pos.second ); for(auto &col : collisions) {
crash = true;
is_left |= piece->isLeft(*col);
is_right |= piece->isRight(*col);
}
}
if(!crash)
break; break;
case 2: if((is_left && is_right) || (is_left && was_right) || (is_right && was_left)) {
block->setPos( pos.first - BLOCK_SIZE, pos.second ); piece->revert();
break; 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;
} }
} }
} }
@ -512,49 +573,32 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) {
case SDLK_a: case SDLK_a:
if(!cur_object) if(!cur_object)
break; break;
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(-BLOCK_SIZE, 0);
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 );
}
for ( auto &x : cur_object->getObjects() ) { for ( auto &x : cur_object->getObjects() ) {
auto collisions = scene.getCollisions( *x, { BRICK_ID } ); 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; crash = true;
} }
if ( crash ) { if ( crash )
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(BLOCK_SIZE, 0);
auto pos = x->getPos();
x->setPos( pos.first + BLOCK_SIZE, pos.second );
}
}
break; break;
case SDLK_RIGHT: case SDLK_RIGHT:
case SDLK_d: case SDLK_d:
if(!cur_object) if(!cur_object)
break; break;
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(BLOCK_SIZE, 0);
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 );
}
for ( auto &x : cur_object->getObjects() ) { for ( auto &x : cur_object->getObjects() ) {
auto collisions = scene.getCollisions( *x, { BRICK_ID } ); 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; crash = true;
} }
} }
if ( crash ) { if ( crash )
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(-BLOCK_SIZE, 0);
auto pos = x->getPos();
x->setPos( pos.first - BLOCK_SIZE, pos.second );
}
}
break; break;
case SDLK_DOWN: case SDLK_DOWN:
case SDLK_s: case SDLK_s:
@ -688,10 +732,7 @@ void moveThem( std::shared_ptr< SDLPP::Scene > scene, int ticks ) {
} }
ticks_till_fall = TICKS_TILL_FALL; ticks_till_fall = TICKS_TILL_FALL;
fall: fall:
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(0, BLOCK_SIZE);
auto pos = x->getPos();
x->setPos( pos.first, pos.second + BLOCK_SIZE );
}
bool fell = false; bool fell = false;
for ( auto &x : cur_object->getObjects() ) { for ( auto &x : cur_object->getObjects() ) {
auto collisions = scene->getCollisions( *x, { BRICK_ID } ); auto collisions = scene->getCollisions( *x, { BRICK_ID } );
@ -705,10 +746,7 @@ fall:
} }
} }
if ( fell ) { if ( fell ) {
for ( auto &x : cur_object->getObjects() ) { cur_object->movePiece(0, -BLOCK_SIZE);
auto pos = x->getPos();
x->setPos( pos.first, pos.second - BLOCK_SIZE );
}
for ( auto &block : cur_object->getObjects() ) { for ( auto &block : cur_object->getObjects() ) {
if ( scene->getCollisions( *block, { GAME_OVER } ).size() > 0 ) { if ( scene->getCollisions( *block, { GAME_OVER } ).size() > 0 ) {
std::cout << "You lost" << std::endl; std::cout << "You lost" << std::endl;