From af5e7bbd34ebf3ddb05b11aacfed677e3b438ad8 Mon Sep 17 00:00:00 2001 From: zvon Date: Mon, 24 Aug 2020 18:44:42 +0200 Subject: [PATCH] Add game over screen --- tetris.cpp | 146 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 137 insertions(+), 9 deletions(-) diff --git a/tetris.cpp b/tetris.cpp index 17a7e28..85fb879 100644 --- a/tetris.cpp +++ b/tetris.cpp @@ -25,12 +25,18 @@ #define TETRIS_L_LEFT 5 #define TETRIS_Z_LEFT 6 -bool pause = false; +#define PAUSE_PAUSE 1 +#define PAUSE_GAME_OVER 2 + +int pause = 0; int pause_select = 0; int pause_max = 2; +int game_over_select = 0; +int game_over_max = 1; int ticks_till_fall = TICKS_TILL_FALL; int ticks_till_descend = TICKS_TILL_DESCEND; std::vector< std::shared_ptr< SDLPP::RectangleRender > > pause_options; +std::vector< std::shared_ptr< SDLPP::RectangleRender > > game_over_options; std::shared_ptr< SDLPP::TextRenderer > score_texture; std::shared_ptr< SDLPP::Renderer > active_renderer; int score = 0; @@ -43,6 +49,7 @@ std::vector< int > bag = { 28, 28, 28, 28, 28, 28, 28 }; std::shared_ptr< SDLPP::Font > font; std::shared_ptr< SDLPP::Scene > active_scene; std::shared_ptr< SDLPP::Scene > pause_scene; +std::shared_ptr< SDLPP::Scene > game_over_scene; class TetrisBlock : public SDLPP::RectangleRender { public: @@ -192,6 +199,7 @@ std::shared_ptr< TetrisPiece > next_object; void doInput( std::shared_ptr< SDLPP::Scene > scene ); void doInputPause(); +void doInputGameOver(); bool quit = false; std::mutex movement_mutex; @@ -500,6 +508,32 @@ void addPause( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { pause_options.push_back( quit ); } +void addGameOver( SDLPP::Scene &scene, std::shared_ptr< SDLPP::Renderer > &r ) { + auto bg = std::make_shared< SDLPP::RectangleRender >( 0, 0, 10, 10, r, + "#00000080", true ); + bg->setId( 123 ); + bg->setPermanent( true ); + scene.addObject( bg ); + auto y = std::make_shared< SDLPP::TextRenderer >( 0.25, 0.1, 0.5, 0.3, r ); + y->setText( *font, "GAME OVER", "#FFFFFF", "#000000", 5 ); + y->setId( 0 ); + y->centerX(); + scene.addObject( y ); + auto restart = + std::make_shared< SDLPP::TextRenderer >( 0.4, 0.5, 0.2, 1, r ); + restart->setText( *font, "Restart", "#FFFFFF", "#000000", 5 ); + restart->centerX(); + restart->setColor( "#FFFFFF40" ); + scene.addObject( restart ); + game_over_options.push_back( restart ); + auto quit = + std::make_shared< SDLPP::TextRenderer >( 0.4, 0.7, 0.2, 1, r ); + quit->setText( *font, "Quit Game", "#FFFFFF", "#000000", 5 ); + quit->centerX(); + scene.addObject( quit ); + game_over_options.push_back( quit ); +} + void quitGame() { std::cout << "Quitting!" << std::endl; quit = true; @@ -587,7 +621,7 @@ void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { switch ( key ) { case SDLK_ESCAPE: { - pause = true; + pause = PAUSE_PAUSE; pause_scene->updateSizeAndPosition(); std::thread pauseThread( doInputPause ); pauseThread.detach(); @@ -654,7 +688,7 @@ void handleKeyUp( SDL_Keycode key ) { void handleKeyDownPause( SDL_Keycode key ) { switch ( key ) { case SDLK_ESCAPE: { - pause = false; + pause = 0; active_scene->setPrevTicks( SDL_GetTicks() ); std::thread inputThread( doInput, active_scene ); inputThread.detach(); @@ -682,17 +716,72 @@ void handleKeyDownPause( SDL_Keycode key ) { case SDLK_RETURN: switch ( pause_select ) { case 0: { - pause = false; + pause = 0; active_scene->setPrevTicks( SDL_GetTicks() ); std::thread inputThread( doInput, active_scene ); inputThread.detach(); } break; case 1: { - pause = false; + pause = 0; cur_object.reset(); checked_line = true; next_object.reset(); + score = 0; + update_score = true; + active_scene->resetScene(); + active_scene->setPrevTicks( SDL_GetTicks() ); + + next_object = tetrisFunctions[std::rand() / ( ( RAND_MAX + 1u ) / 7 )]( + active_scene->getRendererShared(), active_scene ); + next_object->setPos( 0.9, 0.5 ); + std::thread inputThread( doInput, active_scene ); + inputThread.detach(); + } + break; + case 2: + quitGame(); + default: + break; + } + default: + break; + } +} + +void handleKeyDownGameOver( SDL_Keycode key ) { + switch ( key ) { + case SDLK_r: + active_scene->getRenderer().setRenderColiders( + !active_scene->getRenderer().getRenderColiders() ); + break; + case SDLK_s: + case SDLK_DOWN: + game_over_options[game_over_select]->unsetColor(); + game_over_select++; + if ( game_over_select > game_over_max ) + game_over_select = 0; + game_over_options[game_over_select]->setColor( "FFFFFF40" ); + break; + case SDLK_w: + case SDLK_UP: + game_over_options[game_over_select]->unsetColor(); + game_over_select--; + if ( game_over_select < 0 ) + game_over_select = game_over_max; + game_over_options[game_over_select]->setColor( "FFFFFF40" ); + break; + case SDLK_RETURN: + switch ( game_over_select ) { + case 0: + { + // TODO reset function + pause = 0; + cur_object.reset(); + checked_line = true; + next_object.reset(); + score = 0; + update_score = true; active_scene->resetScene(); active_scene->setPrevTicks( SDL_GetTicks() ); @@ -758,6 +847,28 @@ void pollEventsPause() { } } +void pollEventsGameOver() { + SDL_Event event; + while ( SDL_PollEvent( &event ) != 0 ) { + switch ( event.type ) { + case SDL_QUIT: + quitGame(); + break; + case SDL_KEYDOWN: + if ( !event.key.repeat ) + handleKeyDownGameOver( event.key.keysym.sym ); + break; + case SDL_WINDOWEVENT: + if ( event.window.event == SDL_WINDOWEVENT_RESIZED ) { + active_scene->updateSizeAndPosition(); + game_over_scene->updateSizeAndPosition(); + } + default: + break; + } + } +} + void moveThem( std::shared_ptr< SDLPP::Scene > scene, int ticks ) { ticks_till_fall -= ticks; if ( cur_object->isDescending() ) @@ -788,8 +899,10 @@ fall: 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; - quitGame(); + pause = PAUSE_GAME_OVER; + game_over_scene->updateSizeAndPosition(); + std::thread pauseThread( doInputGameOver ); + pauseThread.detach(); } } cur_object.reset(); @@ -851,6 +964,18 @@ void doInputPause() { } } +void doInputGameOver() { + FPSmanager gFPS; + SDL_initFramerate( &gFPS ); + SDL_setFramerate( &gFPS, 200 ); + while ( pause ) { + SDL_framerateDelay( &gFPS ); + pollEventsGameOver(); + if ( !pause ) + break; + } +} + int main() { SDLPP::init(); SDLPP::Window w( "Tetris clone!" ); @@ -865,6 +990,8 @@ int main() { pause_scene = std::make_shared< SDLPP::Scene >( renderer ); addPause( *pause_scene, renderer ); + game_over_scene = std::make_shared(renderer); + addGameOver(*game_over_scene, renderer); auto base = SDL_GetTicks(); int frames = 0; @@ -880,7 +1007,6 @@ int main() { next_object->setPos( 0.9, 0.5 ); while ( !quit ) { SDL_framerateDelay( &gFPS ); - std::cout << "cur_object: " << (cur_object ? "TRUE" : "FALSE") << ", checked_line: " << (checked_line ? "TRUE" : "FALSE") << std::endl; if ( !cur_object && checked_line ) { std::lock_guard< std::mutex > guard( movement_mutex ); cur_object = next_object; @@ -904,8 +1030,10 @@ int main() { } main_scene->renderScene(); - if ( pause ) { + if ( pause == PAUSE_PAUSE ) { pause_scene->renderScene( false ); + } else if ( pause == PAUSE_GAME_OVER ) { + game_over_scene->renderScene( false ); } main_scene->presentScene(); wait_for_anim = false;