Refactor to use objects for terrain/mod creation, added coin modifier

This commit is contained in:
2021-07-23 00:08:05 +02:00
parent 79d9f266b4
commit 3be728843a
15 changed files with 1384 additions and 127 deletions
+388 -79
View File
@@ -1,23 +1,29 @@
#include "blocks.hpp"
#include "blocks/coinblock.hpp"
#include "global_vars.hpp"
#include "objectids.hpp"
#include "sprites.hpp"
#include "editor_visitor.hpp"
#include <unordered_map>
#include "mario_visitor.hpp"
#include "blocks/simpleblocks.hpp"
#include "blocks/coinblock.hpp"
#include "mario.hpp"
#define CAN_BE_DESTROYED_FLAG 0x0000000000000001
#define HAS_COLLISION 0x0000000000000002
#define HAS_COLLISION 0x0000000000000002
MarioBlock::MarioBlock( int x, int y,
std::shared_ptr< SDLPP::Renderer > renderer,
std::shared_ptr< SDLPP::Texture > texture,
SDL_Rect src, bool can_be_destroyed, bool destructible )
const std::shared_ptr< SDLPP::Renderer > &renderer,
std::shared_ptr< SDLPP::Texture > texture, SDL_Rect src,
bool can_be_destroyed, bool destructible )
: RectangleRender( x * BLOCK_SIZE, 1 - ( 16 - y ) * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE, renderer, texture, src ) {
_can_be_destroyed = can_be_destroyed;
_destructible = can_be_destroyed && destructible;
setMovementSpeed(1);
_can_be_destroyed = can_be_destroyed;
_destructible = can_be_destroyed && destructible;
setMovementSpeed( 1 );
_coins = 0;
_mushroom = false;
}
void MarioBlock::visit( SDLPP::Visitor &visitor ) {
#ifdef EDITOR
@@ -30,24 +36,29 @@ void MarioBlock::visit( SDLPP::Visitor &visitor ) {
destroy();
}
#else
if(visitor.getFromId() == MARIO_TOP_DETECT && dynamic_cast<MarioVisitor&>(visitor).canDestroy()) {
if ( visitor.getFromId() == MARIO_TOP_DETECT &&
dynamic_cast< MarioVisitor & >( visitor ).canDestroy() ) {
// TODO if big mario and _can_be_destroyed
if( _destructible ) {
if ( _destructible && !hasCoin() ) {
destroy();
} else {
BounceVisitor bv;
bv.setVisitorType(VisitorType::Terrain);
bv.setVisitorType( VisitorType::Terrain );
setPos(getPos() - SDLPP::Vec2D<double>(0, BLOCK_SIZE));
if(getCollisions().size() < 2)
addCollision(SDLPP::RectColider(0.1, 0.1, 0.8, 0.8, 69));
setPos( getPos() - SDLPP::Vec2D< double >( 0, BLOCK_SIZE ) );
if ( getCollisions().size() < 2 )
addCollision( SDLPP::RectColider( 0.1, 0.1, 0.8, 0.8, 69 ) );
updateSizeAndPosition();
g_playground->visitCollisions(*this, bv);
setPos(getPos() + SDLPP::Vec2D<double>(0, BLOCK_SIZE));
g_playground->visitCollisions( *this, bv );
setPos( getPos() + SDLPP::Vec2D< double >( 0, BLOCK_SIZE ) );
updateSizeAndPosition();
if(bv.canBounce())
if ( bv.canBounce() )
bounce();
}
if ( hasCoin() ) {
removeCoin();
dynamic_cast< MarioVisitor & >( visitor ).setCoin();
}
}
#endif
visitor.visit( *this );
@@ -60,38 +71,85 @@ void MarioBlock::setTerrain( bool terrain ) {
}
void MarioBlock::bounce() {
if(_bouncing)
if ( _bouncing )
return;
_bouncing = true;
og_pos = getPos();
setMovement(0, -0.5);
setMovement( 0, -0.5 );
}
void MarioBlock::custom_move(int ticks) {
if(!_bouncing)
void MarioBlock::custom_move( int ticks ) {
if ( !_bouncing )
return;
if(getMovement().getY() < 0) {
if ( getMovement().getY() < 0 ) {
ticks_to_bounce -= ticks;
if(ticks_to_bounce < 0) {
setMovement(0, 0.5);
if ( ticks_to_bounce < 0 ) {
setMovement( 0, 0.5 );
ticks_to_bounce = bounce_ticks;
}
} else {
if(getPos().getY() >= og_pos.getY()) {
setMovement(0, 0);
setPos(getPos().getX(), og_pos.getY());
if ( getPos().getY() >= og_pos.getY() ) {
setMovement( 0, 0 );
setPos( getPos().getX(), og_pos.getY() );
_bouncing = false;
}
}
}
void MarioBlock::setType(LandType::Value type) {
void MarioBlock::setType( LandType::Value type ) {
_type = type;
setWorldTypeSrc( _type );
}
LandType::Value MarioBlock::getType() const {
return _type;
}
bool MarioBlock::hasCoin() {
return _coins > 0;
}
bool MarioBlock::hasMushroom() {
return _mushroom;
}
void MarioBlock::removeCoin() {
_coins--;
}
void MarioBlock::removeMushroom() {
_mushroom = false;
}
void MarioBlock::setCoinCount( int coins ) {
_coins = coins;
}
void MarioBlock::setDestructible( bool destructible ) {
_destructible = destructible;
}
void MarioBlock::ensureCollision() {
if ( getCollisions().size() == 0 ) {
addCollision( SDLPP::RectColider( 0, 0, 1, 1 ) );
}
}
void MarioBlock::setWorldTypeSrc( LandType::Value world ) {
auto rect = getTextureSourceRect();
switch ( world ) {
case LandType::OVERWORLD:
rect.x += OVERWORLD_SHIFT.getX();
rect.y += OVERWORLD_SHIFT.getY();
break;
case LandType::UNDERWORLD:
rect.x += UNDERWORLD_SHIFT.getX();
rect.y += UNDERWORLD_SHIFT.getY();
break;
case LandType::WATER:
rect.x += WATER_SHIFT.getX();
rect.y += WATER_SHIFT.getY();
break;
case LandType::BOWSER:
rect.x += BOWSER_SHIFT.getX();
rect.y += BOWSER_SHIFT.getY();
break;
}
setTextureSourceRect( rect );
}
const std::vector< uint64_t > possibleBlocks = {
FLOOR_ID,
STEP_ID,
@@ -165,10 +223,7 @@ const std::vector< uint64_t > possibleCharacters = {
};
const std::vector< LandType::Value > possibleLands = {
LandType::OVERWORLD,
LandType::UNDERWORLD,
LandType::WATER,
LandType::BOWSER
LandType::OVERWORLD, LandType::UNDERWORLD, LandType::WATER, LandType::BOWSER
};
const std::unordered_map< uint64_t, const SDL_Rect * > block_mapping = {
@@ -301,37 +356,306 @@ const std::unordered_map< uint64_t, uint64_t > block_flags = {
{ BACKGROUND_MODIFIER_ID, 0 },
};
bool blockCanBeDestroyed(uint64_t id) {
auto it = block_flags.find(id);
if(it == block_flags.end())
bool blockCanBeDestroyed( uint64_t id ) {
auto it = block_flags.find( id );
if ( it == block_flags.end() )
return false;
return it->second & CAN_BE_DESTROYED_FLAG;
}
bool blockHasCollision(uint64_t id) {
auto it = block_flags.find(id);
if(it == block_flags.end()) {
bool blockHasCollision( uint64_t id ) {
auto it = block_flags.find( id );
if ( it == block_flags.end() ) {
return false;
}
return it->second & HAS_COLLISION;
}
std::shared_ptr< SDLPP::RectangleRender >
createBlock( std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y,
std::shared_ptr< SDLPP::Texture > &texture, const SDL_Rect &src,
uint64_t id, LandType::Value land_type, bool destructible, bool editor ) {
auto can_destroy = blockCanBeDestroyed(id);
auto collision = blockHasCollision(id);
if(editor) {
collision = true;
std::shared_ptr< MarioBlock >
createBlockById( uint64_t id, int x, int y,
std::shared_ptr< SDLPP::Renderer > &renderer ) {
std::shared_ptr< MarioBlock > result = nullptr;
switch ( id ) {
case FLOOR_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< FloorBlock >( x, y, renderer ) );
break;
case HILL_INCLINE_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillInclineBlock >( x, y, renderer ) );
break;
case HILL_DECLINE_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillDeclineBlock >( x, y, renderer ) );
break;
case HILL_DOTS_RIGHT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillDotsRightBlock >( x, y, renderer ) );
break;
case HILL_DOTS_LEFT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillDotsLeftBlock >( x, y, renderer ) );
break;
case HILL_FILL_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillFillBlock >( x, y, renderer ) );
break;
case HILL_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< HillTopBlock >( x, y, renderer ) );
break;
case BUSH_LEFT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< BushLeftBlock >( x, y, renderer ) );
break;
case BUSH_MIDDLE_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< BushMiddleBlock >( x, y, renderer ) );
break;
case BUSH_RIGHT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< BushRightBlock >( x, y, renderer ) );
break;
case CLOUD_LEFT_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudLeftBottomBlock >( x, y, renderer ) );
break;
case CLOUD_MIDDLE_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudMiddleBottomBlock >( x, y, renderer ) );
break;
case CLOUD_RIGHT_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudRightBottomBlock >( x, y, renderer ) );
break;
case CLOUD_LEFT_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudLeftTopBlock >( x, y, renderer ) );
break;
case CLOUD_MIDDLE_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudMiddleTopBlock >( x, y, renderer ) );
break;
case CLOUD_RIGHT_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CloudRightTopBlock >( x, y, renderer ) );
break;
case PIPE_LEFT_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PipeLeftBottomBlock >( x, y, renderer ) );
break;
case PIPE_RIGHT_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PipeRightBottomBlock >( x, y, renderer ) );
break;
case PIPE_LEFT_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PipeLeftTopBlock >( x, y, renderer ) );
break;
case PIPE_RIGHT_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PipeRightTopBlock >( x, y, renderer ) );
break;
case CASTLE_LEFT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleLeftBlock >( x, y, renderer ) );
break;
case CASTLE_RIGHT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleRightBlock >( x, y, renderer ) );
break;
case CASTLE_BLACK_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleBlackBlock >( x, y, renderer ) );
break;
case CASTLE_ENTRY_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleEntryBlock >( x, y, renderer ) );
break;
case CASTLE_TOWER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleTowerBlock >( x, y, renderer ) );
break;
case CASTLE_TOWER_FILLED_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CastleTowerFilledBlock >( x, y, renderer ) );
break;
case VINE_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< VineTopBlock >( x, y, renderer ) );
break;
case VINE_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< VineBottomBlock >( x, y, renderer ) );
break;
case POLE_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PoleTopBlock >( x, y, renderer ) );
break;
case POLE_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< PoleBottomBlock >( x, y, renderer ) );
break;
case FLAG_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< FlagBlock >( x, y, renderer ) );
break;
case STEP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< StepBlock >( x, y, renderer ) );
break;
case BRICK_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< BrickBlock >( x, y, renderer ) );
break;
case BRICK_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< BrickTopBlock >( x, y, renderer ) );
break;
case SIDEWAY_PIPE_END_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeEndTopBlock >( x, y, renderer ) );
break;
case SIDEWAY_PIPE_END_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeEndBottomBlock >( x, y, renderer ) );
break;
case SIDEWAY_PIPE_MIDDLE_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeMiddleTopBlock >( x, y, renderer ) );
break;
case SIDEWAY_PIPE_MIDDLE_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeMiddleBottomBlock >( x, y,
renderer ) );
break;
case SIDEWAY_PIPE_CONNECTOR_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeConnectorTopBlock >( x, y,
renderer ) );
break;
case SIDEWAY_PIPE_CONNECTOR_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< SidewayPipeConnectorBottomBlock >( x, y,
renderer ) );
break;
case TREE_PLATFORM_TOP_LEFT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreePlatformTopLeftBlock >( x, y, renderer ) );
break;
case TREE_PLATFORM_TOP_MIDDLE_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreePlatformTopMiddleBlock >( x, y, renderer ) );
break;
case TREE_PLATFORM_TOP_RIGHT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreePlatformTopRightBlock >( x, y, renderer ) );
break;
case TREE_PLATFORM_BARK_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreePlatformBarkBlock >( x, y, renderer ) );
break;
case WATER_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< WaterTopBlock >( x, y, renderer ) );
break;
case WATER_FILL_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< WaterFillBlock >( x, y, renderer ) );
break;
case MUSHROOM_PLATFORM_TOP_LEFT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< MushroomPlatformTopLeftBlock >( x, y,
renderer ) );
break;
case MUSHROOM_PLATFORM_TOP_MIDDLE_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< MushroomPlatformTopMiddleBlock >( x, y,
renderer ) );
break;
case MUSHROOM_PLATFORM_TOP_RIGHT_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< MushroomPlatformTopRightBlock >( x, y,
renderer ) );
break;
case MUSHROOM_PLATFORM_BARK_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< MushroomPlatformBarkTopBlock >( x, y,
renderer ) );
break;
case MUSHROOM_PLATFORM_BARK_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< MushroomPlatformBarkBottomBlock >( x, y,
renderer ) );
break;
case TREE_BARK_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreeBarkBlock >( x, y, renderer ) );
break;
case TREE_LEAVES_SMALL_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreeLeavesSmallBlock >( x, y, renderer ) );
break;
case TREE_LEAVES_TOP_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreeLeavesTopBlock >( x, y, renderer ) );
break;
case TREE_LEAVES_BOTTOM_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< TreeLeavesBottomBlock >( x, y, renderer ) );
break;
case CANNON_TOWER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CannonTowerBlock >( x, y, renderer ) );
break;
case CANNON_PEDESTAL_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CannonPedestalBlock >( x, y, renderer ) );
break;
case CANNON_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared< CannonBlock >( x, y, renderer ) );
break;
case MARIO_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared<Mario>(x,y,renderer));
break;
case DESTRUCTIBLE_MODIFIER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared<DestructibleModifierBlock>(x,y,renderer));
break;
case BACKGROUND_MODIFIER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared<BackgroundModifierBlock>(x,y,renderer));
break;
case COIN_MODIFIER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared<CoinEditorBlock>(x,y,renderer));
break;
case MUSHROOM_MODIFIER_ID:
result = std::static_pointer_cast< MarioBlock >(
std::make_shared<MushroomModifierBlock>(x,y,renderer));
break;
}
return result;
}
std::shared_ptr< MarioBlock >
createBlock( std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y,
uint64_t id, LandType::Value land_type, bool destructible,
bool editor ) {
auto block = createBlockById( id, x, y, renderer );
if(block == nullptr) {
return nullptr;
}
auto block = std::make_shared< MarioBlock >( x, y, renderer, texture, src, can_destroy, destructible );
block->setId( id );
block->setAlignment( SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER );
block->setStatic();
block->setType(land_type);
if ( collision ) {
block->addCollision( SDLPP::RectColider( 0, 0, 1, 1 ) );
block->setType( land_type );
if(destructible) {
block->setDestructible();
}
if ( editor ) {
block->ensureCollision();
}
return block;
}
@@ -361,47 +685,32 @@ SDL_Rect getSourceRectByID( uint64_t id, LandType::Value type ) {
}
return ret_src;
}
std::shared_ptr< SDLPP::RectangleRender >
createTerrainBlock( uint64_t block_id, LandType::Value type,
std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y,
std::shared_ptr< SDLPP::Texture > texture,
bool destructible, bool editor ) {
return createBlock( renderer, x, y, texture,
getSourceRectByID( block_id, type ), block_id, type,
destructible, editor );
}
std::shared_ptr< SDLPP::RectangleRender >
createTerrainBlock( uint64_t block_id, LandType::Value type,
std::shared_ptr< SDLPP::Renderer > &renderer,
std::shared_ptr< SDLPP::Texture > texture,
bool destructible, bool editor ) {
return createTerrainBlock( block_id, type, renderer, 0, 0, texture,
destructible, editor );
}
std::shared_ptr< SDLPP::RectangleRender >
// TODO coin count
std::shared_ptr< MarioBlock >
createTerrainBlock( uint64_t block_id, LandType::Value type,
std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y,
bool destructible, bool editor ) {
return createTerrainBlock( block_id, type, renderer, x, y,
g_terrain_texture, destructible, editor );
return createBlock( renderer, x, y, block_id, type, destructible, editor );
}
std::shared_ptr< SDLPP::RectangleRender >
std::shared_ptr< MarioBlock >
createTerrainBlock( uint64_t block_id, LandType::Value type,
std::shared_ptr< SDLPP::Renderer > &renderer,
bool destructible, bool editor ) {
return createTerrainBlock( block_id, type, renderer, g_terrain_texture,
destructible, editor );
return createTerrainBlock( block_id, type, renderer, 0, 0, destructible,
editor );
}
std::shared_ptr< SDLPP::RectangleRender >
std::shared_ptr< MarioBlock >
createMario( LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer,
int x, int y ) {
int x, int y, bool editor ) {
// TODO add type additions
auto mario = createBlock( renderer, x, y, g_mario_texture,
MARIO_STANDING_SRC, MARIO_ID, type, false, true );
dynamic_cast< MarioBlock & >( *mario ).setTerrain( false );
auto mario = createBlock(renderer, x, y, MARIO_ID, type, false, true);
if(editor) {
mario->setTerrain( false );
mario->removeCollisions();
mario->ensureCollision();
}
return mario;
}