diff --git a/mario/CMakeLists.txt b/mario/CMakeLists.txt index 9a72d6d..53fcc49 100644 --- a/mario/CMakeLists.txt +++ b/mario/CMakeLists.txt @@ -68,15 +68,18 @@ target_sources(mario PRIVATE main.cpp PRIVATE visitors/mario_visitor.cpp PRIVATE visitors/mushroom_visitor.cpp + PRIVATE visitors/goomba_visitor.cpp PRIVATE visitors/bounce_visitor.cpp PRIVATE visitors/visitor_generator.cpp PRIVATE blocks/coinblock.cpp PRIVATE blocks/mushroomblock.cpp + PRIVATE blocks/goombablock.cpp ) target_sources(editor PRIVATE ${CommonFiles} PRIVATE blocks/coineditorblock.cpp + PRIVATE blocks/goombablock.cpp PRIVATE editor.cpp PRIVATE edit_box.cpp PRIVATE tool_box.cpp diff --git a/mario/blocks/goombablock.cpp b/mario/blocks/goombablock.cpp new file mode 100644 index 0000000..888498a --- /dev/null +++ b/mario/blocks/goombablock.cpp @@ -0,0 +1,75 @@ +#include "goombablock.hpp" +#include "../sprites.hpp" +#include "../global_vars.hpp" +#include "../objectids.hpp" +#include "../visitors/goomba_visitor.hpp" + +GoombaBlock::GoombaBlock( int x, int y, std::shared_ptr< SDLPP::Renderer > &renderer ) : MarioBlock(x, y, renderer, g_enemies_texture, GOOMBA_WALK_ANIM[0], true, true) { +#ifndef EDITOR + setAnimationFrames(GOOMBA_WALK_ANIM); + setAnimationSpeed(12.5); + resumeAnimation(); +#endif + setId(GOOMBA_ID); + auto bottom_detect = SDLPP::RectColider( 0.2, 1, 0.6, 0, NPC_FLOOR_DETECT ); + bottom_detect.setMinHeight(1); + addCollision(bottom_detect); + addCollision( + SDLPP::RectColider( 0, 0.25, 0.1, 0.6, NPC_LEFT_SIDE_DETECT ) ); + addCollision( + SDLPP::RectColider( 0.9, 0.25, 0.1, 0.6, NPC_RIGHT_SIDE_DETECT ) ); + addCollision( std::make_shared( 0.5, 0, 0.2, 0.15, NPC_TOP_DETECT ) ); +#ifndef EDITOR + setMovement(-0.19, 0); +#endif +} + +void GoombaBlock::move(int ticks) { +#ifndef EDITOR + if(wasVisible()) { + MarioBlock::move(ticks); + } +#else + MarioBlock::move(ticks); +#endif +} + +void GoombaBlock::custom_move(int ticks) { +#ifndef EDITOR + if(death_started) { + death_countdown -= ticks; + if(death_countdown <= 0) { + destroy(); + } + } else { + gravity(ticks); + } +#endif + MarioBlock::custom_move(ticks); +} + +void GoombaBlock::handleVisitor(SDLPP::Visitor &visitor) { +#ifndef EDITOR + auto &g_visitor = dynamic_cast(visitor); + setOnGround(g_visitor.isOnGround()); + if(isOnGround()) { + setPos(getPos().getX(), g_visitor.getGroundY() - BLOCK_SIZE); + } + if(!g_visitor.canGoLeft() || !g_visitor.canGoRight()) { + setPos(g_visitor.getValidXPos(), getPos().getY()); + setMovement(-getMovement().getX(), getMovement().getY()); + } + if(g_visitor.isDead()) { + removeCollisions(); + pauseAnimation(); + setBaseRect(GOOMBA_DEATH_SRC); + setMovement(0, 0); + startDeath(); + //destroy(); + } +#endif +} + +void GoombaBlock::startDeath() { + death_started = true; +} diff --git a/mario/blocks/goombablock.hpp b/mario/blocks/goombablock.hpp new file mode 100644 index 0000000..c5b3cca --- /dev/null +++ b/mario/blocks/goombablock.hpp @@ -0,0 +1,18 @@ +#ifndef GOOMBA_BLOCK_HPP +#define GOOMBA_BLOCK_HPP + +#include "../blocks.hpp" + +class GoombaBlock : public MarioBlock { +public: + GoombaBlock( int x, int y, std::shared_ptr< SDLPP::Renderer > &renderer ); + void custom_move(int ticks) override; + void move(int ticks) override; + void handleVisitor(SDLPP::Visitor &visitor) override; +private: + void startDeath(); + int death_countdown = 100; + bool death_started = false; +}; + +#endif diff --git a/mario/sprites.cpp b/mario/sprites.cpp index 7a671a1..3736625 100644 --- a/mario/sprites.cpp +++ b/mario/sprites.cpp @@ -90,3 +90,7 @@ const SDLPP::Vec2D OVERWORLD_SHIFT = {0, 0}; const SDLPP::Vec2D UNDERWORLD_SHIFT = {274, 0}; const SDLPP::Vec2D WATER_SHIFT = {548, 0}; const SDLPP::Vec2D BOWSER_SHIFT = {0, 173}; + +const std::vector< SDL_Rect > GOOMBA_WALK_ANIM = { { 1, 28, 16, 16 }, + { 18, 28, 16, 16 } }; +const SDL_Rect GOOMBA_DEATH_SRC = {39, 28, 16, 16}; diff --git a/mario/sprites.hpp b/mario/sprites.hpp index d757efc..90c9f89 100644 --- a/mario/sprites.hpp +++ b/mario/sprites.hpp @@ -93,6 +93,9 @@ extern const SDL_Rect MOD_DESTRUCTIBLE_SRC; extern const SDL_Rect MOD_BACKGROUND_SRC; extern const SDL_Rect MOD_COIN_SRC; extern const SDL_Rect MOD_MUSHROOM_SRC; +//------------------ ENEMIES ------------------------- +extern const SDL_Rect GOOMBA_DEATH_SRC; +extern const std::vector GOOMBA_WALK_ANIM; extern const SDLPP::Vec2D OVERWORLD_SHIFT; extern const SDLPP::Vec2D UNDERWORLD_SHIFT; diff --git a/mario/visitors/goomba_visitor.cpp b/mario/visitors/goomba_visitor.cpp new file mode 100644 index 0000000..61288d2 --- /dev/null +++ b/mario/visitors/goomba_visitor.cpp @@ -0,0 +1,59 @@ +#include "goomba_visitor.hpp" +#include "../../sdlpp/sdlpp_renderobject.hpp" +#include "../objectids.hpp" +#include "../sprites.hpp" + +void GoombaVisitor::visit( const SDLPP::RenderObject &obj ) { + auto id = obj.getId(); + switch ( id ) { + case FLOOR_ID: + case BRICK_ID: + case BRICK_TOP_ID: + case PIPE_LEFT_BOTTOM_ID: + case PIPE_RIGHT_BOTTOM_ID: + case PIPE_LEFT_TOP_ID: + case PIPE_RIGHT_TOP_ID: + case STEP_ID: + case SIDEWAY_PIPE_END_TOP_ID: + case SIDEWAY_PIPE_END_BOTTOM_ID: + case SIDEWAY_PIPE_MIDDLE_BOTTOM_ID: + case SIDEWAY_PIPE_MIDDLE_TOP_ID: + case SIDEWAY_PIPE_CONNECTOR_BOTTOM_ID: + case SIDEWAY_PIPE_CONNECTOR_TOP_ID: + case TREE_PLATFORM_TOP_LEFT_ID: + case TREE_PLATFORM_TOP_RIGHT_ID: + case MUSHROOM_PLATFORM_TOP_MIDDLE_ID: + case MUSHROOM_PLATFORM_TOP_LEFT_ID: + case MUSHROOM_PLATFORM_TOP_RIGHT_ID: + case CANNON_TOWER_ID: + case CANNON_PEDESTAL_ID: + case CANNON_ID: + if ( from == NPC_FLOOR_DETECT ) { + onGround = true; + groundY = obj.getPos().getY(); + } else if ( from == NPC_LEFT_SIDE_DETECT ) { + if(!left && !right) { + movement_blockage = obj.getPos(); + validXPos = movement_blockage.getX() + BLOCK_SIZE; + } + left = true; + } else if (from == NPC_RIGHT_SIDE_DETECT ) { + if(!left && !right) { + movement_blockage = obj.getPos(); + validXPos = movement_blockage.getX() - BLOCK_SIZE; + } + right = true; + } + break; + case DEATH_ID: + death = true; + break; + case MARIO_ID: + if (from == NPC_TOP_DETECT) { + death = true; + } + break; + default: + break; + } +} diff --git a/mario/visitors/goomba_visitor.hpp b/mario/visitors/goomba_visitor.hpp new file mode 100644 index 0000000..8efda9d --- /dev/null +++ b/mario/visitors/goomba_visitor.hpp @@ -0,0 +1,64 @@ +#ifndef GOOMBA_VISITOR_H +#define GOOMBA_VISITOR_H + +#include "../../sdlpp/sdlpp_visitor.hpp" +#include "../../sdlpp/sdlpp_geometry.hpp" +#include "../../sdlpp/sdlpp_scene.hpp" +#include "../blocks.hpp" + +class GoombaVisitor : public SDLPP::Visitor { +public: + GoombaVisitor() = default; + void visit( const SDLPP::RenderObject &obj ) override; + bool isOnGround() const { + return onGround; + } + bool isDead() const { + return death; + } + void setFromId( uint64_t id ) override { + from = id; + } + void setVisitorType( uint64_t type ) override { + _type = type; + } + uint64_t getVisitorType() const override { + return _type; + } + uint64_t getFromId() const override { + return from; + } + bool canGoLeft() const { + return !left; + } + bool canGoRight() const { + return !right; + } + double getGroundY() const { + return groundY; + } + bool topBlock() const { + return top_hit; + } + + const SDLPP::Vec2D &getMovementBlockage() { + return movement_blockage; + } + double getValidXPos() const { + return validXPos; + } + +private: + bool onGround = false; + double groundY = 0; + uint64_t _type{}; + bool death = false; + uint64_t from = -1; + bool left = false; + bool right = false; + bool top_hit = false; + SDLPP::Vec2D movement_blockage; + double validXPos = 0; +}; + +#endif diff --git a/mario/visitors/visitor_generator.cpp b/mario/visitors/visitor_generator.cpp index 3419210..6a037c3 100644 --- a/mario/visitors/visitor_generator.cpp +++ b/mario/visitors/visitor_generator.cpp @@ -2,6 +2,7 @@ #include "../objectids.hpp" #include "mario_visitor.hpp" #include "mushroom_visitor.hpp" +#include "goomba_visitor.hpp" std::shared_ptr< SDLPP::Visitor > getVisitor( const MarioBlock &block, SDLPP::Scene &scene, bool &quit, @@ -14,6 +15,10 @@ getVisitor( const MarioBlock &block, SDLPP::Scene &scene, bool &quit, break; case MUSHROOM_ID: result = std::static_pointer_cast(std::make_shared()); + break; + case GOOMBA_ID: + result = std::static_pointer_cast(std::make_shared()); + break; default: break; }