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() {
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<TetrisPiece> piece, SDLPP::Scene &scene ) {
int right = 0x02;
int bottom = 0x04;
int flags = 0;
// game board limits
while ( crash ) {
crash = false;
flags = 0;
@ -482,18 +512,49 @@ void checkRotation( std::shared_ptr<TetrisPiece> piece, SDLPP::Scene &scene ) {
if ( flags == bottom ) {
piece->revert();
} 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 pos = block->getPos();
switch ( flags ) {
case 1:
block->setPos( pos.first + BLOCK_SIZE, pos.second );
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;
case 2:
block->setPos( pos.first - BLOCK_SIZE, pos.second );
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;
}
}
}
@ -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;