From 5f275081fec1b656d2df00f37fe7e5bea223a9f4 Mon Sep 17 00:00:00 2001 From: zvon Date: Sun, 23 Aug 2020 11:37:07 +0200 Subject: [PATCH] Define block size and player area, check if rotation is valid --- tetris.cpp | 306 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 193 insertions(+), 113 deletions(-) diff --git a/tetris.cpp b/tetris.cpp index 038c158..991f0bc 100644 --- a/tetris.cpp +++ b/tetris.cpp @@ -8,6 +8,12 @@ #define BRICK_ID 0x00000002 #define GAME_OVER 0x00000003 +#define LEFT_BORDER 0.3 +#define RIGHT_BORDER 0.7 +#define BOTTOM_BORDER 1 +#define TOP_BORDER 0.16 +#define BLOCK_SIZE 0.04 + bool pause = false; int pause_select = 0; int pause_max = 1; @@ -26,6 +32,9 @@ std::shared_ptr< SDLPP::Scene > pause_scene; class TetrisPiece { public: + TetrisPiece() { + original_pos.reserve( 4 ); + } void addPiece( std::shared_ptr< SDLPP::RectangleRender > piece, int x, int y ) { pieces.push_back( piece ); @@ -45,23 +54,29 @@ public: auto &piece = pieces[i]; auto &positions = pieces_rel_position[i]; auto position = piece->getPos(); - position.first += positions[0] * 0.04; - position.first -= positions[1] * 0.04; - position.second += positions[2] * 0.04; - position.second -= positions[3] * 0.04; + original_pos[i] = position; + position.first += positions[0] * BLOCK_SIZE; + position.first -= positions[1] * BLOCK_SIZE; + position.second += positions[2] * BLOCK_SIZE; + position.second -= positions[3] * BLOCK_SIZE; auto bottom = positions[3]; auto top = positions[2]; positions[3] = positions[1]; positions[2] = positions[0]; positions[1] = top; positions[0] = bottom; - position.first -= positions[0] * 0.04; - position.first += positions[1] * 0.04; - position.second -= positions[2] * 0.04; - position.second += positions[3] * 0.04; + position.first -= positions[0] * BLOCK_SIZE; + position.first += positions[1] * BLOCK_SIZE; + position.second -= positions[2] * BLOCK_SIZE; + position.second += positions[3] * BLOCK_SIZE; piece->setPos( position.first, position.second ); } } + void revert() { + for ( unsigned long i = 0; i < pieces.size(); i++ ) { + pieces[i]->setPos( original_pos[i].first, original_pos[i].second ); + } + } std::vector< std::shared_ptr< SDLPP::RectangleRender > > &getObjects() { return pieces; } @@ -95,6 +110,7 @@ public: private: std::vector< std::vector< int > > pieces_rel_position; std::vector< std::shared_ptr< SDLPP::RectangleRender > > pieces; + std::vector< std::pair< double, double > > original_pos; double default_x; double default_y; bool descend = false; @@ -116,7 +132,7 @@ createTetrisBlock( double x, double y, const std::string &color, std::shared_ptr< SDLPP::Renderer > renderer, std::shared_ptr< SDLPP::Scene > scene ) { auto ret = std::make_shared< SDLPP::RectangleRender >( - x, y, 0.04, 0.04, renderer, color, true ); + x, y, BLOCK_SIZE, BLOCK_SIZE, renderer, color, true ); ret->setOutlineColor( outline ); ret->addCollision( SDLPP::Rect( 0.1, 0.1, 0.8, 0.8 ) ); ret->setId( BRICK_ID ); @@ -130,17 +146,20 @@ TetrisPiece tetrisBrick( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#FF0000"; auto outline = "#AA0000"; + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 0, 0 ); retPiece.addPiece( - createTetrisBlock( 0.46, 0.16, color, outline, renderer, scene ), 0, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.16, color, outline, renderer, scene ), 0, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.46, 0.20, color, outline, renderer, scene ), 0, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), 0, 0 ); - retPiece.setDefPos( 0.5, 0.16 ); + createTetrisBlock( 0.5, TOP_BORDER, color, outline, renderer, scene ), + 0, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -149,18 +168,21 @@ TetrisPiece tetrisT( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#00FF00"; auto outline = "#00AA00"; + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + -1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); retPiece.addPiece( - createTetrisBlock( 0.46, 0.20, color, outline, renderer, scene ), -1, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), 0, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.16, color, outline, renderer, scene ), 0, - -1 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.20, color, outline, renderer, scene ), 1, - 0 ); - retPiece.setDefPos( 0.5, 0.16 ); + createTetrisBlock( 0.5, TOP_BORDER, color, outline, renderer, scene ), + 0, -1 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 1, 0 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -169,19 +191,21 @@ TetrisPiece tetrisLRight( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#0000FF"; auto outline = "#0000AA"; - retPiece.addPiece( - createTetrisBlock( 0.46, 0.20, color, outline, renderer, scene ), -2, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), -1, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.20, color, outline, renderer, scene ), 0, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.16, color, outline, renderer, scene ), 0, - -1 ); - retPiece.setDefPos( 0.5, 0.16 ); + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + -2, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + -1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 0, -1 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -190,18 +214,20 @@ TetrisPiece tetrisZRight( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#FF00FF"; auto outline = "#AA00AA"; + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + -1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); retPiece.addPiece( - createTetrisBlock( 0.46, 0.20, color, outline, renderer, scene ), -1, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), 0, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.16, color, outline, renderer, scene ), 0, - -1 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.16, color, outline, renderer, scene ), 1, - -1 ); - retPiece.setDefPos( 0.5, 0.16 ); + createTetrisBlock( 0.5, TOP_BORDER, color, outline, renderer, scene ), + 0, -1 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 1, -1 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -210,18 +236,19 @@ TetrisPiece tetrisLine( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#FFFF00"; auto outline = "#AAAA00"; + retPiece.addPiece( createTetrisBlock( 0.5 - 2 * BLOCK_SIZE, TOP_BORDER, + color, outline, renderer, scene ), + -1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 0, 0 ); retPiece.addPiece( - createTetrisBlock( 0.42, 0.16, color, outline, renderer, scene ), -1, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.46, 0.16, color, outline, renderer, scene ), 0, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.16, color, outline, renderer, scene ), 1, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.16, color, outline, renderer, scene ), 2, - 0 ); - retPiece.setDefPos( 0.5, 0.16 ); + createTetrisBlock( 0.5, TOP_BORDER, color, outline, renderer, scene ), + 1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 2, 0 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -230,18 +257,21 @@ TetrisPiece tetrisLLeft( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#00FFFF"; auto outline = "#00AAAA"; - retPiece.addPiece( - createTetrisBlock( 0.46, 0.16, color, outline, renderer, scene ), 0, - -1 ); - retPiece.addPiece( - createTetrisBlock( 0.46, 0.20, color, outline, renderer, scene ), 0, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), 1, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.20, color, outline, renderer, scene ), 2, - 0 ); - retPiece.setDefPos( 0.5, 0.16 ); + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + 0, -1 ); + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 1, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 2, 0 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -250,17 +280,20 @@ TetrisPiece tetrisZLeft( std::shared_ptr< SDLPP::Renderer > renderer, TetrisPiece retPiece{}; auto color = "#FFFFFF"; auto outline = "#AAAAAA"; + retPiece.addPiece( createTetrisBlock( 0.5 - BLOCK_SIZE, TOP_BORDER, color, + outline, renderer, scene ), + -1, 0 ); retPiece.addPiece( - createTetrisBlock( 0.46, 0.16, color, outline, renderer, scene ), -1, - 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.16, color, outline, renderer, scene ), 0, 0 ); - retPiece.addPiece( - createTetrisBlock( 0.5, 0.20, color, outline, renderer, scene ), 0, 1 ); - retPiece.addPiece( - createTetrisBlock( 0.54, 0.20, color, outline, renderer, scene ), 1, - 1 ); - retPiece.setDefPos( 0.5, 0.16 ); + createTetrisBlock( 0.5, TOP_BORDER, color, outline, renderer, scene ), + 0, 0 ); + retPiece.addPiece( createTetrisBlock( 0.5, TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 0, 1 ); + retPiece.addPiece( createTetrisBlock( 0.5 + BLOCK_SIZE, + TOP_BORDER + BLOCK_SIZE, color, + outline, renderer, scene ), + 1, 1 ); + retPiece.setDefPos( 0.5, TOP_BORDER ); return retPiece; } @@ -277,15 +310,16 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { bg->setPermanent( true ); scene.addObject( bg ); auto left_barrier = std::make_shared< SDLPP::RectangleRender >( - 0.28, 0, 0.02, 1, r, "#FF000080", true ); + LEFT_BORDER - 0.02, 0, 0.02, BOTTOM_BORDER, r, "#FF000080", true ); left_barrier->centerX(); scene.addObject( left_barrier ); auto right_barrier = std::make_shared< SDLPP::RectangleRender >( - 0.7, 0, 0.02, 1, r, "#FF000080", true ); + RIGHT_BORDER, 0, 0.02, BOTTOM_BORDER, r, "#FF000080", true ); right_barrier->centerX(); scene.addObject( right_barrier ); auto bottom_barrier = std::make_shared< SDLPP::RectangleRender >( - 0.28, 1, 0.44, 0.02, r, "#FF000080", true ); + LEFT_BORDER - 0.02, BOTTOM_BORDER, RIGHT_BORDER - LEFT_BORDER + 0.04, + 0.02, r, "#FF000080", true ); bottom_barrier->centerX(); scene.addObject( bottom_barrier ); auto tetris = std::make_shared< SDLPP::TextRenderer >( @@ -293,34 +327,34 @@ void addStuff( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { tetris->centerX(); scene.addObject( tetris ); auto next = std::make_shared< SDLPP::TextRenderer >( - 0.8, 0.35, 0.2, 0.1, r, *font, "NEXT", "FFFFFF", "000000", 5, - SDLPP_TEXT_CENTER ); + RIGHT_BORDER + 0.1, 0.35, 0.2, 0.1, r, *font, "NEXT", "FFFFFF", + "000000", 5, SDLPP_TEXT_CENTER ); next->centerX(); scene.addObject( next ); double posy = 1; - auto gameover = - std::make_shared< SDLPP::RectangleRender >( 0.5, 0, 0, 0.195, r ); - auto gameover_collision = SDLPP::Rect( -1, 0, -1, 1 ); + auto gameover = std::make_shared< SDLPP::RectangleRender >( + 0.5, 0, 0, TOP_BORDER + BLOCK_SIZE, r ); + auto gameover_collision = SDLPP::Rect( -1, 0, -1, 0.9 ); gameover_collision.setInfinite(); gameover->addCollision( gameover_collision ); gameover->setId( GAME_OVER ); gameover->setColiderColor( "FF0000" ); scene.addObject( gameover ); auto score_text = std::make_shared< SDLPP::TextRenderer >( - 0.8, 0.1, 0.2, 0.1, r, *font, "SCORE", "#FFFFFF", "#000000", 5, - SDLPP_TEXT_CENTER ); + RIGHT_BORDER + 0.1, 0.1, 0.2, 0.1, r, *font, "SCORE", "#FFFFFF", + "#000000", 5, SDLPP_TEXT_CENTER ); score_text->centerX(); scene.addObject( score_text ); score_texture = std::make_shared< SDLPP::TextRenderer >( - 0.8, 0.2, 0.2, 0.1, r, *font, std::to_string( score ), "FFFFFF", - "000000", 5, SDLPP_TEXT_TOP ); + RIGHT_BORDER + 0.1, 0.2, 0.2, 0.1, r, *font, std::to_string( score ), + "FFFFFF", "000000", 5, SDLPP_TEXT_TOP ); score_texture->centerX(); scene.addObject( score_texture ); for ( int i = 0; i < 20; i++ ) { - posy -= 0.04; + posy -= BLOCK_SIZE; auto colider = std::make_shared< SDLPP::RectangleRender >( - 0.3, posy, 0.04, 0.04, r ); + LEFT_BORDER, posy, BLOCK_SIZE, BLOCK_SIZE, r ); auto colider_colider = SDLPP::Rect( -1, 0.1, -1, 0.8 ); colider_colider.setInfinite(); colider->addCollision( colider_colider ); @@ -366,6 +400,51 @@ void quitGame() { quit = true; } +void checkRotation( TetrisPiece &piece, SDLPP::Scene &scene ) { + bool crash = true; + int left = 0x01; + int right = 0x02; + int bottom = 0x04; + int flags = 0; + 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 ) { + 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; + } + } + } + } + } +} + void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { bool crash = false; std::lock_guard< std::mutex > guard( movement_mutex ); @@ -380,10 +459,10 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { case SDLK_a: for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - // 0.31 because doubles - if ( pos.first < 0.31 ) + // 0.01 because doubles + if ( pos.first < ( LEFT_BORDER + 0.01 ) ) crash = true; - x->setPos( pos.first - 0.04, pos.second ); + x->setPos( pos.first - BLOCK_SIZE, pos.second ); } for ( auto &x : cur_object.getObjects() ) { auto collisions = scene.getCollisions( *x, { BRICK_ID } ); @@ -393,7 +472,7 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { if ( crash ) { for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - x->setPos( pos.first + 0.04, pos.second ); + x->setPos( pos.first + BLOCK_SIZE, pos.second ); } } break; @@ -401,11 +480,11 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { case SDLK_d: for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - // 0.65 because doubles - if ( pos.first > 0.65 ) { + // 0.01 because doubles + if ( pos.first > RIGHT_BORDER - BLOCK_SIZE - 0.01 ) { crash = true; } - x->setPos( pos.first + 0.04, pos.second ); + x->setPos( pos.first + BLOCK_SIZE, pos.second ); } for ( auto &x : cur_object.getObjects() ) { auto collisions = scene.getCollisions( *x, { BRICK_ID } ); @@ -416,7 +495,7 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { if ( crash ) { for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - x->setPos( pos.first - 0.04, pos.second ); + x->setPos( pos.first - BLOCK_SIZE, pos.second ); } } break; @@ -427,6 +506,7 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { case SDLK_UP: case SDLK_w: cur_object.rotate(); + checkRotation( cur_object, scene ); break; case SDLK_r: scene.getRenderer().setRenderColiders( @@ -549,7 +629,7 @@ void moveThem( std::shared_ptr< SDLPP::Scene > scene, int ticks ) { fall: for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - x->setPos( pos.first, pos.second + 0.04 ); + x->setPos( pos.first, pos.second + BLOCK_SIZE ); } bool fell = false; for ( auto &x : cur_object.getObjects() ) { @@ -566,7 +646,7 @@ fall: if ( fell ) { for ( auto &x : cur_object.getObjects() ) { auto pos = x->getPos(); - x->setPos( pos.first, pos.second - 0.04 ); + x->setPos( pos.first, pos.second - BLOCK_SIZE ); } for ( auto &block : cur_object.getObjects() ) { if ( scene->getCollisions( *block, { GAME_OVER } ).size() > 0 ) { @@ -608,7 +688,7 @@ void doInput( std::shared_ptr< SDLPP::Scene > scene ) { continue; auto pos = elem->getPos(); if ( pos.second < colider_y ) { - elem->setPos( pos.first, pos.second + 0.04 ); + elem->setPos( pos.first, pos.second + BLOCK_SIZE ); } } using namespace std::chrono_literals; @@ -666,7 +746,7 @@ int main() { if ( ticks_till_next <= 0 && cur_object.getObjects().size() == 0 ) { std::lock_guard< std::mutex > guard( movement_mutex ); cur_object = next_object; - cur_object.setPos( 0.5, 0.16 ); + cur_object.setPos( 0.5, TOP_BORDER ); next_object = tetrisFunctions[std::rand() / ( ( RAND_MAX + 1u ) / 7 )]( renderer, main_scene );