#include "../sdlpp/sdlpp.hpp" #include "sprites.hpp" #ifdef _WIN32 #include "../sdlpp/SDL2/SDL2_framerate.h" #include #include #include #else #include #endif // UNIX #include #include "global_vars.hpp" #include "objectids.hpp" #include "blocks.hpp" #include "maploader.hpp" #include "mario_visitor.hpp" #define SIDE_MOVEMENT 0.8 #define FALL_MOVEMENT 1 bool quit = false; std::shared_ptr< SDLPP::RectangleRender > mario = nullptr; std::shared_ptr< SDLPP::Texture > mario_texture = nullptr; std::shared_ptr< SDLPP::RectangleRender > leftStop = nullptr; std::shared_ptr< SDLPP::Renderer > renderer = nullptr; bool mario_facing_right = true; void setMarioStanding() { if ( mario->getMovement().getX() == 0 ) { mario->pauseAnimation(); } } void handleKeyDown( SDL_Keycode key, SDLPP::Scene &scene ) { switch ( key ) { case SDLK_ESCAPE: quit = true; break; case SDLK_a: mario->resumeAnimation(); mario->addMovement( -SIDE_MOVEMENT, 0 ); if ( mario->getMovement().getX() < 0 && mario_facing_right ) { mario->flipHorizontally(); mario_facing_right = false; } break; case SDLK_d: mario->resumeAnimation(); mario->addMovement( SIDE_MOVEMENT, 0 ); if ( mario->getMovement().getX() > 0 && !mario_facing_right ) { mario->flipHorizontally(); mario_facing_right = true; } break; case SDLK_SPACE: case SDLK_w: break; case SDLK_s: break; case SDLK_r: scene.getRenderer().setRenderColiders( !scene.getRenderer().getRenderColiders() ); default: break; } } void handleKeyUp( SDL_Keycode key ) { switch ( key ) { case SDLK_a: mario->resumeAnimation(); mario->addMovement( SIDE_MOVEMENT, 0 ); if ( mario->getMovement().getX() > 0 && !mario_facing_right ) { mario->flipHorizontally(); mario_facing_right = true; } break; case SDLK_d: mario->resumeAnimation(); mario->addMovement( -SIDE_MOVEMENT, 0 ); if ( mario->getMovement().getX() < 0 && mario_facing_right ) { mario->flipHorizontally(); mario_facing_right = false; } break; case SDLK_w: case SDLK_s: default: break; } } void pollEvents( SDLPP::Scene &scene ) { SDL_Event event; while ( SDLPP::getSDLEvent( event ) ) { switch ( event.type ) { case SDL_QUIT: quit = true; break; case SDL_KEYDOWN: if ( !event.key.repeat ) handleKeyDown( event.key.keysym.sym, scene ); break; case SDL_KEYUP: handleKeyUp( event.key.keysym.sym ); break; case SDL_WINDOWEVENT: if ( event.window.event == SDL_WINDOWEVENT_RESIZED ) { scene.updateSizeAndPosition(); if ( leftStop ) { auto rendDims = renderer->getDoubleDimensions(); auto left = rendDims.getX() < 2.0 ? -( rendDims.getX() - 1 ) / 2.0 - 0.1 : -0.5; leftStop->setPos( left, 0 ); } auto dimensions = renderer->getDoubleDimensions(); auto leftmost = -( dimensions.getX() - 1 ) / 2.0; auto rightmost = 1 - leftmost; auto marioPos = mario->getPos(); if ( marioPos.getX() < leftmost ) { scene.moveEverything( leftmost - marioPos.getX(), 0 ); } else if ( marioPos.getX() > rightmost ) { scene.moveEverything( marioPos.getX() - rightmost, 0 ); } if ( mario->getPos().getX() < leftStop->getDoubleRect().first.getX() + leftStop->getDoubleRect().second.getX() ) { mario->setPos( leftStop->getDoubleRect().first.getX() + leftStop->getDoubleRect().second.getX(), mario->getPos().getY() ); } } default: break; } } } void doInput( std::shared_ptr< SDLPP::Scene > scene ) { FPSmanager gFPS; SDL_initFramerate( &gFPS ); SDL_setFramerate( &gFPS, 200 ); while ( true ) { SDL_framerateDelay( &gFPS ); pollEvents( *scene ); auto prevPos = mario->getDoubleRect().first; scene->updateScene(); MarioVisitor mv{}; scene->visitCollisions( *mario, mv ); if ( mv.isDead() ) { quit = true; } if ( !mv.isOnGround() ) { mario->setMovement( mario->getMovement().getX(), FALL_MOVEMENT ); } else { mario->resetMovementY(); } if ( mv.isStopped() || ( !mv.canGoLeft() && prevPos.getX() > mario->getPos().getX() ) || ( !mv.canGoRight() && prevPos.getX() < mario->getPos().getX() ) ) { mario->setPos( prevPos.getX(), mario->getPos().getY() ); } auto playerX = mario->getRect().x; auto width = scene->getWidth(); auto rightBarrier = width * 0.7; auto rightmostX = scene->rightmost()->getRect().x + scene->rightmost()->getRect().w; scene->moveEverything( ( playerX > rightBarrier && rightmostX > width ) * ( rightBarrier - playerX ) / width, 0 ); } } #ifdef _WIN32 int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmdLine, int nCmdShow ) { #else int main() { #endif SDLPP::init(); SDLPP::Window w( "Mario clone!" ); w.setResizable( true ); renderer = std::make_shared< SDLPP::Renderer >( w ); renderer->setBlendMode( SDL_BLENDMODE_BLEND ); // prepare global vars g_terrain_texture = std::make_shared< SDLPP::Texture >( renderer, "sprites/terrain.png", MARIO_OVERWORLD_COLORKEY ); auto scene = std::make_shared< SDLPP::Scene >( renderer ); auto bg = std::make_shared< SDLPP::RectangleRender >( 0, 0, 10, 10, renderer, MARIO_OVERWORLD_COLORKEY, true ); bg->setPermanent(); bg->setStatic(); bg->setId( 1 ); scene->addObject( bg ); mario_texture = std::make_shared< SDLPP::Texture >( renderer, "sprites/mario.png", MARIO_OVERWORLD_COLORKEY ); mario = std::make_shared< SDLPP::RectangleRender >( 0, 0, BLOCK_SIZE, BLOCK_SIZE, renderer, mario_texture, MARIO_STANDING_SRC ); mario->setAnimationFrames( MARIO_WALK_ANIM ); mario->setId( 2 ); mario->setAlignment( SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER ); mario->setAnimationSpeed( 12.5 ); mario->pauseAnimation(); mario->setMovement( 0, 0 ); mario->setMovementSpeed( 0.4 ); mario->addCollision( SDLPP::RectColider( 0.21, 0.85, 0.65, 0.16, MARIO_FLOOR_DETECT ) ); mario->addCollision( SDLPP::RectColider( 0, 0.1, 0.1, 0.8, MARIO_LEFT_SIDE_DETECT ) ); mario->addCollision( SDLPP::RectColider( 0.9, 0.1, 0.1, 0.8, MARIO_RIGHT_SIDE_DETECT ) ); mario->setStatic( false ); scene->addObject( mario ); auto defeat = std::make_shared< SDLPP::RectangleRender >( 0, 1.01, 0, 0, renderer ); defeat->setId( DEATH_ID ); defeat->setAlignment( SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER ); defeat->setPermanent(); auto defeatCol = SDLPP::RectColider( -1, 0, -1, -1 ); defeatCol.setInfinite(); defeat->addCollision( defeatCol ); scene->addObject( defeat ); leftStop = std::make_shared< SDLPP::RectangleRender >( -0.1, 0, 0.11, 0, renderer ); leftStop->setId( STOP_MOVEMENT ); leftStop->setAlignment( SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER ); leftStop->setPermanent(); auto leftStopCol = SDLPP::RectColider( 0, -1, 1, -1 ); leftStopCol.setInfinite(); leftStop->addCollision( leftStopCol ); leftStop->setColiderColor( "#FF00FF" ); scene->addObject( leftStop ); loadMap( scene, mario, "test_binary2.bin", renderer ); FPSmanager gFPS; SDL_initFramerate( &gFPS ); SDL_setFramerate( &gFPS, 60 ); auto base = SDL_GetTicks(); int frames = 0; std::thread inputThread( doInput, scene ); inputThread.detach(); scene->moveEverything( -mario->getDoubleRect().first.getX() + 0.2, 0 ); while ( !quit ) { SDL_PumpEvents(); SDL_framerateDelay( &gFPS ); setMarioStanding(); scene->renderScene(); renderer->presentRenderer(); frames++; if ( SDL_GetTicks() - base >= 1000 ) { std::cout << "FPS: " << frames << std::endl; frames = 0; base = SDL_GetTicks(); } } return 0; }