#include #include #include #include #include #include #include #include "map/tile.hpp" #include "defaults/input.hpp" #include "map/map.hpp" #include "defaults/ui.hpp" namespace Tile { size_t active_tileset_id = 0; TileType active_tileset_type = TILE_BACKGROUND; TileSet* active_tileset = nullptr; bool draw_tile_set = true; bool tile_selected = false; bool object_selected = false; size_t selected_object_id = SIZE_MAX; SDL_Point selected_position = {0,0}; TileObjectPropSettingStates object_props_setting_state = TileObjectPropSettingStates::OBJECT_SETTING_STATE_TYPE; std::unordered_map> tilesets; std::vector selected_tiles; SDL_FPoint tileset_offset = {0, Ui::top_bar_height}; SDL_FPoint tileset_offset_to_set = {0, 0}; bool setting_tileset_offset = false; float tileset_scale = 0; float tileset_scale_to_set = 0; bool setting_tileset_scale = false; bool hovering_set = false; SDL_Point selection_tile_dimension = {1, 1}; SDL_Point selected_tile_dimension = {1, 1}; std::string save_tileset_collission_path = "saves/save.tileset_collissions"; std::string save_tileset_objects_path = "saves/save.tileset_objects"; std::string save_tileset_floortype_path = "saves/save.tileset_floortype"; std::vector tile_setting_history; std::vector floor_props; std::unordered_map> tileset_floor_props; const char* to_String(TileTypeFloors type) { switch (type) { case NONE: return "NONE"; case MEADOW: return "MEADOW"; case CLAY: return "CLAY"; case SOIL: return "SOIL"; case BRICKS: return "BRICKS"; case ICE: return "ICE"; case DESERT: return "DESERT"; case WATER: return "WATER"; default: return "UNKNOWN"; } } bool Init(SDL_Renderer* renderer) { Tile::tilesets[TILE_BACKGROUND].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Floors_Tiles.png"), {25, 26}, TILE_GROUND, {}, {}, {} }); Tile::tilesets[TILE_BACKGROUND].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Water_tiles.png"), {25, 25}, TILE_WATER, {}, {}, {} }); Tile::tilesets[TILE_BACKGROUND].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Dungeon_Tiles.png"), {25, 25}, TILE_DUNGEON, {}, {}, {} }); Tile::tilesets[TILE_BACKGROUND].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Wall_Tiles.png"), {25, 25}, TILE_WALL, {}, {}, {} }); Tile::tilesets[TILE_BACKGROUND].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Wall_Variations.png"), {16, 30}, TILE_WALL_VARIATION, {}, {}, {} }); Tile::tilesets[TILE_OVERLAY].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Tilesets/Overlay_tiles.png"), {25,25}, TILE_OVERLAY_FARM, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Structures/Buildings/Floors.png"), {25, 25}, TILE_FLOORS, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Structures/Buildings/Props.png"), {25, 25}, TILE_PROPS, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Structures/Buildings/Roofs.png"), {25, 25}, TILE_ROOFS, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Structures/Buildings/Walls.png"), {42, 50}, TILE_WALLS, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Furniture.png"), {50, 54}, TILE_FURNITURE, {}, {}, {} }); Tile::tilesets[TILE_BUILDING].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Structures/Stations/Workbench/Workbench.png"), {12, 22}, TILE_WORKBENCH, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Vegetation.png"), {25, 27}, TILE_VEGETATION, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Rocks.png"), {13, 19}, TILE_ROCK, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Trees/Model_01/Size_02.png"), {16, 8}, TILE_TREE, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Trees/Model_01/Size_03.png"), {13, 12}, TILE_TREE, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Trees/Model_01/Size_04.png"), {23, 16}, TILE_TREE, {}, {}, {} }); Tile::tilesets[TILE_OBJECT].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Trees/Model_01/Size_05.png"), {28, 23}, TILE_TREE, {}, {}, {} }); Tile::tilesets[TILE_FARM].push_back( {IMG_LoadTexture(renderer, "Pixel_Crawler/Environment/Props/Static/Farm.png"), {25, 25}, TILE_FARMING, {}, {}, {} }); for (auto& [tile_type, tileset_vector] : Tile::tilesets) { for (auto& tileset : tileset_vector) { SDL_Texture* tex = tileset.texture; if (tex) { SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST); } } } if (!Tile::tilesets[TILE_BACKGROUND][0].texture) { SDL_Log("Couldn't load texture: %s\n", SDL_GetError()); return false; } const int cells_per_tile = Tile::get_Size() / Tile::tile_collider_size; for (auto& tileset : Tile::tilesets[TILE_BACKGROUND]) { if (tileset.texture) { SDL_SetTextureScaleMode(tileset.texture, SDL_SCALEMODE_NEAREST); } } for (auto &pair : Tile::tilesets) { for (auto &tile : pair.second) { size_t total_cells = static_cast(tile.size.x * cells_per_tile * tile.size.y * cells_per_tile); tile.collission_map.assign(total_cells, false); } } Tile::load_Collissions(); Tile::load_Objects(); ResourceData::load_Resources(); Tile::load_TilesetFloorProps(); Tile::active_tileset = &Tile::tilesets[TILE_BACKGROUND][0]; floor_props.push_back({NONE, true, false}); floor_props.push_back({MEADOW, true, false}); floor_props.push_back({CLAY, true, false}); floor_props.push_back({SOIL, true, true}); floor_props.push_back({BRICKS, true, false}); floor_props.push_back({ICE, false, false}); floor_props.push_back({DESERT, false, false}); floor_props.push_back({WATER, false, false}); return true; } TileType get_Type(TileCategory category) { switch (category) { case TILE_GROUND: case TILE_WATER: case TILE_WALL: case TILE_WALL_VARIATION: case TILE_DUNGEON: return TILE_BACKGROUND; case TILE_OVERLAY_FARM: return TILE_OVERLAY; case TILE_FLOORS: case TILE_PROPS: case TILE_ROOFS: case TILE_WALLS: case TILE_WORKBENCH: case TILE_FURNITURE: return TILE_BUILDING; case TILE_TREE: case TILE_ROCK: case TILE_VEGETATION: case TILE_FARMING: return TILE_OBJECT; } return TILE_TYPE_LAST; } size_t get_Size() { return (tile_size); } size_t get_SelectionSize(ModifyState_s modify_state) { if (modify_state == MODIFY_COLLISSION) return (tile_collider_size); return (tile_size); } size_t get_ObjectIdFromTileset(SDL_Point selected_tile, TileSet tileset) { for (const auto& pair : tileset.objects) { SDL_Rect position = pair.second.position; if (position.x <= static_cast(selected_tile.x) && position.y <= static_cast(selected_tile.y) && position.x+pair.second.position.w > static_cast(selected_tile.x) && position.y+pair.second.position.h > static_cast(selected_tile.y)) { return pair.first; } } return SIZE_MAX; } void set_HoveringTileset(SDL_FPoint mouse_state) { size_t selection_size = get_Size(); float logical_x = mouse_state.x - tileset_offset.x; float logical_y = mouse_state.y - tileset_offset.y; int tile_x = static_cast(logical_x / selection_size); int tile_y = static_cast(logical_y / selection_size); hovering_set = (tile_x >= 0 && tile_x < static_cast(active_tileset->size.x) && tile_y >= 0 && tile_y < static_cast(active_tileset->size.y)); } TileSet& get_TilesetFromMapTile(Tile_s tile) { return tilesets[get_Type(tile.set_category)][tile.set_id]; } void save_Objects() { std::ofstream file(save_tileset_objects_path, std::ios::binary); if (!file) return; uint32_t types_count = tilesets.size(); file.write(reinterpret_cast(&types_count), sizeof(types_count)); for (const auto& [type, vec] : tilesets) { uint32_t t = static_cast(type); file.write(reinterpret_cast(&t), sizeof(t)); uint32_t set_count = vec.size(); file.write(reinterpret_cast(&set_count), sizeof(set_count)); for (const auto& tile : vec) { uint64_t obj_count = tile.objects.size(); file.write(reinterpret_cast(&obj_count), sizeof(obj_count)); for (const auto& [key, obj] : tile.objects) { file.write(reinterpret_cast(&key), sizeof(key)); // --- TilesetObject serialization --- file.write(reinterpret_cast(&obj.position.x), sizeof(obj.position.x)); file.write(reinterpret_cast(&obj.position.y), sizeof(obj.position.y)); file.write(reinterpret_cast(&obj.position.w), sizeof(obj.position.w)); file.write(reinterpret_cast(&obj.position.h), sizeof(obj.position.h)); file.write(reinterpret_cast(&obj.draw_from_this_tile), sizeof(obj.draw_from_this_tile)); int type_value = static_cast(obj.object_type); file.write(reinterpret_cast(&type_value), sizeof(type_value)); file.write(reinterpret_cast(&obj.collectable), sizeof(obj.collectable)); //int building_status = static_cast(obj.building_status); // file.write(reinterpret_cast(&building_status), sizeof(building_status)); file.write(reinterpret_cast(&obj.z_index), sizeof(obj.z_index)); // --- Tile_s serialization --- file.write(reinterpret_cast(&obj.tileset_info.set_id), sizeof(obj.tileset_info.set_id)); file.write(reinterpret_cast(&obj.tileset_info.object_id), sizeof(obj.tileset_info.object_id)); int category = static_cast(obj.tileset_info.set_category); file.write(reinterpret_cast(&category), sizeof(category)); file.write(reinterpret_cast(&obj.tileset_info.set_position.x), sizeof(obj.tileset_info.set_position.x)); file.write(reinterpret_cast(&obj.tileset_info.set_position.y), sizeof(obj.tileset_info.set_position.y)); } } } } void load_Objects() { std::ifstream file(save_tileset_objects_path, std::ios::binary); if (!file) return; uint32_t types_count = 0; file.read(reinterpret_cast(&types_count), sizeof(types_count)); for (uint32_t i = 0; i < types_count; ++i) { uint32_t t = 0; file.read(reinterpret_cast(&t), sizeof(t)); TileType type = static_cast(t); uint32_t set_count = 0; file.read(reinterpret_cast(&set_count), sizeof(set_count)); auto& vec = tilesets[type]; for (uint32_t j = 0; j < set_count && j < vec.size(); ++j) { uint64_t obj_count = 0; file.read(reinterpret_cast(&obj_count), sizeof(obj_count)); vec[j].objects.clear(); for (uint64_t k = 0; k < obj_count; ++k) { size_t key = 0; file.read(reinterpret_cast(&key), sizeof(key)); TilesetObject obj{}; file.read(reinterpret_cast(&obj.position.x), sizeof(obj.position.x)); file.read(reinterpret_cast(&obj.position.y), sizeof(obj.position.y)); file.read(reinterpret_cast(&obj.position.w), sizeof(obj.position.w)); file.read(reinterpret_cast(&obj.position.h), sizeof(obj.position.h)); file.read(reinterpret_cast(&obj.draw_from_this_tile), sizeof(obj.draw_from_this_tile)); int type_value = 0; file.read(reinterpret_cast(&type_value), sizeof(type_value)); obj.object_type = static_cast(type_value); file.read(reinterpret_cast(&obj.collectable), sizeof(obj.collectable)); file.read(reinterpret_cast(&obj.z_index), sizeof(obj.z_index)); // --- Tile_s deserialization --- file.read(reinterpret_cast(&obj.tileset_info.set_id), sizeof(obj.tileset_info.set_id)); file.read(reinterpret_cast(&obj.tileset_info.object_id), sizeof(obj.tileset_info.object_id)); int category = 0; file.read(reinterpret_cast(&category), sizeof(category)); obj.tileset_info.set_category = static_cast(category); file.read(reinterpret_cast(&obj.tileset_info.set_position.x), sizeof(obj.tileset_info.set_position.x)); file.read(reinterpret_cast(&obj.tileset_info.set_position.y), sizeof(obj.tileset_info.set_position.y)); vec[j].objects.emplace(key, obj); } } } } void save_Collissions() { std::ofstream file(save_tileset_collission_path, std::ios::binary); if (!file) return; uint32_t types_count = tilesets.size(); file.write(reinterpret_cast(&types_count), sizeof(types_count)); for (const auto &[type, vec] : tilesets) { uint32_t t = static_cast(type); file.write(reinterpret_cast(&t), sizeof(t)); uint32_t set_count = vec.size(); file.write(reinterpret_cast(&set_count), sizeof(set_count)); for (const auto &tile : vec) { uint64_t map_size = tile.collission_map.size(); file.write(reinterpret_cast(&map_size), sizeof(map_size)); for (bool v : tile.collission_map) { uint8_t b = v ? 1 : 0; file.write(reinterpret_cast(&b), 1); } } } } void load_Collissions() { std::ifstream file(save_tileset_collission_path, std::ios::binary); if (!file) return; uint32_t types_count = 0; file.read(reinterpret_cast(&types_count), sizeof(types_count)); for (uint32_t i = 0; i < types_count; ++i) { uint32_t t = 0; file.read(reinterpret_cast(&t), sizeof(t)); TileType type = static_cast(t); uint32_t set_count = 0; file.read(reinterpret_cast(&set_count), sizeof(set_count)); auto &vec = tilesets[type]; for (uint32_t j = 0; j < set_count && j < vec.size(); ++j) { uint64_t map_size = 0; file.read(reinterpret_cast(&map_size), sizeof(map_size)); vec[j].collission_map.resize(map_size); for (uint64_t k = 0; k < map_size; ++k) { uint8_t b = 0; file.read(reinterpret_cast(&b), 1); vec[j].collission_map[k] = (b != 0); } } } } inline int TileCategoryToInt(TileCategory t) { return static_cast(t); } inline int TileTypeFloorsToInt(TileTypeFloors f) { return static_cast(f); } inline TileCategory IntToTileCategory(int i) { return static_cast(i); } inline TileTypeFloors IntToTileTypeFloors(int i) { return static_cast(i); } void save_TilesetFloorProps() { std::ofstream out(save_tileset_floortype_path, std::ios::binary); if (!out) { std::cerr << "Failed to open file for saving: " << save_tileset_floortype_path << "\n"; return; } size_t map_size = tileset_floor_props.size(); out.write(reinterpret_cast(&map_size), sizeof(map_size)); for (auto& [tile_type, inner_map] : tileset_floor_props) { int tt = TileCategoryToInt(tile_type); out.write(reinterpret_cast(&tt), sizeof(tt)); size_t inner_size = inner_map.size(); out.write(reinterpret_cast(&inner_size), sizeof(inner_size)); for (auto& [index, props] : inner_map) { out.write(reinterpret_cast(&index), sizeof(index)); int floor = TileTypeFloorsToInt(props.tiletype); out.write(reinterpret_cast(&floor), sizeof(floor)); out.write(reinterpret_cast(&props.z_index), sizeof(props.z_index)); } } } void load_TilesetFloorProps() { std::ifstream in(save_tileset_floortype_path, std::ios::binary); if (!in) { std::cerr << "Failed to open file for loading: " << save_tileset_floortype_path << "\n"; return; } tileset_floor_props.clear(); size_t map_size = 0; in.read(reinterpret_cast(&map_size), sizeof(map_size)); for (size_t i = 0; i < map_size; ++i) { int tt_int; in.read(reinterpret_cast(&tt_int), sizeof(tt_int)); TileCategory tt = IntToTileCategory(tt_int); size_t inner_size = 0; in.read(reinterpret_cast(&inner_size), sizeof(inner_size)); std::unordered_map inner_map; for (size_t j = 0; j < inner_size; ++j) { size_t index; int floor_int; int z_index; in.read(reinterpret_cast(&index), sizeof(index)); in.read(reinterpret_cast(&floor_int), sizeof(floor_int)); in.read(reinterpret_cast(&z_index), sizeof(z_index)); inner_map[index] = TilesetFloorProps{IntToTileTypeFloors(floor_int), z_index}; } tileset_floor_props[tt] = std::move(inner_map); } } void draw_SelectedObject(SDL_Renderer* renderer, Input input) { // render selected object if (Tile::object_selected && Default::modify_state == MODIFY_TILES) { TilesetObject object = active_tileset->objects[selected_object_id]; SDL_FRect obj_src = { object.position.x * static_cast(Tile::tile_size), object.position.y * static_cast(Tile::tile_size), object.position.w * static_cast(Tile::tile_size), object.position.h * static_cast(Tile::tile_size) }; SDL_FPoint tile_offset = { (static_cast(selected_position.x) - object.position.x) * static_cast(Tile::tile_size), (static_cast(selected_position.y) - object.position.y) * static_cast(Tile::tile_size) }; SDL_FPoint offset = {(float)tileset_offset.x, (float)tileset_offset.y}; if (!hovering_set) { offset.x = Map::offset.x; offset.y = Map::offset.y; } SDL_FRect dst {Scale(input.mouse_tile_position.x* static_cast(Tile::tile_size) + offset.x - tile_offset.x), Scale(input.mouse_tile_position.y* static_cast(Tile::tile_size) + offset.y - tile_offset.y), Scale(object.position.w * static_cast(Tile::tile_size)), Scale(object.position.h * static_cast(Tile::tile_size))}; SDL_Texture* tex = Tile::tilesets[active_tileset_type][active_tileset_id].texture; SDL_SetTextureAlphaMod(tex, 100); SDL_RenderTexture(renderer, tex, &obj_src, &dst); SDL_SetTextureAlphaMod(tex, 255); } } void draw_Tileset(SDL_Renderer* renderer, Input input) { // render Set float cell_size = Tile::get_SelectionSize(Default::modify_state); SDL_FRect dst = { 0.0f + tileset_offset.x * Default::game_scale, 0.0f + tileset_offset.y * Default::game_scale, Scale(Tile::active_tileset->size.x * tile_size), Scale(Tile::active_tileset->size.y * tile_size) }; SDL_FRect bg_rect = dst; SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_RenderFillRect(renderer, &bg_rect); SDL_RenderTexture(renderer, Tile::active_tileset->texture, NULL, &dst); // Render Set-Border float border_thickness = 4.0f; SDL_FRect top = { dst.x-border_thickness, dst.y-border_thickness, dst.w+border_thickness*2, border_thickness }; SDL_FRect bottom = { dst.x-border_thickness, dst.y + dst.h, dst.w+border_thickness*2, border_thickness }; SDL_FRect left = { dst.x-border_thickness, dst.y-border_thickness, border_thickness, dst.h+border_thickness*2 }; SDL_FRect right = { dst.x + dst.w, dst.y-border_thickness, border_thickness, dst.h+border_thickness*2 }; SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderFillRect(renderer, &top); SDL_RenderFillRect(renderer, &bottom); SDL_RenderFillRect(renderer, &left); SDL_RenderFillRect(renderer, &right); // render object cells if (Default::modify_state == MODIFY_FLOOR_TYPE) { SDL_SetRenderDrawColor(renderer, 0, 160, 255, 255); SDL_Point tileset_size = active_tileset->size; for (const auto& pair : tileset_floor_props[active_tileset->category]) { if (pair.second.tiletype == NONE) continue; int x = static_cast(pair.first) % tileset_size.x; int y = static_cast(pair.first) / tileset_size.x; SDL_FRect cell_rect = { Scale(x * tile_size + tileset_offset.x), Scale(y * tile_size + tileset_offset.y), Scale(tile_size), Scale(tile_size) }; // draw cell outline SDL_RenderRect(renderer, &cell_rect); // draw cross SDL_RenderLine(renderer, cell_rect.x, cell_rect.y, cell_rect.x + cell_rect.w, cell_rect.y + cell_rect.h); SDL_RenderLine(renderer, cell_rect.x + cell_rect.w, cell_rect.y, cell_rect.x, cell_rect.y + cell_rect.h); } } else if (Default::modify_state == MODIFY_OBJECTS || Default::modify_state == MODIFY_OBJECTS_PROPS || Default::modify_state == MODIFY_OBJECTS_PROPS_RESOURCE) { SDL_SetRenderDrawColor(renderer, 0, 255, Default::modify_state == MODIFY_OBJECTS_PROPS ? 160 : 255, 255); for (const auto& pair : active_tileset->objects) { if (Default::modify_state == MODIFY_OBJECTS_PROPS_RESOURCE && !pair.second.collectable) continue; if (pair.second.object_type == ObjectType::NONE) SDL_SetRenderDrawColor(renderer, 200, 0, 0, 255); else SDL_SetRenderDrawColor(renderer, 0, 255, Default::modify_state == MODIFY_OBJECTS_PROPS ? 160 : 255, 255); SDL_FRect cell_rect = { Scale(pair.second.position.x * cell_size + tileset_offset.x), Scale(pair.second.position.y * cell_size + tileset_offset.y), Scale(pair.second.position.w * cell_size), Scale(pair.second.position.h * cell_size) }; // draw cell outline SDL_RenderRect(renderer, &cell_rect); // draw cross SDL_RenderLine(renderer, cell_rect.x, cell_rect.y, cell_rect.x + cell_rect.w, cell_rect.y + cell_rect.h); SDL_RenderLine(renderer, cell_rect.x + cell_rect.w, cell_rect.y, cell_rect.x, cell_rect.y + cell_rect.h); } // render collision cells } else if (Default::modify_state == MODIFY_COLLISSION) { size_t map_width = static_cast(Tile::active_tileset->size.x); size_t map_height = static_cast(Tile::active_tileset->size.y); SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 255, 0, 0, 100); size_t cells_per_tile = tile_size/tile_collider_size; for (size_t y = 0; y < map_height*cells_per_tile; ++y) { for (size_t x = 0; x < map_width*cells_per_tile; ++x) { size_t index = y * map_width*cells_per_tile + x; if (!Tile::active_tileset->collission_map[index]) continue; SDL_FRect cell_rect = { Scale(x * cell_size + tileset_offset.x), Scale(y * cell_size + tileset_offset.y), Scale(cell_size), Scale(cell_size) }; // draw cell outline SDL_RenderRect(renderer, &cell_rect); // draw cross SDL_RenderLine(renderer, cell_rect.x, cell_rect.y, cell_rect.x + cell_rect.w, cell_rect.y + cell_rect.h); SDL_RenderLine(renderer, cell_rect.x + cell_rect.w, cell_rect.y, cell_rect.x, cell_rect.y + cell_rect.h); } } } // render selection_border if (hovering_set) { SDL_FRect tile_rect {Scale(input.mouse_tile_position.x*cell_size + tileset_offset.x), Scale(input.mouse_tile_position.y*cell_size + tileset_offset.y), Scale(cell_size*Tile::selection_tile_dimension.x), Scale(cell_size*Tile::selection_tile_dimension.y)}; SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); SDL_RenderRect(renderer, &tile_rect); } // render selected border if (Tile::tile_selected) { SDL_FRect tile_rect_selected {Scale(Tile::selected_tiles[0].x*tile_size + tileset_offset.x), Scale(Tile::selected_tiles[0].y*tile_size + tileset_offset.y), Scale(tile_size*Tile::selected_tile_dimension.x), Scale(tile_size*Tile::selected_tile_dimension.y)}; SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_RenderRect(renderer, &tile_rect_selected); } else if (Tile::object_selected) { TilesetObject object = active_tileset->objects[selected_object_id]; SDL_FRect tile_rect_selected {Scale(object.position.x*static_cast(tile_size) + tileset_offset.x), Scale(object.position.y*static_cast(tile_size) + tileset_offset.y), Scale(object.position.w*static_cast(tile_size)), Scale(object.position.h*static_cast(tile_size))}; SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_RenderRect(renderer, &tile_rect_selected); SDL_FRect tile_rect_selected_position {Scale(selected_position.x * static_cast(tile_size) + tileset_offset.x), Scale(selected_position.y * static_cast(tile_size) + tileset_offset.y), Scale(tile_size), Scale(tile_size)}; SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 0, 255, 0, 60); SDL_RenderFillRect(renderer, &tile_rect_selected_position); SDL_SetRenderDrawColor(renderer, 0, 255, 255, 60); SDL_RenderRect(renderer, &tile_rect_selected_position); } } void clear_Objects(Input& input) { for (int y = 0; y < Tile::selection_tile_dimension.y; y++) { for (int x = 0; x < Tile::selection_tile_dimension.x; x++) { int map_x = input.mouse_tile_position.x + x; int map_y = input.mouse_tile_position.y + y; if (map_x >= Map::size.x || map_y >= Map::size.y) continue; size_t index = static_cast(map_y * Map::size.x + map_x); auto& tile_objects = Map::tile_map[index].objects; if (!input.pressed_c || tile_objects.empty()) continue; TileObject &obj = tile_objects[0]; Object* object = Object::get_ObjectById(obj.object_id); if (!object) continue; int world_tile_x = map_x - obj.position.x; int world_tile_y = map_y - obj.position.y; for (int wx = world_tile_x; wx < world_tile_x + object->dimension.x; ++wx) { for (int wy = world_tile_y; wy < world_tile_y + object->dimension.y; ++wy) { if (wx < 0 || wy < 0 || wx >= Map::size.x || wy >= Map::size.y) continue; size_t i = static_cast(wy * Map::size.x + wx); auto &objects = Map::tile_map[i].objects; for (auto it = objects.begin(); it != objects.end();) { Object* oo = Object::get_ObjectById(it->object_id); if (!oo || oo->id == object->id) { it = objects.erase(it); } else ++it; } Map::set_TileCollissionForObjects({wx, wy}); } } delete object; } } } void set_Collission(Input& input) { const int map_width = Tile::active_tileset->size.x * (tile_size/tile_collider_size); for (int y = 0; y < Tile::selection_tile_dimension.y; ++y) { for (int x = 0; x < Tile::selection_tile_dimension.x; ++x) { int cell_x = input.mouse_tile_position.x + x; int cell_y = input.mouse_tile_position.y + y; size_t id = static_cast(cell_y * map_width + cell_x); if (id >= Tile::active_tileset->collission_map.size()) continue; Tile::active_tileset->collission_map[id] = !Tile::active_tileset->collission_map[id]; } } } bool objec_HasCollission(TilesetObject& object) { TileType type = get_Type( object.tileset_info.set_category); std::vector collision_map = Tile::get_ObjectCollisionsFromTileset(object.tileset_info.set_id, object.tileset_info.object_id, type); for (bool collission : collision_map) { if (collission) return true; } return false; } std::vector get_CollissionsOfTileFromObject(TilesetObject& obj, SDL_Point tile) { const size_t scale = Tile::tile_size / Tile::tile_collider_size; // convert rectangle to collider coordinates // 0 2 TileType type = get_Type( obj.tileset_info.set_category); std::vector collision_map = Tile::get_ObjectCollisionsFromTileset(obj.tileset_info.set_id, obj.tileset_info.object_id, type); int y_start = tile.y * (tile_size/tile_collider_size); int y_end = y_start + static_cast(tile_size/tile_collider_size); int x_start = tile.x * (tile_size/tile_collider_size); int x_end = x_start + static_cast(tile_size/tile_collider_size); int obj_w = static_cast(obj.position.w) * scale; //int obj_h = static_cast(obj.position.h) * scale; std::vector collissions; for (int y = y_start; y < y_end; y++) { for (int x = x_start; x < x_end; x++) { size_t index = static_cast(y * obj_w + x); bool cell_value = index < collision_map.size() ? collision_map[index] : false; collissions.push_back(cell_value); } } /* int obj_abs_x = static_cast(tile.x) - obj.position.x; int obj_abs_y = static_cast(tile.y) - obj.position.y; int obj_cx = obj_abs_x * static_cast(scale); int obj_cy = obj_abs_y * static_cast(scale); size_t obj_cw = static_cast(obj.position.w) * scale; size_t obj_ch = static_cast(obj.position.h) * scale; int start_cx = obj_cx; int end_cx = obj_cx + static_cast(Tile::tile_size) / static_cast(Tile::tile_collider_size); int start_cy = obj_cy; int end_cy = obj_cy + static_cast(Tile::tile_size) / static_cast(Tile::tile_collider_size); for (int cy = start_cy; cy < end_cy; ++cy) { for (int cx = start_cx; cx < end_cx; ++cx) { int rel_x = cx - obj_cx; int rel_y = cy - obj_cy; if (rel_x < 0 || rel_y < 0 || static_cast(rel_x) >= obj_cw || static_cast(rel_y) >= obj_ch) { continue; } size_t obj_index = static_cast(rel_y) * obj_cw + static_cast(rel_x); bool cell_value = obj_index < obj.collission_map.size() ? obj.collission_map[obj_index] : false; std::cout << (int)cell_value; collissions.push_back(cell_value); } std::cout << std::endl; } */ return collissions; } void set_Object(Input& input) { std::unordered_map& objects = active_tileset->objects; size_t object_id = objects.size(); size_t mouse_tile_x = static_cast(input.mouse_tile_position.x); size_t mouse_tile_y = static_cast(input.mouse_tile_position.y); // check if any tile already in objects map bool removed_object = false; for (size_t y = 0; y < static_cast(Tile::selection_tile_dimension.y); ++y) { for (size_t x = 0; x < static_cast(Tile::selection_tile_dimension.x); ++x) { size_t cell_x = mouse_tile_x + x; size_t cell_y = mouse_tile_y + y; for (size_t i = 0; i < object_id; i++) { if (objects[i].position.x == static_cast(cell_x) && objects[i].position.y == static_cast(cell_y)) { objects.erase(i); removed_object = true; break; } } } } std::cout<< "NEW OBJ ID " << object_id << " " << selected_object_id << std::endl; if (removed_object) return; // add objecz to map objects[object_id].position.x = static_cast(mouse_tile_x); objects[object_id].position.y = static_cast(mouse_tile_y); objects[object_id].position.w = Tile::selection_tile_dimension.x, objects[object_id].position.h = Tile::selection_tile_dimension.y, objects[object_id].object_type = ObjectType::NONE, objects[object_id].collectable = false; //objects[object_id].building_status = TileBuildingStatus::NONE; Tile_s tileset_info = {Tile::active_tileset_id, object_id, Tile::tilesets[Tile::active_tileset_type][Tile::active_tileset_id].category , {static_cast(objects[object_id].position.x), static_cast(objects[object_id].position.y)}}; objects[object_id].tileset_info = tileset_info; // std::cout << mouse_tile_x << " " << mouse_tile_y << " " << Tile::selection_tile_dimension.x << " " << Tile::selection_tile_dimension.x << std::endl; } void set_ObjectProps(Input& input) { static ObjectType set_type = ObjectType::NONE; static bool set_collectable = 0; static int set_zindex = 1; if (input.click_left_released) { object_props_setting_state = TileObjectPropSettingStates::OBJECT_SETTING_STATE_TYPE; size_t id = get_ObjectIdFromTileset({input.mouse_tile_position.x, input.mouse_tile_position.y}); if (id == SIZE_MAX) return; Tile::object_selected = true; Tile::selected_object_id = id; Tile::selected_position = {input.mouse_tile_position.x, input.mouse_tile_position.y}; Tile::tile_selected = false; TilesetObject object = active_tileset->objects[selected_object_id]; if (object.object_type != ObjectType::NONE) { set_type = object.object_type; set_collectable = object.collectable; set_zindex = object.z_index; } std::cout << "Type: " << Object::to_String(set_type) << ", Collectable: " << set_collectable << ", Z-Index: " << set_zindex << std::endl; std::cout << "Setting: "; } else if (object_selected) { if (input.pressed_return_released) { // get to next object_props_setting_state = static_cast(static_cast(object_props_setting_state) + 1); std::cout << "Setting: "; switch ( object_props_setting_state ) { case TileObjectPropSettingStates::OBJECT_SETTING_STATE_TYPE: std::cout << "-> Type\n active: " << Object::to_String(set_type) << std::endl; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_COLLECTING_METHODE: std::cout << "-> Collecting Methode\n active: " << set_collectable << std::endl; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_ZINDEX_METHODE: std::cout << "-> Z-Index\n active: " << set_zindex << std::endl; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_SAVE: std::cout << "Save ?\n"; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_LAST: { // Save current TilesetObject& object = active_tileset->objects[selected_object_id]; object.object_type = set_type; object.collectable = set_collectable; object.z_index = set_zindex; save_Objects(); std::cout << "Saving!" << "\n Type :" << Object::to_String(object.object_type) << "\n Collectable :" << object.collectable << "\n Z-Index :" << object.z_index << std::endl; object_selected = false; break; } default: break; } } else if (input.pressed_arrowdown_released) { switch ( object_props_setting_state ) { case TileObjectPropSettingStates::OBJECT_SETTING_STATE_TYPE: set_type = static_cast( (static_cast(set_type) + 1) % static_cast(ObjectType::LAST) ); std::cout << "Type: " << Object::to_String(set_type) << std::endl; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_COLLECTING_METHODE: set_collectable = !set_collectable; std::cout << "Collectable: " << set_collectable << "\n"; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_ZINDEX_METHODE: set_zindex -= 1; std::cout << "Z-Index " << set_zindex << "\n"; break; default: break; } std::cout << "Type: " << Object::to_String(set_type) << ", Collectable: " << set_collectable << ", Z-Index: "<< set_zindex << std::endl; } else if (input.pressed_arrowup_released) { switch ( object_props_setting_state ) { case TileObjectPropSettingStates::OBJECT_SETTING_STATE_TYPE: { int type = static_cast(set_type); int last = static_cast(ObjectType::LAST); type = (type - 1 + last) % last; set_type = static_cast(type); } std::cout << "Type: " << Object::to_String(set_type) << std::endl; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_COLLECTING_METHODE: set_collectable = !set_collectable; std::cout << "Collectable: " << set_collectable << "\n"; break; case TileObjectPropSettingStates::OBJECT_SETTING_STATE_ZINDEX_METHODE: set_zindex += 1; std::cout << "Z-Index " << set_zindex << "\n"; break; default: break; } std::cout << "Type: " << Object::to_String(set_type) << ", Collectable: " << set_collectable << ", Z-Index: "<< set_zindex << std::endl; } } }; void set_FloorType(Input& input) { static TileTypeFloors set_type = TileTypeFloors::NONE; static size_t set_state = 0; static int set_zindex = 0; static TilesetFloorProps* props = nullptr; if (input.click_left_released) { size_t id = static_cast(input.mouse_tile_position.x + input.mouse_tile_position.y * active_tileset->size.x); if (id == SIZE_MAX) return; Tile::tile_selected = false; Tile::object_selected = true; Tile::selected_object_id = id; Tile::selected_position = {input.mouse_tile_position.x, input.mouse_tile_position.y}; set_state = 0; props = nullptr; props = &tileset_floor_props[active_tileset->category][id]; if (props->tiletype != NONE) { set_type = props->tiletype; set_zindex = props->z_index; } std::cout << "Type: " << to_String(set_type) << std::endl; std::cout << "Z-Index: " << set_zindex << std::endl; if (set_state == 2) std::cout << "Save?\n"; } else if (object_selected) { if ( input.pressed_return_released ) { set_state++; if (set_state > 2) { std::cout << "Saving...\n"; props->tiletype = set_type; props->z_index = set_zindex; save_TilesetFloorProps(); set_state = 0; } else std::cout << "Setting: \n"; std::cout << "Type: " << to_String(set_type) << std::endl; std::cout << "Z-Index: " << set_zindex << std::endl; } else if (set_state == 0) { if (input.pressed_arrowup_released) { int type = static_cast(set_type); int last = static_cast(TileTypeFloors::LAST); type = (type - 1 + last) % last; set_type = static_cast(type); } else if (input.pressed_arrowdown_released) { set_type = static_cast( (static_cast(set_type) + 1) % static_cast(TileTypeFloors::LAST) ); } if ( input.pressed_arrowdown_released || input.pressed_arrowup_released || input.pressed_return_released) { std::cout << "Type: " << to_String(set_type) << std::endl; } } else if (set_state == 1) { if (input.pressed_arrowup_released) { set_zindex++; } else if (input.pressed_arrowdown_released) { set_zindex--; } if ( input.pressed_arrowdown_released || input.pressed_arrowup_released) { std::cout << "Z-Index: " << set_zindex << std::endl; } } } } TileTypeFloors get_FloorType(Tile_s& tile_s) { SDL_Point& position = tile_s.set_position; TileSet& tileset = get_TilesetFromMapTile(tile_s); size_t id = static_cast(position.y * tileset.size.x + position.x); return tileset_floor_props[tile_s.set_category][id].tiletype; } TileTypeFloors get_FloorType(SDL_Point& world_tile) { if (Map::tile_map[Map::get_IdFromTilePoint(world_tile)].overlays.size() > 0) { for (Tile_s t : Map::tile_map[Map::get_IdFromTilePoint(world_tile)].overlays) { if (t.set_position.x == 0 && t.set_position.y == 0) return TileTypeFloors::SOIL; } } Tile_s& tile_s = Map::tile_map[Map::get_IdFromTilePoint(world_tile)].background; SDL_Point& position = tile_s.set_position; TileSet& tileset = get_TilesetFromMapTile(tile_s); size_t id = static_cast(position.y * tileset.size.x + position.x); return tileset_floor_props[tile_s.set_category][id].tiletype; } void transfer_ToMap(Input& input) { // If pressing on tileset if (hovering_set) { if (!input.click_left) { if (active_tileset_type == TILE_BACKGROUND || input.pressed_shift) { Tile::selected_tiles.clear(); for (int y = 0; y < Tile::selection_tile_dimension.y; y++) { for (int x = 0; x < Tile::selection_tile_dimension.x; x++) { Tile::selected_tiles.push_back({input.mouse_tile_position.x+x, input.mouse_tile_position.y+y }); } } Tile::selected_tile_dimension.x = Tile::selection_tile_dimension.x; Tile::selected_tile_dimension.y = Tile::selection_tile_dimension.y; Tile::tile_selected = true; return; } size_t id = get_ObjectIdFromTileset({input.mouse_tile_position.x, input.mouse_tile_position.y}); if (id == SIZE_MAX) return; Tile::object_selected = true; Tile::selected_object_id = id; Tile::selected_position = {input.mouse_tile_position.x, input.mouse_tile_position.y}; Tile::tile_selected = false; print_TileObject(active_tileset->objects[selected_object_id]); } } // If pressing on map else if ( input.click_left_released && !input.pressed_c && (Tile::tile_selected || Tile::object_selected) && !Map::setting_offset && ( input.mouse_tile_position.x >= 0 && input.mouse_tile_position.y >= 0 ) && ( input.mouse_tile_position.x < Map::size.x ) && ( input.mouse_tile_position.y < Map::size.y ) ) { std::cout << "MOUS: " << input.mouse_tile_position.x << " " << input.mouse_tile_position.y << std::endl; // Set selected tile in map if (Tile::active_tileset_type == TILE_OBJECT) { TilesetObject object = active_tileset->objects[selected_object_id]; std::vector collision_map = get_ObjectCollisionsFromTileset(object.tileset_info.set_id, object.tileset_info.object_id, get_Type(object.tileset_info.set_category)); bool has_collission = objec_HasCollission(object); SDL_Point tile_offset = { selected_position.x - object.position.x, selected_position.y - object.position.y }; int map_origin_x = input.mouse_tile_position.x - tile_offset.x; int map_origin_y = input.mouse_tile_position.y - tile_offset.y; std::cout << "WP " << map_origin_x << " " << map_origin_y << std::endl; TileType type = get_Type(object.tileset_info.set_category); Resource_s res; if (object.collectable) { res = get_ResourceFromTileSet(object.tileset_info.set_id, object.tileset_info.object_id); } Object* new_object = !object.collectable ? new Object(object.object_type, object.collectable ? ObjectCategory::RESOURCE : ObjectCategory::STATIC, type, object.tileset_info.set_id, object.tileset_info.object_id, {map_origin_x, map_origin_y}, {object.position.w, object.position.h}, object.z_index) : new Resource(object.object_type, ObjectCategory::RESOURCE, type, object.tileset_info.set_id, object.tileset_info.object_id, {map_origin_x, map_origin_y}, {object.position.w, object.position.h}, object.z_index, res.resource, res.quantity, res.collecting_methode, res.collecting_duration ); Object::objects.push_back(new_object); TileObject o ={ {0,0}, false, new_object->id }; bool tile_exists = false; bool check_existence = true; bool draw_is_set = false; std::cout << "##################################\n"; for (int y = 0; y < object.position.h && !tile_exists; y++) { for (int x = 0; x < object.position.w && !tile_exists; x++) { //bool shall_set_on_tile = true; o.draw_from_this_tile = false; o.position.x = x; o.position.y = y; int map_x = map_origin_x + x ; int map_y = map_origin_y + y ; if (map_x < 0 || map_y < 0 || map_x >= static_cast(Map::size.x) || map_y >= static_cast(Map::size.y)) continue; int index = map_y * static_cast(Map::size.x) + map_x; if (has_collission) { size_t s = Tile::tile_size / Tile::tile_collider_size; size_t width_c = static_cast(object.position.w) * s; bool check = false; for (size_t yc = static_cast(y) * s; yc < static_cast(y + 1) * s && !check; yc++) { for (size_t xc = static_cast(x) * s; xc < static_cast(x + 1) * s && !check; xc++) { size_t i = yc * width_c + xc; if (collision_map[i]) { check = true; if (!draw_is_set) { o.draw_from_this_tile = true; draw_is_set = true; } } std::cout << (collision_map[i] ? '#' : '.') << ' '; } std::cout << '\n'; } //shall_set_on_tile = check; std::cout << "---- tile (" << x << "," << y << ") ----\n"; } else { if (!draw_is_set) o.draw_from_this_tile = true; draw_is_set = true; } //if (!shall_set_on_tile) continue; // make sure we dont get dublicates if (check_existence) { for (const TileObject& t : Map::tile_map[static_cast(index)].objects) { Object* map_o = Object::get_ObjectById(t.object_id); if (t.position.x == x && t.position.y == y && map_o->tileset_object_id == selected_object_id) { std::cout << "Object already set!\n"; tile_exists = true; break; } } check_existence = false; if (tile_exists) break; } Map::tile_map[static_cast(index)].objects.push_back(o); std::sort(Map::tile_map[static_cast(index)].objects.begin(), Map::tile_map[static_cast(index)].objects.end(), [](const TileObject& a, const TileObject& b) { return Object::get_ObjectById(a.object_id)->z_index < Object::get_ObjectById(b.object_id)->z_index; }); //print_TileObject(o); } } // SET OBJECT COLLISION ON TILE_MAP if (tile_exists) { delete Object::objects.back(); return; } if (!has_collission) return; Map::set_ObjectCollisionOnTilemap(new_object->id, {map_origin_x, map_origin_y}); return; } else if (Tile::active_tileset_type == TILE_BACKGROUND) { for (int y = 0; y < Tile::selection_tile_dimension.y; y++) { for (int x = 0; x < Tile::selection_tile_dimension.x; x++) { int map_x = input.mouse_tile_position.x + x; int map_y = input.mouse_tile_position.y + y; if (map_x < Map::size.x && map_y < Map::size.y) { size_t index = static_cast(map_y * Map::size.x + map_x); // Repeat selection if placing is bigger than original int wrapped_x = x % Tile::selected_tile_dimension.x; int wrapped_y = y % Tile::selected_tile_dimension.y; size_t t_id = static_cast(wrapped_y * Tile::selected_tile_dimension.x + wrapped_x); Tile_s& background = Map::tile_map[index].background; TileSet tileset = get_TilesetFromMapTile(background); /* tile_setting_history.push_back({ TILE_BACKGROUND, index, {background.set_id, background.set_category, {background.set_position.x, background.set_position.y } } }); */ background.set_id = Tile::active_tileset_id; background.set_position.x = Tile::selected_tiles[t_id].x; background.set_position.y = Tile::selected_tiles[t_id].y; background.object_id = static_cast(map_y*tileset.size.x + map_x); background.set_category = Tile::tilesets[TILE_BACKGROUND][background.set_id].category; } } } } } } void set_TilesetOffset(Input& input) { // START UNUSED FUNCTION // reset scale if (!input.click_left && tileset_scale_to_set != 0) { tileset_scale_to_set = 0; setting_tileset_scale = false; } // Set scale else if (tileset_scale_to_set != 0) { tileset_scale = input.mouse_state.y - tileset_scale_to_set; } // Update scale if (input.click_left && input.pressed_shift && (tileset_scale_to_set == 0)) { tileset_scale_to_set = input.mouse_state.y - tileset_scale; setting_tileset_scale = true; } // END UNUSED FUNCTION // Reset tileset offset if (!input.click_left && tileset_offset_to_set.x != 0 && tileset_offset_to_set.y != 0) { tileset_offset_to_set.x = 0; tileset_offset_to_set.y = 0; setting_tileset_offset = false; } // Set tileset offset else if (tileset_offset_to_set.x != 0 && tileset_offset_to_set.y != 0) { tileset_offset.x = input.mouse_state.x - tileset_offset_to_set.x; tileset_offset.y = input.mouse_state.y - tileset_offset_to_set.y; } // Update tileset_offset set if (input.click_left && input.pressed_ctrl && (tileset_offset_to_set.x == 0 && tileset_offset_to_set.y == 0)) { tileset_offset_to_set.x = input.mouse_state.x - tileset_offset.x; tileset_offset_to_set.y = input.mouse_state.y - tileset_offset.y; setting_tileset_offset = true; } } Resource_s get_ResourceFromTileSet(size_t tileset_id, size_t object_id) { return tilesets[TILE_OBJECT][tileset_id].resources[object_id]; } TilesetObject get_ObjectFromTileSet(size_t tileset_id, size_t object_id, TileType type) { return tilesets[type][tileset_id].objects[object_id]; } std::vector get_ObjectCollisionsFromTileset(size_t tileset_id, size_t object_id, TileType type) { TileSet& ts = tilesets[type][tileset_id]; auto it = ts.objects.find(object_id); if (it == ts.objects.end()) { return {}; } TilesetObject& obj = it->second; std::vector vec; int scale = Tile::tile_size / Tile::tile_collider_size; int collider_w = obj.position.w * scale; int collider_h = obj.position.h * scale; int collider_x = obj.position.x * scale; int collider_y = obj.position.y * scale; int row_width = ts.size.x * scale; if (collider_x + collider_w > row_width || collider_y + collider_h > ts.size.y * scale) { std::cerr << "Object rectangle out of collider bounds!\n"; return vec; } vec.reserve(static_cast(collider_w * collider_h)); for (int y = 0; y < collider_h; ++y) { for (int x = 0; x < collider_w; ++x) { size_t index = static_cast((collider_y + y) * row_width + (collider_x + x)); vec.push_back(ts.collission_map[index]); } } return vec; } void print_CollisionMap(const TilesetObject& obj) { size_t collider_w = static_cast(obj.position.w) * Tile::tile_size / Tile::tile_collider_size; size_t collider_h = static_cast(obj.position.h) * Tile::tile_size / Tile::tile_collider_size; std::cout << "Collision Map for object " << obj.tileset_info.object_id << " (collider size: " << collider_w << "x" << collider_h << "):\n"; std::vector collision_map = get_ObjectCollisionsFromTileset(obj.tileset_info.set_id, obj.tileset_info.object_id, get_Type(obj.tileset_info.set_category)); for (size_t y = 0; y < collider_h; ++y) { for (size_t x = 0; x < collider_w; ++x) { size_t index = y * collider_w + x; if (index >= collision_map.size()) { std::cout << "? "; // safety: missing data } else { std::cout << (collision_map[index] ? "1 " : "0 "); } } std::cout << "\n"; } } void print_TileObject(const TilesetObject& obj) { std::cout << "TilesetObject {\n"; std::cout << " position: { x: " << obj.position.x << ", y: " << obj.position.y << ", w: " << obj.position.w << ", h: " << obj.position.h << " }\n"; std::cout << " object_type: " << static_cast(obj.object_type) << "\n"; std::cout << " collectable: " << std::boolalpha << obj.collectable << "\n"; std::cout << " z_index: " << obj.z_index << "\n"; std::cout << " tileset_info: {\n"; std::cout << " set_id: " << obj.tileset_info.set_id << "\n"; std::cout << " object_id: " << obj.tileset_info.object_id << "\n"; std::cout << " set_category: " << static_cast(obj.tileset_info.set_category) << "\n"; std::cout << " set_position: { x: " << obj.tileset_info.set_position.x << ", y: " << obj.tileset_info.set_position.y << " }\n"; std::cout << " }\n"; std::cout << "}\n"; print_CollisionMap(obj); } /* bool is_BehindTileObject(TilesetObject object, SDL_FPoint position, SDL_FRect rect) { const int scale = Tile::tile_size / Tile::tile_collider_size; const int obj_w = object.position.w * scale; const int obj_h = object.position.h * scale; const int obj_x = position.x / scale; const int obj_y = position.y / scale; const int rect_x = rect.x / Tile::tile_collider_size; const int rect_y = rect.y / Tile::tile_collider_size; const int rect_w = (rect.w + Tile::tile_collider_size - 1) / Tile::tile_collider_size; //std::cout << "OB " << obj_x << " " << obj_y << " " << obj_w << " " << obj_h << std::endl; //std::cout << "RE " << rect_x << " " << rect_y << " " << rect_w << std::endl; const int row_width = obj_w; // horizontal overlap? if (rect_x + rect_w <= obj_x || rect_x >= obj_x + obj_w) return true; int start_x = std::max(rect_x, obj_x) - obj_x; int end_x = std::min(rect_x + rect_w, obj_x + obj_w) - obj_x; // rect completely above object if (rect_y < obj_y) return true; int rect_row = rect_y - obj_y; // rect completely below object if (rect_row >= obj_h) return true; // -------------------------------------------------------- // SCAN COLLIDER ROWS BELOW THE RECT // -------------------------------------------------------- //bool collission_above = false; bool collission_below = false; bool anywhere_above = false; bool anywhere_below = false; for (int y = 0; y < obj_h; ++y) { int base = y * row_width; for (int x = 0; x < obj_w; ++x) { if (object.collission_map[static_cast(base + x)]) { if (y < rect_row) { //std::cout << "ABOVE "; anywhere_above = true; if (x > start_x && x < end_x) { //collission_above = true; return false; } } else { //std::cout << "BELOW\n"; anywhere_below = true; if (x > start_x && x < end_x) { //std::cout << "BELOW"; collission_below = true; } } } } } if (anywhere_below && !collission_below) return true; if (collission_below) return true; if (!anywhere_above && !collission_below) return false; return false; } */ }