#include "blocks.hpp" #include "global_vars.hpp" #include "objectids.hpp" #include "sprites.hpp" #include "editor_visitor.hpp" #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 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); } void MarioBlock::visit( SDLPP::Visitor &visitor ) { #ifdef EDITOR if ( !_tool && _terrain && visitor.getVisitorType() == VisitorType::Terrain ) { destroy(); } if ( !_tool && !_terrain && visitor.getVisitorType() == VisitorType::Modifier ) { destroy(); } #else if(visitor.getFromId() == MARIO_TOP_DETECT && dynamic_cast(visitor).canDestroy()) { // TODO if big mario and _can_be_destroyed if( _destructible ) { destroy(); } else { BounceVisitor bv; bv.setVisitorType(VisitorType::Terrain); setPos(getPos() - SDLPP::Vec2D(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(0, BLOCK_SIZE)); updateSizeAndPosition(); if(bv.canBounce()) bounce(); } } #endif visitor.visit( *this ); } void MarioBlock::setTool( bool tool ) { _tool = tool; } void MarioBlock::setTerrain( bool terrain ) { _terrain = terrain; } void MarioBlock::bounce() { if(_bouncing) return; _bouncing = true; og_pos = getPos(); setMovement(0, -0.5); } void MarioBlock::custom_move(int ticks) { if(!_bouncing) return; if(getMovement().getY() < 0) { ticks_to_bounce -= ticks; 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()); _bouncing = false; } } } void MarioBlock::setType(LandType::Value type) { _type = type; } LandType::Value MarioBlock::getType() const { return _type; } const std::vector< uint64_t > possibleBlocks = { FLOOR_ID, STEP_ID, HILL_TOP_ID, HILL_DOTS_LEFT_ID, HILL_FILL_ID, HILL_INCLINE_ID, HILL_DOTS_RIGHT_ID, HILL_DECLINE_ID, CLOUD_LEFT_TOP_ID, CLOUD_MIDDLE_TOP_ID, CLOUD_RIGHT_TOP_ID, VINE_TOP_ID, CLOUD_LEFT_BOTTOM_ID, CLOUD_MIDDLE_BOTTOM_ID, CLOUD_RIGHT_BOTTOM_ID, VINE_BOTTOM_ID, BRICK_TOP_ID, BRICK_ID, FLAG_ID, WATER_TOP_ID, BUSH_LEFT_ID, BUSH_MIDDLE_ID, BUSH_RIGHT_ID, WATER_FILL_ID, PIPE_LEFT_TOP_ID, PIPE_RIGHT_TOP_ID, CASTLE_TOWER_ID, CASTLE_TOWER_FILLED_ID, PIPE_LEFT_BOTTOM_ID, PIPE_RIGHT_BOTTOM_ID, CASTLE_LEFT_ID, CASTLE_RIGHT_ID, POLE_TOP_ID, CASTLE_ENTRY_ID, SIDEWAY_PIPE_END_TOP_ID, SIDEWAY_PIPE_MIDDLE_TOP_ID, POLE_BOTTOM_ID, CASTLE_BLACK_ID, SIDEWAY_PIPE_END_BOTTOM_ID, SIDEWAY_PIPE_MIDDLE_BOTTOM_ID, SIDEWAY_PIPE_CONNECTOR_TOP_ID, TREE_PLATFORM_TOP_LEFT_ID, TREE_PLATFORM_TOP_MIDDLE_ID, TREE_PLATFORM_TOP_RIGHT_ID, SIDEWAY_PIPE_CONNECTOR_BOTTOM_ID, MUSHROOM_PLATFORM_TOP_LEFT_ID, MUSHROOM_PLATFORM_TOP_MIDDLE_ID, MUSHROOM_PLATFORM_TOP_RIGHT_ID, TREE_PLATFORM_BARK_ID, MUSHROOM_PLATFORM_BARK_TOP_ID, TREE_LEAVES_TOP_ID, TREE_LEAVES_SMALL_ID, CANNON_TOWER_ID, MUSHROOM_PLATFORM_BARK_BOTTOM_ID, TREE_LEAVES_BOTTOM_ID, TREE_BARK_ID, CANNON_PEDESTAL_ID, CANNON_ID, }; const std::vector< uint64_t > possibleMods = { DESTRUCTIBLE_MODIFIER_ID, BACKGROUND_MODIFIER_ID, }; const std::vector< uint64_t > possibleCharacters = { MARIO_ID, }; const std::vector< LandType::Value > possibleLands = { LandType::OVERWORLD, LandType::UNDERWORLD, LandType::WATER, LandType::BOWSER }; const std::unordered_map< uint64_t, const SDL_Rect * > block_mapping = { { FLOOR_ID, &FLOOR_SRC }, { HILL_INCLINE_ID, &HILL_INCLINE_SRC }, { HILL_DECLINE_ID, &HILL_DECLINE_SRC }, { HILL_DOTS_RIGHT_ID, &HILL_DOTS_RIGHT_SRC }, { HILL_DOTS_LEFT_ID, &HILL_DOTS_LEFT_SRC }, { HILL_FILL_ID, &HILL_FILL_SRC }, { HILL_TOP_ID, &HILL_TOP_SRC }, { BUSH_LEFT_ID, &BUSH_LEFT_SRC }, { BUSH_MIDDLE_ID, &BUSH_MIDDLE_SRC }, { BUSH_RIGHT_ID, &BUSH_RIGHT_SRC }, { CLOUD_LEFT_BOTTOM_ID, &CLOUD_LEFT_BOTTOM_SRC }, { CLOUD_MIDDLE_BOTTOM_ID, &CLOUD_MIDDLE_BOTTOM_SRC }, { CLOUD_RIGHT_BOTTOM_ID, &CLOUD_RIGHT_BOTTOM_SRC }, { CLOUD_LEFT_TOP_ID, &CLOUD_LEFT_TOP_SRC }, { CLOUD_MIDDLE_TOP_ID, &CLOUD_MIDDLE_TOP_SRC }, { CLOUD_RIGHT_TOP_ID, &CLOUD_RIGHT_TOP_SRC }, { PIPE_LEFT_BOTTOM_ID, &PIPE_LEFT_BOTTOM_SRC }, { PIPE_LEFT_TOP_ID, &PIPE_LEFT_TOP_SRC }, { PIPE_RIGHT_BOTTOM_ID, &PIPE_RIGHT_BOTTOM_SRC }, { PIPE_RIGHT_TOP_ID, &PIPE_RIGHT_TOP_SRC }, { CASTLE_LEFT_ID, &CASTLE_LEFT_SRC }, { CASTLE_RIGHT_ID, &CASTLE_RIGHT_SRC }, { CASTLE_BLACK_ID, &CASTLE_BLACK_SRC }, { CASTLE_ENTRY_ID, &CASTLE_ENTRY_SRC }, { CASTLE_TOWER_ID, &CASTLE_TOWER_SRC }, { CASTLE_TOWER_FILLED_ID, &CASTLE_TOWER_FILLED_SRC }, { VINE_TOP_ID, &VINE_TOP_SRC }, { VINE_BOTTOM_ID, &VINE_BOTTOM_SRC }, { POLE_TOP_ID, &POLE_TOP_SRC }, { POLE_BOTTOM_ID, &POLE_BOTTOM_SRC }, { FLAG_ID, &FLAG_SRC }, { STEP_ID, &STEP_SRC }, { BRICK_ID, &BRICK_SRC }, { BRICK_TOP_ID, &BRICK_TOP_SRC }, { SIDEWAY_PIPE_END_TOP_ID, &SIDEWAY_PIPE_END_TOP_SRC }, { SIDEWAY_PIPE_END_BOTTOM_ID, &SIDEWAY_PIPE_END_BOTTOM_SRC }, { SIDEWAY_PIPE_MIDDLE_TOP_ID, &SIDEWAY_PIPE_MIDDLE_TOP_SRC }, { SIDEWAY_PIPE_MIDDLE_BOTTOM_ID, &SIDEWAY_PIPE_MIDDLE_BOTTOM_SRC }, { SIDEWAY_PIPE_CONNECTOR_TOP_ID, &SIDEWAY_PIPE_CONNECTOR_TOP_SRC }, { SIDEWAY_PIPE_CONNECTOR_BOTTOM_ID, &SIDEWAY_PIPE_CONNECTOR_BOTTOM_SRC }, { TREE_PLATFORM_TOP_LEFT_ID, &TREE_PLATFORM_TOP_LEFT_SRC }, { TREE_PLATFORM_TOP_MIDDLE_ID, &TREE_PLATFORM_TOP_MIDDLE_SRC }, { TREE_PLATFORM_TOP_RIGHT_ID, &TREE_PLATFORM_TOP_RIGHT_SRC }, { TREE_PLATFORM_BARK_ID, &TREE_PLATFORM_BARK_SRC }, { WATER_TOP_ID, &WATER_TOP_SRC }, { WATER_FILL_ID, &WATER_FILL_SRC }, { MUSHROOM_PLATFORM_TOP_LEFT_ID, &MUSHROOM_PLATFORM_TOP_LEFT_SRC }, { MUSHROOM_PLATFORM_TOP_MIDDLE_ID, &MUSHROOM_PLATFORM_TOP_MIDDLE_SRC }, { MUSHROOM_PLATFORM_TOP_RIGHT_ID, &MUSHROOM_PLATFORM_TOP_RIGHT_SRC }, { MUSHROOM_PLATFORM_BARK_TOP_ID, &MUSHROOM_PLATFORM_BARK_TOP_SRC }, { MUSHROOM_PLATFORM_BARK_BOTTOM_ID, &MUSHROOM_PLATFORM_BARK_BOTTOM_SRC }, { TREE_BARK_ID, &TREE_BARK_SRC }, { TREE_LEAVES_SMALL_ID, &TREE_LEAVES_SMALL_SRC }, { TREE_LEAVES_TOP_ID, &TREE_LEAVES_TOP_SRC }, { TREE_LEAVES_BOTTOM_ID, &TREE_LEAVES_BOTTOM_SRC }, { CANNON_TOWER_ID, &CANNON_TOWER_SRC }, { CANNON_PEDESTAL_ID, &CANNON_PEDESTAL_SRC }, { CANNON_ID, &CANNON_SRC }, { MARIO_ID, &MARIO_STANDING_SRC }, { DESTRUCTIBLE_MODIFIER_ID, &DESTRUCTIBLE_SRC }, { BACKGROUND_MODIFIER_ID, &BACKGROUND_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, CAN_BE_DESTROYED_FLAG | HAS_COLLISION }, { BRICK_TOP_ID, CAN_BE_DESTROYED_FLAG | HAS_COLLISION }, { 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_MODIFIER_ID, 0 }, { BACKGROUND_MODIFIER_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 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 ) { block->addCollision( SDLPP::RectColider( 0, 0, 1, 1 ) ); } return block; } SDL_Rect getSourceRectByID( uint64_t id, LandType::Value type ) { auto mapping = block_mapping.find( id ); if ( mapping == block_mapping.end() ) return {}; SDL_Rect ret_src = *mapping->second; switch ( type ) { case LandType::OVERWORLD: ret_src.x += OVERWORLD_SHIFT.getX(); ret_src.y += OVERWORLD_SHIFT.getY(); break; case LandType::UNDERWORLD: ret_src.x += UNDERWORLD_SHIFT.getX(); ret_src.y += UNDERWORLD_SHIFT.getY(); break; case LandType::WATER: ret_src.x += WATER_SHIFT.getX(); ret_src.y += WATER_SHIFT.getY(); break; case LandType::BOWSER: ret_src.x += BOWSER_SHIFT.getX(); ret_src.y += BOWSER_SHIFT.getY(); break; } 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 > 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 ); } std::shared_ptr< SDLPP::RectangleRender > 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 ); } std::shared_ptr< SDLPP::RectangleRender > 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, false, true ); dynamic_cast< MarioBlock & >( *mario ).setTerrain( false ); return mario; } enum BlockRole::Value getBlockRole( uint64_t id ) { if ( id >= 0x7000 ) return BlockRole::TERRAIN; if ( id == MARIO_ID ) return BlockRole::MARIO; if ( id < MARIO_ID ) return BlockRole::MODIFIER; // TODO modifier/character return BlockRole::MODIFIER; }