Check surroundings before rotation
This commit is contained in:
parent
9daf4b373d
commit
e6bf3def99
136
tetris.cpp
136
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<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;
|
||||
|
Loading…
Reference in New Issue
Block a user