diff --git a/mario/blocks.cpp b/mario/blocks.cpp index ee58ef8..0157657 100644 --- a/mario/blocks.cpp +++ b/mario/blocks.cpp @@ -10,6 +10,7 @@ #include "blocks/simpleblocks.hpp" #include "blocks/coineditorblock.hpp" #include "blocks/coinblock.hpp" +#include "blocks/mushroomblock.hpp" #include "mario.hpp" #define CAN_BE_DESTROYED_FLAG 0x0000000000000001 @@ -66,6 +67,13 @@ void MarioBlock::visit( SDLPP::Visitor &visitor ) { dynamic_cast< MarioVisitor & >( visitor ).setCoin(); dynamic_cast< MarioVisitor & >( visitor ).setCoinBlock(coin); } + if ( hasMushroom() ) { + removeMushroom(); + auto mushroom = createTerrainBlock(MUSHROOM_ID, LandType::OVERWORLD, renderer); + mushroom->setPos(getPos()); + std::dynamic_pointer_cast(mushroom)->setParent(this); + dynamic_cast< MarioVisitor & >( visitor ).setMushroomBlock(mushroom); + } } #endif visitor.visit( *this ); @@ -78,32 +86,94 @@ void MarioBlock::setTerrain( bool terrain ) { } void MarioBlock::bounce() { - if ( _bouncing ) + if ( _bouncing ) { return; + } _bouncing = true; og_pos = getPos(); ticks_to_bounce = bounce_ticks; setMovement( 0, -bounce_speed ); } -bool MarioBlock::isBouncing() { +void MarioBlock::travelToPos(const SDLPP::Vec2D &target) { + if(_traveling) { + return; + } + _traveling = true; + _target = target; + + auto movement = (_target - getPos()); + auto abs_mov_x = movement.getX(); + if(abs_mov_x < 0) { + abs_mov_x *= -1; + } + auto abs_mov_y = movement.getY(); + if(abs_mov_y < 0) { + abs_mov_y *= -1; + } + + movement = movement / (abs_mov_x > abs_mov_y ? abs_mov_x : abs_mov_y); + movement = movement * travel_speed; + setMovement(movement.getX(), movement.getY()); +} + +void MarioBlock::gravity(int ticks) { + if(_on_ground) { + return; + } + _ticks_till_gravity -= ticks; + if(_ticks_till_gravity < 0) { + addMovement(0, _gravity_acceleration); + _ticks_till_gravity = _base_gravity_ticks; + } +} + +bool MarioBlock::isBouncing() const { return _bouncing; } +bool MarioBlock::isTraveling() const { + return _traveling; +} + void MarioBlock::custom_move( int ticks ) { - if ( !_bouncing ) + if ( !_bouncing && !_traveling ) { return; - if ( getMovement().getY() < 0 ) { - ticks_to_bounce -= ticks; - if ( ticks_to_bounce < 0 ) { - setMovement( 0, bounce_speed ); - ticks_to_bounce = bounce_ticks; + } + if( _bouncing ) { + if ( getMovement().getY() < 0 ) { + ticks_to_bounce -= ticks; + if ( ticks_to_bounce < 0 ) { + setMovement( 0, bounce_speed ); + ticks_to_bounce = bounce_ticks; + } + } else { + if ( getPos().getY() >= og_pos.getY() ) { + setMovement( 0, 0 ); + setPos( getPos().getX(), og_pos.getY() ); + _bouncing = false; + } } - } else { - if ( getPos().getY() >= og_pos.getY() ) { - setMovement( 0, 0 ); - setPos( getPos().getX(), og_pos.getY() ); - _bouncing = false; + } + if(_traveling) { + bool overshot_x = (getMovement().getX() < 0 && + getPos().getX() <= _target.getX()) || + (getMovement().getX() > 0 && + getPos().getX() >= _target.getX()); + bool overshot_y = (getMovement().getY() < 0 && + getPos().getY() <= _target.getY()) || + (getMovement().getY() > 0 && + getPos().getY() >= _target.getY()); + if(overshot_x) { + setPos(_target.getX(), getPos().getY()); + setMovement(0, getMovement().getY()); + } + if(overshot_y) { + setPos(getPos().getX(), _target.getY()); + setMovement(getMovement().getX(), 0); + } + if(getMovement() == SDLPP::Vec2D(0,0)) { + _traveling = false; } } } @@ -128,6 +198,9 @@ void MarioBlock::removeCoin() { void MarioBlock::removeMushroom() { _mushroom = false; } +void MarioBlock::addMushroom() { + _mushroom = true; +} void MarioBlock::setCoinCount( int coins ) { _coins = coins; } @@ -510,6 +583,10 @@ createBlockById( uint64_t id, int x, int y, result = std::static_pointer_cast< MarioBlock >( std::make_shared< CoinBlock >( x, y, renderer ) ); break; + case MUSHROOM_ID: + result = std::static_pointer_cast< MarioBlock >( + std::make_shared< MushroomBlock >( x, y, renderer ) ); + break; #endif } return result; @@ -574,3 +651,8 @@ enum BlockRole::Value getBlockRole( uint64_t id ) { // TODO modifier/character return BlockRole::MODIFIER; } + +void MarioBlock::setBaseRect(SDL_Rect rect) { + _base_src = rect; + setType(getType()); +} diff --git a/mario/blocks.hpp b/mario/blocks.hpp index fc47965..c4b1d8b 100644 --- a/mario/blocks.hpp +++ b/mario/blocks.hpp @@ -2,6 +2,7 @@ #define BLOCKS_H #include "../sdlpp/sdlpp_rectrenderer.hpp" +#include #include struct LandType { @@ -18,6 +19,7 @@ public: void setTool( bool tool = true ); void setTerrain( bool terrain = true ); void bounce(); + void travelToPos(const SDLPP::Vec2D &target); void custom_move( int ticks ) override; void setType( LandType::Value type ); LandType::Value getType() const; @@ -33,14 +35,33 @@ public: bool hasMushroom(); void removeCoin(); void removeMushroom(); + void addMushroom(); void setCoinCount( int coins ); void setDestructible( bool destructible = true ); void ensureCollision(); - bool isBouncing(); + bool isBouncing() const; + bool isTraveling() const; + void setBaseRect(SDL_Rect rect); protected: double bounce_speed = 0.5; int bounce_ticks = 100; + double travel_speed = bounce_speed; + void gravity(int ticks); + void setOnGround(bool on_ground = true) { + _on_ground = on_ground; + if(on_ground) { + setMovement(getMovement().getX(), 0); + } + } + bool isOnGround() const { + return _on_ground; + } + void setGravityTicks(int ticks) { + _base_gravity_ticks = ticks; + } + + virtual void setWorldTypeSrc( LandType::Value world ); private: bool _tool = false; @@ -48,6 +69,7 @@ private: bool _destructible = false; bool _can_be_destroyed = false; bool _bouncing = false; + bool _traveling = false; int _coins = 0; bool _mushroom = false; bool _release_coin = false; @@ -55,8 +77,12 @@ private: SDLPP::Vec2D< double > og_pos = {}; LandType::Value _type; SDL_Rect _base_src; + SDLPP::Vec2D _target = {0,0}; - virtual void setWorldTypeSrc( LandType::Value world ); + bool _on_ground = true; + int _base_gravity_ticks = 1000 / 60; + int _ticks_till_gravity = 0; + double _gravity_acceleration = 1.0/(64.0/7.0); }; extern const std::vector< uint64_t > possibleBlocks;