From 243c1d9d04c7cff8e3c98c15067c7a8c794a05b3 Mon Sep 17 00:00:00 2001 From: zvon Date: Mon, 31 May 2021 18:54:59 +0200 Subject: [PATCH] Mario: add a dictionary of flags for each block --- mario/blocks.cpp | 122 ++++++++++++++++++++++++++++++++++------ mario/blocks.hpp | 11 ++-- mario/editor.cpp | 10 ++-- mario/mario_visitor.cpp | 22 +++++++- 4 files changed, 137 insertions(+), 28 deletions(-) diff --git a/mario/blocks.cpp b/mario/blocks.cpp index 1074209..0eff04b 100644 --- a/mario/blocks.cpp +++ b/mario/blocks.cpp @@ -6,13 +6,17 @@ #include #include "mario_visitor.hpp" +#define CAN_BE_DESTROYED_FLAG 0x0000000000000001 +#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 destructible ) + 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 ) { - _destructible = destructible; + _can_be_destroyed = can_be_destroyed; + _destructible = can_be_destroyed && destructible; setMovementSpeed(1); } void MarioBlock::visit( SDLPP::Visitor &visitor ) { @@ -27,6 +31,7 @@ void MarioBlock::visit( SDLPP::Visitor &visitor ) { } #else if(visitor.getFromId() == MARIO_TOP_DETECT && dynamic_cast(visitor).canDestroy()) { + // TODO if big mario and _can_be_destroyed if( _destructible ) { destroy(); } else { @@ -226,24 +231,109 @@ const std::unordered_map< uint64_t, const SDL_Rect * > block_mapping = { { DESTRUCTIBLE_ID, &DESTRUCTIBLE_SRC }, }; +const std::unordered_map< uint64_t, uint64_t > block_flags = { + { FLOOR_ID, CAN_BE_DESTROYED_FLAG | HAS_COLLISION }, + { HILL_INCLINE_ID, 0 }, + { HILL_DECLINE_ID, 0 }, + { HILL_DOTS_RIGHT_ID, 0 }, + { HILL_DOTS_LEFT_ID, 0 }, + { HILL_FILL_ID, 0 }, + { HILL_TOP_ID, 0 }, + { BUSH_LEFT_ID, 0 }, + { BUSH_MIDDLE_ID, 0 }, + { BUSH_RIGHT_ID, 0 }, + { CLOUD_LEFT_BOTTOM_ID, 0 }, + { CLOUD_MIDDLE_BOTTOM_ID, 0 }, + { CLOUD_RIGHT_BOTTOM_ID, 0 }, + { CLOUD_LEFT_TOP_ID, 0 }, + { CLOUD_MIDDLE_TOP_ID, 0 }, + { CLOUD_RIGHT_TOP_ID, 0 }, + { PIPE_LEFT_BOTTOM_ID, HAS_COLLISION }, + { PIPE_LEFT_TOP_ID, HAS_COLLISION }, + { PIPE_RIGHT_BOTTOM_ID, HAS_COLLISION }, + { PIPE_RIGHT_TOP_ID, HAS_COLLISION }, + { CASTLE_LEFT_ID, 0 }, + { CASTLE_RIGHT_ID, 0 }, + { CASTLE_BLACK_ID, 0 }, + { CASTLE_ENTRY_ID, 0 }, + { CASTLE_TOWER_ID, 0 }, + { CASTLE_TOWER_FILLED_ID, 0 }, + { VINE_TOP_ID, HAS_COLLISION }, + { VINE_BOTTOM_ID, HAS_COLLISION }, + { POLE_TOP_ID, HAS_COLLISION }, + { POLE_BOTTOM_ID, HAS_COLLISION }, + { FLAG_ID, 0 }, + { STEP_ID, CAN_BE_DESTROYED_FLAG | HAS_COLLISION }, + { BRICK_ID, 0 }, + { BRICK_TOP_ID, 0 }, + { SIDEWAY_PIPE_END_TOP_ID, HAS_COLLISION }, + { SIDEWAY_PIPE_END_BOTTOM_ID, HAS_COLLISION }, + { SIDEWAY_PIPE_MIDDLE_TOP_ID, HAS_COLLISION }, + { SIDEWAY_PIPE_MIDDLE_BOTTOM_ID, HAS_COLLISION }, + { SIDEWAY_PIPE_CONNECTOR_TOP_ID, HAS_COLLISION }, + { SIDEWAY_PIPE_CONNECTOR_BOTTOM_ID, HAS_COLLISION }, + { TREE_PLATFORM_TOP_LEFT_ID, HAS_COLLISION }, + { TREE_PLATFORM_TOP_MIDDLE_ID, HAS_COLLISION }, + { TREE_PLATFORM_TOP_RIGHT_ID, HAS_COLLISION }, + { TREE_PLATFORM_BARK_ID, HAS_COLLISION }, + { WATER_TOP_ID, HAS_COLLISION }, + { WATER_FILL_ID, HAS_COLLISION }, + { MUSHROOM_PLATFORM_TOP_LEFT_ID, HAS_COLLISION }, + { MUSHROOM_PLATFORM_TOP_MIDDLE_ID, HAS_COLLISION }, + { MUSHROOM_PLATFORM_TOP_RIGHT_ID, HAS_COLLISION }, + { MUSHROOM_PLATFORM_BARK_TOP_ID, HAS_COLLISION }, + { MUSHROOM_PLATFORM_BARK_BOTTOM_ID, HAS_COLLISION }, + { TREE_BARK_ID, HAS_COLLISION }, + { TREE_LEAVES_SMALL_ID, HAS_COLLISION }, + { TREE_LEAVES_TOP_ID, HAS_COLLISION }, + { TREE_LEAVES_BOTTOM_ID, HAS_COLLISION }, + { CANNON_TOWER_ID, HAS_COLLISION }, + { CANNON_PEDESTAL_ID, HAS_COLLISION }, + { CANNON_ID, HAS_COLLISION }, + { MARIO_ID, 0 }, + { DESTRUCTIBLE_ID, 0 }, +}; + +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()) { + 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 collision = false, bool destructible = false ) { - auto block = std::make_shared< MarioBlock >( x, y, renderer, texture, src, destructible ); + uint64_t id, LandType::Value land_type, bool destructible, bool editor ) { + auto can_destroy = blockCanBeDestroyed(id); + auto collision = blockHasCollision(id); + if(editor) { + collision = true; + } + 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 ) + if ( collision ) { block->addCollision( SDLPP::RectColider( 0, 0, 1, 1 ) ); + } return block; } SDL_Rect getSourceRectByID( uint64_t id, LandType::Value type ) { - if ( block_mapping.find( id ) == block_mapping.end() ) + auto mapping = block_mapping.find( id ); + if ( mapping == block_mapping.end() ) return {}; - SDL_Rect ret_src = *block_mapping.at( id ); + SDL_Rect ret_src = *mapping->second; switch ( type ) { case LandType::OVERWORLD: ret_src.x += OVERWORLD_SHIFT.getX(); @@ -268,34 +358,34 @@ 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 collision, bool destructible ) { + bool destructible, bool editor ) { return createBlock( renderer, x, y, texture, getSourceRectByID( block_id, type ), block_id, type, - collision, destructible ); + 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 collision, bool destructible ) { + bool destructible, bool editor ) { return createTerrainBlock( block_id, type, renderer, 0, 0, texture, - collision, destructible ); + destructible, editor ); } std::shared_ptr< SDLPP::RectangleRender > createTerrainBlock( uint64_t block_id, LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y, - bool collision, bool destructible ) { + bool destructible, bool editor ) { return createTerrainBlock( block_id, type, renderer, x, y, - g_terrain_texture, collision, destructible ); + g_terrain_texture, destructible, editor ); } std::shared_ptr< SDLPP::RectangleRender > createTerrainBlock( uint64_t block_id, LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, - bool collision, bool destructible ) { + bool destructible, bool editor ) { return createTerrainBlock( block_id, type, renderer, g_terrain_texture, - collision, destructible ); + destructible, editor ); } std::shared_ptr< SDLPP::RectangleRender > @@ -303,7 +393,7 @@ createMario( LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y ) { // TODO add type additions auto mario = createBlock( renderer, x, y, g_mario_texture, - MARIO_STANDING_SRC, MARIO_ID, type, true ); + MARIO_STANDING_SRC, MARIO_ID, type, false, true ); dynamic_cast< MarioBlock & >( *mario ).setTerrain( false ); return mario; } diff --git a/mario/blocks.hpp b/mario/blocks.hpp index 6602a41..a353c86 100644 --- a/mario/blocks.hpp +++ b/mario/blocks.hpp @@ -11,7 +11,7 @@ struct LandType { class MarioBlock : public SDLPP::RectangleRender { public: MarioBlock( int x, int y, std::shared_ptr< SDLPP::Renderer > renderer, - std::shared_ptr< SDLPP::Texture > texture, SDL_Rect src, bool destructible = false ); + std::shared_ptr< SDLPP::Texture > texture, SDL_Rect src, bool can_be_destroyed = false, bool destructible = false ); void visit( SDLPP::Visitor &visitor ) override; void setTool( bool tool = true ); void setTerrain( bool terrain = true ); @@ -24,6 +24,7 @@ private: bool _tool = false; bool _terrain = true; bool _destructible = false; + bool _can_be_destroyed = false; bool _bouncing = false; const int bounce_ticks = 100; int ticks_to_bounce = bounce_ticks; @@ -48,21 +49,21 @@ struct BlockRole { std::shared_ptr< SDLPP::RectangleRender > createTerrainBlock( uint64_t block_id, LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, - bool collision = false, bool destructible = false ); + bool destructible = false, bool editor = false ); std::shared_ptr< SDLPP::RectangleRender > createTerrainBlock( uint64_t block_id, LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y, - bool collision = false, bool destructible = false ); + bool destructible = false, bool editor = false ); 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 collision = false, bool destructible = false ); + bool destructible = false, bool editor = false ); 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 collision = false, bool destructible = false ); + bool destructible = false, bool editor = false ); std::shared_ptr< SDLPP::RectangleRender > createMario( LandType::Value type, std::shared_ptr< SDLPP::Renderer > &renderer, int x, int y ); diff --git a/mario/editor.cpp b/mario/editor.cpp index 29628a9..04b3aeb 100644 --- a/mario/editor.cpp +++ b/mario/editor.cpp @@ -593,7 +593,7 @@ void placeTool( SDLPP::Scene &scene ) { createTerrainBlock( global_vars.current_tool->getId(), global_vars.current_world_type, renderer, global_vars.mouse.edit_box.getX(), - global_vars.mouse.edit_box.getY(), true ); + global_vars.mouse.edit_box.getY(), false, true ); new_obj->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); break; case VisitorType::Modifier: @@ -623,7 +623,7 @@ void placeTool( SDLPP::Scene &scene ) { global_vars.current_world_type, renderer, global_vars.mouse.edit_box.getX(), global_vars.mouse.edit_box.getY(), - global_vars.translucent_terrain_texture, true ); + global_vars.translucent_terrain_texture, false, true ); new_obj->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); // TODO createModifierBlock dynamic_cast< MarioBlock * >( new_obj.get() ) @@ -813,7 +813,7 @@ void populateToolGrid( case ToolType::BLOCK: case ToolType::MOD: tool_store.push_back( createTerrainBlock( - block, global_vars.current_world_type, renderer, false ) ); + block, global_vars.current_world_type, renderer, false, true ) ); default: break; } @@ -860,7 +860,7 @@ void populateWorldType( } int tool_index = 0; for ( auto &type : possibleLands ) { - auto land = createTerrainBlock( BRICK_ID, type, renderer, false ); + auto land = createTerrainBlock( BRICK_ID, type, renderer, false, true ); auto x = tool_index % count_x; auto y = tool_index / count_x; land->setId( EDITOR_WORLD_CHANGE_ID ); @@ -917,7 +917,6 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, #else int main() { #endif - // TODO the code setting up UI is terrible, terrible mess, make it cleaner SDLPP::init(); SDLPP::Window w( "Mario editor!" ); w.setResizable( true ); @@ -1043,6 +1042,7 @@ int main() { global_vars.current_tool = createTerrainBlock( possibleBlocks[global_vars.tool.index], global_vars.current_world_type, renderer, global_vars.translucent_terrain_texture, false ); + global_vars.current_tool->removeCollisions(); global_vars.current_tool->addCollision( SDLPP::RectColider( 0.1, 0.1, 0.8, 0.8 ) ); dynamic_cast< MarioBlock & >( *global_vars.current_tool ).setTool(); diff --git a/mario/mario_visitor.cpp b/mario/mario_visitor.cpp index f204f38..9df0cd7 100644 --- a/mario/mario_visitor.cpp +++ b/mario/mario_visitor.cpp @@ -1,13 +1,31 @@ #include "mario_visitor.hpp" #include "../sdlpp/sdlpp_renderobject.hpp" #include "objectids.hpp" +#include "sprites.hpp" void MarioVisitor::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 == MARIO_FLOOR_DETECT ) { onGround = true; groundY = obj.getPos().getY();