From a54d079fd2323f5527bf0cf7522bf70f3792e621 Mon Sep 17 00:00:00 2001 From: zv0n Date: Mon, 7 Jun 2021 23:48:28 +0200 Subject: [PATCH] Mario: add MapObject and use that instead of tuples --- mario/Makefile | 4 +- mario/blocks.cpp | 6 +- mario/editor.cpp | 136 +++++++++++++++----------------- mario/main.cpp | 2 +- mario/maploader.cpp | 188 +++++++++++++++++++++++++++----------------- mario/maploader.hpp | 20 +---- mario/mapobject.cpp | 98 +++++++++++++++++++++++ mario/mapobject.hpp | 42 ++++++++++ mario/objectids.hpp | 2 +- 9 files changed, 329 insertions(+), 169 deletions(-) create mode 100644 mario/mapobject.cpp create mode 100644 mario/mapobject.hpp diff --git a/mario/Makefile b/mario/Makefile index 69fae3d..dacc799 100644 --- a/mario/Makefile +++ b/mario/Makefile @@ -18,7 +18,7 @@ LDFLAGS ?= -lSDL2 -lSDL2_image -lSDL2_gfx -lSDL2_ttf -pthread OUTPUTFLAG = -o endif -COMMON_OBJECTS = global_vars.${OBJEXT} sprites.${OBJEXT} maploader.${OBJEXT} +COMMON_OBJECTS = global_vars.${OBJEXT} sprites.${OBJEXT} maploader.${OBJEXT} mapobject.${OBJEXT} ifneq ($(UNAME_S),Windows) COMMON_OBJECTS += libsdlpp.a endif @@ -69,6 +69,8 @@ tool_box.${OBJEXT}: tool_box.cpp ../sdlpp/sdlpp.hpp sprites.hpp tool_box.hpp $(CXX) $(CXXFLAGS) -c ${OUTPUTFLAG}$@ $< editor_visitor.${OBJEXT}: editor_visitor.cpp ../sdlpp/sdlpp.hpp sprites.hpp editor_visitor.hpp $(CXX) $(CXXFLAGS) -c ${OUTPUTFLAG}$@ $< +mapobject.${OBJEXT}: mapobject.cpp ../sdlpp/sdlpp.hpp objectids.hpp + $(CXX) $(CXXFLAGS) -c ${OUTPUTFLAG}$@ $< mario.${OBJEXT}: mario.cpp ../sdlpp/sdlpp.hpp mario.hpp global_vars.hpp objectids.hpp sprites.hpp ../sdlpp/sdlpp_rectrenderer.hpp $(CXX) $(CXXFLAGS) -c ${OUTPUTFLAG}$@ $< libsdlpp.a: ../sdlpp diff --git a/mario/blocks.cpp b/mario/blocks.cpp index 0eff04b..05d5c31 100644 --- a/mario/blocks.cpp +++ b/mario/blocks.cpp @@ -154,7 +154,7 @@ const std::vector< uint64_t > possibleBlocks = { }; const std::vector< uint64_t > possibleMods = { - DESTRUCTIBLE_ID, + DESTRUCTIBLE_MODIFIER_ID, }; const std::vector< uint64_t > possibleCharacters = { @@ -228,7 +228,7 @@ const std::unordered_map< uint64_t, const SDL_Rect * > block_mapping = { { CANNON_PEDESTAL_ID, &CANNON_PEDESTAL_SRC }, { CANNON_ID, &CANNON_SRC }, { MARIO_ID, &MARIO_STANDING_SRC }, - { DESTRUCTIBLE_ID, &DESTRUCTIBLE_SRC }, + { DESTRUCTIBLE_MODIFIER_ID, &DESTRUCTIBLE_SRC }, }; const std::unordered_map< uint64_t, uint64_t > block_flags = { @@ -291,7 +291,7 @@ const std::unordered_map< uint64_t, uint64_t > block_flags = { { CANNON_PEDESTAL_ID, HAS_COLLISION }, { CANNON_ID, HAS_COLLISION }, { MARIO_ID, 0 }, - { DESTRUCTIBLE_ID, 0 }, + { DESTRUCTIBLE_MODIFIER_ID, 0 }, }; bool blockCanBeDestroyed(uint64_t id) { diff --git a/mario/editor.cpp b/mario/editor.cpp index af80e68..41b00a8 100644 --- a/mario/editor.cpp +++ b/mario/editor.cpp @@ -136,13 +136,9 @@ void updateTool() { void removeMario() { if ( !global_vars.mario ) return; - auto prev = global_vars.objects[global_vars.mario_pos.getX()] - [global_vars.mario_pos.getY()]; - // remove character/modifiers global_vars - .objects[global_vars.mario_pos.getX()][global_vars.mario_pos.getY()] = { - std::get< 0 >( prev ), std::get< 1 >( prev ), 0, 0, 0, 0 - }; + .objects[global_vars.mario_pos.getX()][global_vars.mario_pos.getY()] + .unsetCharacter(); global_vars.mario->destroy(); } @@ -166,7 +162,7 @@ void setToolColor( const std::string &color ) { store = nullptr; break; } - if(store == nullptr) + if ( store == nullptr ) return; auto index = global_vars.tool.index % ( 2 * multiplier ); store->at( index )->setColor( color ); @@ -203,7 +199,7 @@ void updateToolSelection( int prev_index, ToolType::Value type ) { default: break; } - if(tool_vec == nullptr) + if ( tool_vec == nullptr ) return; auto cur = cur_page * multiplier; size_t prev = prev_index * multiplier; @@ -291,7 +287,7 @@ void updateToolIndex( uint64_t new_index, ToolType::Value new_type ) { } void updateToolIndex( uint64_t new_index ) { - updateToolIndex(new_index, global_vars.tool.type); + updateToolIndex( new_index, global_vars.tool.type ); } void selectLowerTool() { @@ -549,7 +545,7 @@ SDLPP::Vec2D< int > getSelectedObjectIndexes() { SDLPP::Vec2D< int >( global_vars.map.cur_page - 1, 0 ); } -mapObjectType &getSelectedObject() { +MapObject &getSelectedObject() { auto pos = getSelectedObjectIndexes(); return global_vars.objects[pos.getX()][pos.getY()]; } @@ -570,48 +566,36 @@ void placeTool( SDLPP::Scene &scene ) { } scene.visitCollisions( *global_vars.current_tool, visitor ); + auto &obj = getSelectedObject(); if ( visitor.removeBlock() && !visitor.addBlock() ) { - auto &obj = getSelectedObject(); switch ( visitor.getVisitorType() ) { case VisitorType::Terrain: - std::get< MapObject::TERRAIN_TYPE >( obj ) = - global_vars.current_world_type; - std::get< MapObject::TERRAIN_ID >( obj ) = 0; + obj.unsetTerrain(); break; case VisitorType::Modifier: - std::get< MapObject::CHARACTER_TYPE >( obj ) = 0; - std::get< MapObject::CHARACTER_ID >( obj ) = 0; - std::get< MapObject::MODIFIER_TYPE >( obj ) = 0; - std::get< MapObject::MODIFIER_DATA >( obj ) = 0; + obj.unsetModifier(); break; default: break; } } else if ( visitor.addBlock() ) { - auto &obj = getSelectedObject(); auto renderer = scene.getRendererShared(); int z_index = 1; std::shared_ptr< SDLPP::RenderObject > new_obj = nullptr; switch ( visitor.getVisitorType() ) { case VisitorType::Terrain: - std::get< MapObject::TERRAIN_TYPE >( obj ) = - global_vars.current_world_type; - std::get< MapObject::TERRAIN_ID >( obj ) = - global_vars.current_tool->getId(); - new_obj = - createTerrainBlock( global_vars.current_tool->getId(), - global_vars.current_world_type, renderer, - global_vars.mouse.edit_box.getX(), - global_vars.mouse.edit_box.getY(), false, true ); + obj.setTerrain( global_vars.current_tool->getId(), + global_vars.current_world_type ); + new_obj = createTerrainBlock( + obj.getTerrainId(), + obj.getTerrainType(), renderer, + global_vars.mouse.edit_box.getX(), + global_vars.mouse.edit_box.getY(), false, true ); new_obj->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); break; case VisitorType::Modifier: if ( tool_type == BlockRole::MARIO ) { - std::get< MapObject::CHARACTER_TYPE >( obj ) = - global_vars.current_world_type; - std::get< MapObject::CHARACTER_ID >( obj ) = MARIO_ID; - std::get< MapObject::MODIFIER_TYPE >( obj ) = 0; - std::get< MapObject::MODIFIER_DATA >( obj ) = 0; + obj.setCharacter(MARIO_ID, global_vars.current_world_type); new_obj = createMario( global_vars.current_world_type, renderer, global_vars.mouse.edit_box.getX(), global_vars.mouse.edit_box.getY() ); @@ -624,12 +608,10 @@ void placeTool( SDLPP::Scene &scene ) { // TODO BlockRole::Character } else { // TODO data - std::get< MapObject::MODIFIER_TYPE >( obj ) = - global_vars.current_tool->getId(); - std::get< MapObject::MODIFIER_DATA >( obj ) = 0; + obj.setModifier(global_vars.current_tool->getId(), 0); new_obj = createTerrainBlock( - global_vars.current_tool->getId(), - global_vars.current_world_type, renderer, + obj.getModifierId(), + LandType::OVERWORLD, renderer, global_vars.mouse.edit_box.getX(), global_vars.mouse.edit_box.getY(), global_vars.translucent_terrain_texture, false, true ); @@ -705,7 +687,8 @@ void pollEvents( SDLPP::Scene &scene ) { global_vars.current_world_type = possibleLands[index]; updateWorld(); } else if ( index < max_index ) { - updateToolIndex( cur_page * multiplier + index, global_vars.mouse.tool_type ); + updateToolIndex( cur_page * multiplier + index, + global_vars.mouse.tool_type ); } } break; @@ -820,8 +803,9 @@ void populateToolGrid( // fall through case ToolType::BLOCK: case ToolType::MOD: - tool_store.push_back( createTerrainBlock( - block, global_vars.current_world_type, renderer, false, true ) ); + tool_store.push_back( + createTerrainBlock( block, global_vars.current_world_type, + renderer, false, true ) ); default: break; } @@ -952,7 +936,7 @@ int main() { global_vars.current_world_type = LandType::OVERWORLD; // TODO file name - loadMap( scene, global_vars.mario, "test_binary.bin", renderer, + loadMap( scene, global_vars.mario, "test_binary.bin", global_vars.objects, true, MAP_WIDTH ); auto font = std::make_shared< SDLPP::Font >( "testfont.ttf", 36 ); @@ -962,9 +946,9 @@ int main() { // create grids and arrow controls // map auto arrows = createArrowControls( - 0, ( MAP_WIDTH + 1 ) * BLOCK_SIZE, - 1 - MAP_HEIGHT * BLOCK_SIZE, MAP_HEIGHT * BLOCK_SIZE, - EDITOR_LEFT_MAP_ID, EDITOR_RIGHT_MAP_ID, scene, font_config ); + 0, ( MAP_WIDTH + 1 ) * BLOCK_SIZE, 1 - MAP_HEIGHT * BLOCK_SIZE, + MAP_HEIGHT * BLOCK_SIZE, EDITOR_LEFT_MAP_ID, EDITOR_RIGHT_MAP_ID, scene, + font_config ); auto left_map_arrow = arrows.first; auto right_map_arrow = arrows.second; createGrid( BLOCK_SIZE, 1 - MAP_HEIGHT * BLOCK_SIZE, MAP_WIDTH, MAP_HEIGHT, @@ -973,53 +957,61 @@ int main() { for ( int i = 0; i < MAP_WIDTH; i++ ) { for ( int j = 0; j < MAP_HEIGHT; j++ ) { scene->addObject( std::make_shared< EditBox >( - i, j, BLOCK_SIZE, 1 - MAP_HEIGHT * BLOCK_SIZE, MAP_WIDTH, MAP_HEIGHT, renderer ) ); + i, j, BLOCK_SIZE, 1 - MAP_HEIGHT * BLOCK_SIZE, MAP_WIDTH, + MAP_HEIGHT, renderer ) ); } } // tools populateToolGrid( TOOLS_WIDTH, 2, ( MAP_WIDTH - TOOLS_WIDTH ) * BLOCK_SIZE, - 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, ToolType::BLOCK, possibleBlocks, - global_vars.tools, global_vars.tool_boxes, scene, - "TERRAIN", font_config ); - arrows = createArrowControls( ( MAP_WIDTH - TOOLS_WIDTH - 1 ) * BLOCK_SIZE, - MAP_WIDTH * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, - 2 * BLOCK_SIZE, EDITOR_LEFT_TOOL_ID, - EDITOR_RIGHT_TOOL_ID, scene, font_config ); + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, ToolType::BLOCK, + possibleBlocks, global_vars.tools, global_vars.tool_boxes, + scene, "TERRAIN", font_config ); + arrows = createArrowControls( + ( MAP_WIDTH - TOOLS_WIDTH - 1 ) * BLOCK_SIZE, MAP_WIDTH * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, 2 * BLOCK_SIZE, + EDITOR_LEFT_TOOL_ID, EDITOR_RIGHT_TOOL_ID, scene, font_config ); auto left_tool_arrow = arrows.first; auto right_tool_arrow = arrows.second; - createGrid( ( MAP_WIDTH - TOOLS_WIDTH ) * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, - TOOLS_WIDTH, 2, scene ); + createGrid( ( MAP_WIDTH - TOOLS_WIDTH ) * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, TOOLS_WIDTH, 2, scene ); // mods - populateToolGrid( MOD_WIDTH, 2, 5 * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, ToolType::MOD, + populateToolGrid( MOD_WIDTH, 2, 5 * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, ToolType::MOD, possibleMods, global_vars.mods, global_vars.mod_boxes, scene, "MODS", font_config ); - arrows = - createArrowControls( 4 * BLOCK_SIZE, ( MOD_WIDTH + 5 ) * BLOCK_SIZE, - 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, 2 * BLOCK_SIZE, EDITOR_LEFT_MOD_ID, - EDITOR_RIGHT_MOD_ID, scene, font_config ); + arrows = createArrowControls( + 4 * BLOCK_SIZE, ( MOD_WIDTH + 5 ) * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, 2 * BLOCK_SIZE, EDITOR_LEFT_MOD_ID, + EDITOR_RIGHT_MOD_ID, scene, font_config ); auto left_mod_arrow = arrows.first; auto right_mod_arrow = arrows.second; - createGrid( 5 * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, MOD_WIDTH, 2, scene ); + createGrid( 5 * BLOCK_SIZE, 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, MOD_WIDTH, + 2, scene ); // characters populateToolGrid( CHARACTER_WIDTH, 2, ( MOD_WIDTH + 8 ) * BLOCK_SIZE, - 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, ToolType::CHARACTER, possibleCharacters, - global_vars.characters, global_vars.character_boxes, - scene, "CHARACTERS", font_config ); - arrows = createArrowControls( - ( MOD_WIDTH + 7 ) * BLOCK_SIZE, - ( MOD_WIDTH + 8 + CHARACTER_WIDTH ) * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, - 2 * BLOCK_SIZE, EDITOR_LEFT_CHARACTER_ID, EDITOR_RIGHT_CHARACTER_ID, - scene, font_config ); + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, ToolType::CHARACTER, + possibleCharacters, global_vars.characters, + global_vars.character_boxes, scene, "CHARACTERS", + font_config ); + arrows = + createArrowControls( ( MOD_WIDTH + 7 ) * BLOCK_SIZE, + ( MOD_WIDTH + 8 + CHARACTER_WIDTH ) * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, + 2 * BLOCK_SIZE, EDITOR_LEFT_CHARACTER_ID, + EDITOR_RIGHT_CHARACTER_ID, scene, font_config ); auto left_char_arrow = arrows.first; auto right_char_arrow = arrows.second; - createGrid( ( MOD_WIDTH + 8 ) * BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, CHARACTER_WIDTH, 2, + createGrid( ( MOD_WIDTH + 8 ) * BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, CHARACTER_WIDTH, 2, scene ); // world type - populateWorldType( OVERWORLD_WIDTH, 2, BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, scene, "WORLD", + populateWorldType( OVERWORLD_WIDTH, 2, BLOCK_SIZE, + 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, scene, "WORLD", font_config ); - createGrid( BLOCK_SIZE, 1 - (MAP_HEIGHT + 3) * BLOCK_SIZE, OVERWORLD_WIDTH, 2, scene ); + createGrid( BLOCK_SIZE, 1 - ( MAP_HEIGHT + 3 ) * BLOCK_SIZE, + OVERWORLD_WIDTH, 2, scene ); global_vars.map.max_page = global_vars.objects.size() - MAP_WIDTH; diff --git a/mario/main.cpp b/mario/main.cpp index 93b1667..828317d 100644 --- a/mario/main.cpp +++ b/mario/main.cpp @@ -207,7 +207,7 @@ int main() { leftStop->setColiderColor( "#FF00FF" ); scene->addObject( leftStop ); - loadMap( scene, mario, "test_binary2.bin", renderer ); + loadMap( scene, mario, "test_binary2.bin" ); auto font = std::make_shared< SDLPP::Font >( "testfont.ttf", 36 ); fps = std::make_shared(0.2, 0, 0.78, 0.1, renderer, font, "0fps", "#FFFFFF", "#000000", 0.1, SDLPP_TEXT_RIGHT); diff --git a/mario/maploader.cpp b/mario/maploader.cpp index b55643b..dcdcab2 100644 --- a/mario/maploader.cpp +++ b/mario/maploader.cpp @@ -7,92 +7,144 @@ #include "objectids.hpp" #include "global_vars.hpp" +#define TERRAIN_TYPE_HAS_ADDITIONAL 0x8 +#define WIDE_TERRAIN_HAS_ADDITIONAL 0x8000 +#define ADDITIONAL_IS_MOD 0x80 + void loadMap( std::shared_ptr< SDLPP::Scene > &scene, std::shared_ptr< SDLPP::RenderObject > mario, - const std::string &file, - std::shared_ptr< SDLPP::Renderer > &renderer ) { + const std::string &file ) { std::vector< mapColumnType > tmp = {}; - loadMap(scene, mario, file, renderer, tmp, false); - scene->moveZTop(mario); + loadMap( scene, mario, file, tmp, false ); + scene->moveZTop( mario ); +} + +uint8_t read8Bits( std::ifstream &file ) { + uint8_t data; + file.read( ( char * )&data, sizeof( uint8_t ) / sizeof( char ) ); + return data; +} +void write8Bits( std::ofstream &file, uint8_t data ) { + file.write( ( char * )&data, sizeof( uint8_t ) / sizeof( char ) ); +} + +uint16_t read16Bits( std::ifstream &file ) { + uint16_t data; + file.read( ( char * )&data, sizeof( uint16_t ) / sizeof( char ) ); + return data; +} +void write16Bits( std::ofstream &file, uint16_t data ) { + file.write( ( char * )&data, sizeof( uint16_t ) / sizeof( char ) ); +} + +std::pair< uint16_t, uint8_t > separateWideTerrain( uint16_t wide_terrain ) { + uint8_t terrain_type = ( wide_terrain & 0xF000 ) >> 12; + uint16_t terrain_id = ( wide_terrain & 0x0FFF ) | BLOCK_PREFIX; + return { terrain_id, terrain_type }; +} + +std::pair< uint8_t, uint8_t > separateAdditionalData( uint8_t data ) { + auto id = data & 0x0F; + auto type = ( data & 0xF0 ) >> 4; + return { id, type }; +} +uint16_t combineTerrain( uint16_t id, uint8_t type ) { + uint16_t wide_terrain = type; + wide_terrain = wide_terrain << 12; + wide_terrain |= 0x0FFF & id; + return wide_terrain; +} +uint8_t combineAdditionalData( uint8_t id, uint8_t type ) { + return type << 4 | id; +} + +MapObject parseBlock( std::ifstream &map_file ) { + uint8_t character_type = 0, character_id = 0, modifier_id = 0, + modifier_data = 0; + uint16_t wide_terrain = read16Bits( map_file ); + auto terrain = separateWideTerrain( wide_terrain ); + uint16_t terrain_id = terrain.first; + uint8_t terrain_type = terrain.second; + if ( terrain_type & TERRAIN_TYPE_HAS_ADDITIONAL ) { + uint8_t additional_data = read8Bits( map_file ); + terrain_type &= ~TERRAIN_TYPE_HAS_ADDITIONAL; + if ( additional_data & ADDITIONAL_IS_MOD ) { + additional_data &= ~ADDITIONAL_IS_MOD; + auto modifier = separateAdditionalData( additional_data ); + // TODO swap modifier id and data + modifier_id = modifier.second; + modifier_data = modifier.first; + } else { + // character + auto character = separateAdditionalData( additional_data ); + character_id = character.first; + character_type = character.second; + } + } + return MapObject( terrain_id, terrain_type, character_id, character_type, + modifier_id, modifier_data ); } // editor loader void loadMap( std::shared_ptr< SDLPP::Scene > &scene, std::shared_ptr< SDLPP::RenderObject > &mario, const std::string &file, - std::shared_ptr< SDLPP::Renderer > &renderer, - std::vector< mapColumnType > &objects, bool editor, size_t editor_width ) { + std::vector< mapColumnType > &objects, bool editor, + size_t editor_width ) { + auto renderer = scene->getRendererShared(); std::ifstream map_file; map_file.open( file, std::ios::in | std::ios::binary ); uint16_t cols; map_file.read( ( char * )&cols, sizeof( uint16_t ) / sizeof( char ) ); - if(editor) { + if ( editor ) { objects.resize( cols ); } mapColumnType *col = nullptr; for ( uint16_t i = 0; i < cols; i++ ) { - if(editor) { + if ( editor ) { col = &objects[i]; } for ( int j = 0; j < 16; j++ ) { - uint16_t input_number; - uint8_t additional_data = 0; - uint8_t character_type = 0, character = 0, modifier_type = 0, - modifier_data = 0; - map_file.read( ( char * )&input_number, - sizeof( uint16_t ) / sizeof( char ) ); - uint8_t type = ( input_number & 0xF000 ) >> 12; - uint16_t id = ( input_number & 0x0FFF ) | BLOCK_PREFIX; - if ( type & 0x8 ) { - map_file.read( ( char * )&additional_data, - sizeof( uint8_t ) / sizeof( char ) ); - type &= ~0x8; - if ( additional_data & 0x80 ) { - // modifier - additional_data &= ~0x80; - modifier_type = ( additional_data & 0xF0 ) >> 4; - modifier_data = additional_data & 0x0F; - } else { - // character - character_type = ( additional_data & 0xF0 ) >> 4; - character = additional_data & 0x0F; - } - } - if(editor) { - col->at(j) = { type, id, character_type, character, - modifier_type, modifier_data }; + auto block = parseBlock( map_file ); + if ( editor ) { + col->at( j ) = block; } bool destructible = false; - if(!editor && modifier_type == DESTRUCTIBLE_ID) { + if ( !editor && + block.getModifierId() == DESTRUCTIBLE_MODIFIER_ID ) { destructible = true; } // TODO add modifiers to createTerrainBlock - auto obj = - createTerrainBlock( id, static_cast< LandType::Value >( type ), - renderer, i, j, destructible, editor ); - if(obj != nullptr) { - if(editor) { - obj->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); + if(block.getTerrainId() != 0) { + auto obj = createTerrainBlock( + block.getTerrainId(), block.getTerrainType(), + renderer, i, j, destructible, editor ); + if ( obj != nullptr ) { + if ( editor ) { + obj->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); + } + scene->addObject( obj ); } - scene->addObject( obj ); } - if ( character ) { - if ( character == MARIO_ID ) { - if(editor) { + if ( block.hasCharacter() ) { + if ( block.getCharacterId() == MARIO_ID ) { + if ( editor ) { scene->addObject( createMario( - static_cast< LandType::Value >( character_type ), + block.getCharacterType(), renderer, i, j ) ); - mario = scene->getObject(scene->getObjects().size() - 1); + mario = + scene->getObject( scene->getObjects().size() - 1 ); } else { mario->setPos( i * BLOCK_SIZE, 1 - ( 16 - j ) * BLOCK_SIZE ); } } } - if ( editor && modifier_type ) { + if ( editor && block.hasModifier() ) { + // TODO createModifierBlock with data auto mod = createTerrainBlock( - modifier_type, LandType::OVERWORLD, renderer, i, j, + block.getModifierId(), LandType::OVERWORLD, renderer, i, j, g_translucent_terrain_texture, false, editor ); mod->getCollisions()[0]->setId( EDITOR_TERRAIN_ID ); dynamic_cast< MarioBlock * >( mod.get() )->setTerrain( false ); @@ -105,8 +157,6 @@ void loadMap( std::shared_ptr< SDLPP::Scene > &scene, } } -// tuple - world object type, object, world character type, character, modifier -// type, modifier data void saveMap( const std::string &file, std::vector< mapColumnType > &objects ) { std::ofstream output_file; output_file.open( file, std::ios::out | std::ios::binary ); @@ -114,33 +164,23 @@ void saveMap( const std::string &file, std::vector< mapColumnType > &objects ) { output_file.write( ( char * )&cols, sizeof( uint16_t ) / sizeof( char ) ); for ( auto &col : objects ) { for ( int i = 0; i < 16; i++ ) { - auto &obj = col[i]; - uint16_t wide_type = std::get< MapObject::TERRAIN_TYPE >( obj ); - wide_type = wide_type << 12; - uint16_t write_num = - ( 0x0FFF & std::get< MapObject::TERRAIN_ID >( obj ) ) | - wide_type; - // character type can be 0 (overworld), modifier data can be 0 - if ( std::get< MapObject::CHARACTER_ID >( obj ) || - std::get< MapObject::MODIFIER_TYPE >( obj ) ) { - write_num |= 0x8000; + auto &block = col[i]; + auto wide_terrain = combineTerrain(block.getTerrainId(), block.getTerrainType()); + // if block has additional data it needs to indicate it + if ( block.hasCharacter() || block.hasModifier() ) { + wide_terrain |= WIDE_TERRAIN_HAS_ADDITIONAL; } - output_file.write( ( char * )&write_num, - sizeof( uint16_t ) / sizeof( char ) ); + write16Bits(output_file, wide_terrain); uint8_t additional_data = 0; - if ( std::get< MapObject::CHARACTER_ID >( obj ) ) { - additional_data |= std::get< MapObject::CHARACTER_TYPE >( obj ) - << 4; - additional_data |= std::get< MapObject::CHARACTER_ID >( obj ); - } else if ( std::get< MapObject::MODIFIER_TYPE >( obj ) ) { - additional_data |= std::get< MapObject::MODIFIER_TYPE >( obj ) - << 4; - additional_data |= 0x80; - additional_data |= std::get< MapObject::MODIFIER_DATA >( obj ); + if ( block.hasCharacter() ) { + additional_data = combineAdditionalData(block.getCharacterId(), block.getCharacterType()); + } else if ( block.hasModifier() ) { + // TODO seriously change order of id/data!!! + additional_data = combineAdditionalData(block.getModifierData(), block.getModifierId()); + additional_data |= ADDITIONAL_IS_MOD; } if ( additional_data ) { - output_file.write( ( char * )&additional_data, - sizeof( uint8_t ) / sizeof( char ) ); + write8Bits(output_file, additional_data); } } } diff --git a/mario/maploader.hpp b/mario/maploader.hpp index 27f008f..2a02ebd 100644 --- a/mario/maploader.hpp +++ b/mario/maploader.hpp @@ -3,30 +3,16 @@ #include "../sdlpp/sdlpp_scene.hpp" #include "../sdlpp/sdlpp_rectrenderer.hpp" +#include "mapobject.hpp" -struct MapObject { - enum Index { - TERRAIN_TYPE = 0, - TERRAIN_ID = 1, - CHARACTER_TYPE = 2, - CHARACTER_ID = 3, - MODIFIER_TYPE = 4, - MODIFIER_DATA = 5, - }; -}; - -typedef std::tuple< uint8_t, uint16_t, uint8_t, uint8_t, uint8_t, uint8_t > - mapObjectType; -typedef std::array< mapObjectType, 16 > mapColumnType; +typedef std::array< MapObject, 16 > mapColumnType; void loadMap( std::shared_ptr< SDLPP::Scene > &scene, std::shared_ptr< SDLPP::RenderObject > mario, - const std::string &file, - std::shared_ptr< SDLPP::Renderer > &renderer ); + const std::string &file ); void loadMap( std::shared_ptr< SDLPP::Scene > &scene, std::shared_ptr< SDLPP::RenderObject > &mario, const std::string &file, - std::shared_ptr< SDLPP::Renderer > &renderer, std::vector< mapColumnType > &objects, bool editor = false, size_t editor_width = 0 ); void saveMap( const std::string &file, std::vector< mapColumnType > &objects ); diff --git a/mario/mapobject.cpp b/mario/mapobject.cpp new file mode 100644 index 0000000..2f5d168 --- /dev/null +++ b/mario/mapobject.cpp @@ -0,0 +1,98 @@ +#include "mapobject.hpp" + +MapObject::MapObject( uint16_t terrain_id, LandType::Value terrain_type, + uint8_t character_id, LandType::Value character_type, + uint8_t modifier_id, uint8_t modifier_data ) { + setTerrain(terrain_id, terrain_type); + if(character_id != 0) + setCharacter(character_id, character_type); + if(modifier_id != 0) + setModifier(modifier_id, modifier_data); +} + +MapObject::MapObject( uint16_t terrain_id, uint8_t terrain_type, + uint8_t character_id, uint8_t character_type, + uint8_t modifier_id, uint8_t modifier_data ) + : MapObject( terrain_id, static_cast< LandType::Value >( terrain_type ), + character_id, + static_cast< LandType::Value >( character_type ), + modifier_id, modifier_data ) {} + +void MapObject::setTerrain( uint16_t id, LandType::Value land_type ) { + terrain_id = id; + terrain_type = land_type; +} + +void MapObject::setTerrain( uint16_t id, uint8_t land_type ) { + setTerrain( id, static_cast< LandType::Value >( land_type ) ); +} + +void MapObject::setCharacter( uint8_t id, LandType::Value land_type ) { + character_id = id; + character_type = land_type; + if(hasModifier()) { + modifier_id = 0; + modifier_data = 0; + } +} + +void MapObject::setCharacter( uint8_t id, uint8_t land_type ) { + setCharacter( id, static_cast< LandType::Value >( land_type ) ); +} + +void MapObject::setModifier( uint8_t id, uint8_t data ) { + modifier_id = id; + modifier_data = data; + if(hasCharacter()) { + character_id = 0; + character_type = LandType::OVERWORLD; + } +} + +void MapObject::unsetTerrain() { + setTerrain(0, 0); +} + +void MapObject::unsetModifier() { + if ( hasModifier() ) { + setModifier( 0, 0 ); + } +} + +void MapObject::unsetCharacter() { + if ( hasCharacter() ) { + setCharacter( 0, 0 ); + } +} + +bool MapObject::hasCharacter() { + return character_id != 0; +} + +bool MapObject::hasModifier() { + return modifier_id != 0; +} + +uint16_t MapObject::getTerrainId() { + return terrain_id; +} + +uint8_t MapObject::getCharacterId() { + return character_id; +} + +uint8_t MapObject::getModifierId() { + return modifier_id; +} + +LandType::Value MapObject::getTerrainType() { + return terrain_type; +} + +LandType::Value MapObject::getCharacterType() { + return character_type; +} + +uint8_t MapObject::getModifierData() { + return modifier_data; +} diff --git a/mario/mapobject.hpp b/mario/mapobject.hpp new file mode 100644 index 0000000..2b28d36 --- /dev/null +++ b/mario/mapobject.hpp @@ -0,0 +1,42 @@ +#ifndef MAP_OBJECT_H +#define MAP_OBJECT_H + +#include "blocks.hpp" + +class MapObject { +public: + MapObject() = default; + MapObject( uint16_t terrain_id, uint8_t terrain_type, uint8_t character_id, + uint8_t character_type, uint8_t modifier_id, + uint8_t modifier_data ); + MapObject( uint16_t terrain_id, LandType::Value terrain_type, + uint8_t character_id, LandType::Value character_type, + uint8_t modifier_id, uint8_t modifier_data ); + void setTerrain( uint16_t id, LandType::Value land_type ); + void setTerrain( uint16_t id, uint8_t land_type ); + void setCharacter( uint8_t id, LandType::Value land_type ); + void setCharacter( uint8_t id, uint8_t land_type ); + void setModifier( uint8_t id, uint8_t data ); + void unsetTerrain(); + void unsetModifier(); + void unsetCharacter(); + bool hasCharacter(); + bool hasModifier(); + + uint16_t getTerrainId(); + uint8_t getCharacterId(); + uint8_t getModifierId(); + LandType::Value getTerrainType(); + LandType::Value getCharacterType(); + uint8_t getModifierData(); + +private: + LandType::Value terrain_type = LandType::OVERWORLD; + uint16_t terrain_id = 0; + LandType::Value character_type = LandType::OVERWORLD; + uint8_t character_id = 0; + uint8_t modifier_id = 0; + uint8_t modifier_data = 0; +}; + +#endif diff --git a/mario/objectids.hpp b/mario/objectids.hpp index f61d9f8..4c627f6 100644 --- a/mario/objectids.hpp +++ b/mario/objectids.hpp @@ -63,7 +63,7 @@ #define CANNON_ID 0x703A // modifiers -#define DESTRUCTIBLE_ID 0x01 +#define DESTRUCTIBLE_MODIFIER_ID 0x01 // character IDs #define MARIO_ID 0x0F