mapcreator git · master
SDL3 2.5D game and engine using assets, with map editor
C++ 99.3%git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gzAdd planting seeds
src/character/character.cpp | 43 +++++++++--- src/character/character.hpp | 1 + src/character/message.cpp | 1 + src/character/message.hpp | 1 + src/inventory/inventory.cpp | 157 +++++++++++++++++++++++++++++++++++++++++- src/inventory/inventory.hpp | 18 ++++- src/map/map.cpp | 6 +- src/vegetables/vegetables.cpp | 18 ++--- src/vegetables/vegetables.hpp | 4 +- 9 files changed, 222 insertions(+), 27 deletions(-) diff --git a/src/character/character.cpp b/src/character/character.cpp index 2013441..2369794 100644 --- a/src/character/character.cpp +++ b/src/character/character.cpp @@ -63,7 +63,7 @@ Character::Init(SDL_Renderer* renderer) { attacking_logic = { 0.0f, nullptr, AttackingLogicStatus_e::NONE, false, nullptr }; consuming_logic = { 0.0f, 3.0f, false, nullptr }; cultivation_logic = { 0.0f, 3.0f, false, false, {0,0} }; - planting_logic = { 0.0f, 3.0f, false, {0,0}, VegetableData::Type::NONE }; + planting_logic = { 0.0f, 3.0f, false, {0,0}, VegetableData::Type::NONE, false}; sprintstart_logic = {0, 0.8, false}; death_duration = 0; @@ -532,9 +532,14 @@ Character::collect_Object() { // Remove object from MapTileObject s Object* object = Object::get_ObjectById(collecting_logic.object->object_id); - if (object->object_type == ObjectType::VEGETABLE) - inventory->add_Vegetable(static_cast<Vegetable*>(object)->type, static_cast<Vegetable*>(object)->quantity, messages.get()); - else + if (object->object_type == ObjectType::VEGETABLE) { + Vegetable* v = static_cast<Vegetable*>(object); + std::cout << "ISSEED " << v->is_seed << std::endl; + if (v->is_seed) + inventory->add_Seed(v->type, v->quantity, messages.get()); + else + inventory->add_Vegetable(v->type, v->quantity, messages.get()); + } else inventory->add_Resource(collecting_logic.resource.resource, static_cast<int>(collecting_logic.resource.quantity), messages.get()); /* resources[collecting_logic.resource.resource] += collecting_logic.resource.quantity; @@ -910,9 +915,11 @@ Character::plant_Start() { set_Status(CharacterStatus::PLANTING); handle_Animation(); + planting_logic.is_planting = true; planting_logic.tile_world = tile_world; planting_logic.type = static_cast<InventoryVegetable*>(selected_item)->type; + planting_logic.is_seed = !static_cast<InventoryVegetable*>(selected_item)->is_seed; } void @@ -932,12 +939,14 @@ Character::plant_Vegetable() { } if (planting_logic.duration >= planting_logic.duration_max) { - std::cout << "DEF " << (int)planting_logic.type << std::endl; - Vegetable* v = new Vegetable(planting_logic.type, planting_logic.tile_world); + Vegetable* v = new Vegetable(planting_logic.type, planting_logic.tile_world, planting_logic.is_seed); TileObject to = {{0,0}, true, v->id}; size_t id = Map::get_IdFromTilePoint(planting_logic.tile_world); - std::cout << " " << id << std::endl; Map::tile_map[id].objects.push_back(to); + if (!planting_logic.is_seed) // YES thats reversed! + inventory->remove_Seed(planting_logic.type, 1); + else + inventory->remove_Vegetable(planting_logic.type, 1); plant_Stop(); } @@ -1413,8 +1422,16 @@ Character::handle_Input(Input& input, SDL_Rect win_size) { if (inventory->selected_inventory.vegetable != VegetableData::Type::NONE) { InventoryVegetable& iv = inventory->vegetables.at(inventory->selected_inventory.vegetable); setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, &iv); + std::cout << "NOOO \n"; + //inventory->Equip(it); + } else + if (inventory->selected_inventory.seed != VegetableData::Type::NONE) { + InventoryVegetable& iv = inventory->seeds.at(inventory->selected_inventory.seed); + std::cout << "JEEE " << iv.is_seed << "\n"; + setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, &iv); //inventory->Equip(it); } else { + std::cout << "FUCK \n"; setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, inventory->selected_inventory.item); if (setted_hotbar) { if (sel_item) inventory->Equip(sel_item); @@ -1581,11 +1598,15 @@ Character::handle_Input(Input& input, SDL_Rect win_size) { attack_Start(); return; } - } else - if (selected_item->object_type == InventoryObjectType::VEGETABLE) { + } else { if (!planting_logic.is_planting) { - plant_Start(); - return; + switch (selected_item->object_type) { + case InventoryObjectType::VEGETABLE: + case InventoryObjectType::SEED: + plant_Start(); + return; + default: break; + } } } } else diff --git a/src/character/character.hpp b/src/character/character.hpp index c845648..e471761 100644 --- a/src/character/character.hpp +++ b/src/character/character.hpp @@ -102,6 +102,7 @@ struct CharacterPlantingLogic { bool is_planting; SDL_Point tile_world; VegetableData::Type type; + bool is_seed; }; struct CharacterStats { diff --git a/src/character/message.cpp b/src/character/message.cpp index 888da34..2eabcf7 100644 --- a/src/character/message.cpp +++ b/src/character/message.cpp @@ -24,6 +24,7 @@ Messages::Messages() { {MessageKey::ADD_INVENTORY, {10, MessageType::INVENTORY, "Added item: "}}, {MessageKey::ADD_RESOURCE, {10, MessageType::RESOURCE, "Resource "}}, {MessageKey::ADD_VEGETABLE, {10, MessageType::VEGETABLE, "Vegetable "}}, + {MessageKey::ADD_VEGETABLE_SEED, {10, MessageType::VEGETABLE, "Seed "}}, {MessageKey::NOTHING_TO_INTERACT, {4, MessageType::CHARACTER, "I cant find anything to interact with.."}}, }; } diff --git a/src/character/message.hpp b/src/character/message.hpp index 6724ef8..bc3656d 100644 --- a/src/character/message.hpp +++ b/src/character/message.hpp @@ -36,6 +36,7 @@ enum class MessageKey { ADD_INVENTORY, ADD_RESOURCE, ADD_VEGETABLE, + ADD_VEGETABLE_SEED, NOTHING_TO_INTERACT, }; diff --git a/src/inventory/inventory.cpp b/src/inventory/inventory.cpp index 26614da..f50b850 100644 --- a/src/inventory/inventory.cpp +++ b/src/inventory/inventory.cpp @@ -85,7 +85,7 @@ void Inventory::Unequip(EquipmentSlot slot) { // VEGETABLE void Inventory::add_Vegetable(VegetableData::Type type, size_t amount, Messages* messages) { - auto [it, inserted] = vegetables.try_emplace(type, InventoryVegetable(next_item_id, type)); + auto [it, inserted] = vegetables.try_emplace(type, InventoryVegetable(next_item_id, type, false)); if (inserted) next_item_id++; @@ -103,6 +103,7 @@ Inventory::remove_Vegetable(VegetableData::Type type, size_t amount) { if (it == vegetables.end() || it->second.count < amount) return false; + std::cout << "TSCHÖÖ VEG\n"; it->second.count -= amount; if (it->second.count == 0) vegetables.erase(it); @@ -115,6 +116,39 @@ Inventory::get_Vegetable(VegetableData::Type type) const { return (it != vegetables.end()) ? it->second.count : 0; } +// SEED +void +Inventory::add_Seed(VegetableData::Type type, size_t amount, Messages* messages) { + auto [it, inserted] = seeds.try_emplace(type, InventoryVegetable(next_item_id, type, true)); + if (inserted) + next_item_id++; + + it->second.count += amount; + + auto* t = new VegetableData::Type(type); + std::cout << "ADD VEGETABLE TYPE: " << static_cast<int>(*t) << std::endl; + if (messages) + messages->Add(MessageKey::ADD_VEGETABLE_SEED, static_cast<void*>(t)); +} + +bool +Inventory::remove_Seed(VegetableData::Type type, size_t amount) { + std::cout << "TSCHÖÖ\n"; + auto it = seeds.find(type); + if (it == seeds.end() || it->second.count < amount) + return false; + + it->second.count -= amount; + if (it->second.count == 0) + seeds.erase(it); + return true; +} + +int +Inventory::get_Seed(VegetableData::Type type) const { + auto it = seeds.find(type); + return (it != seeds.end()) ? it->second.count : 0; +} // RESOURCE void @@ -504,6 +538,15 @@ Inventory::draw_InfoPanel(SDL_Renderer* renderer, return; } + if (selected_item->seed != VegetableData::Type::NONE) + { + const auto& def = + VegetableData::crop_defs[static_cast<uint32_t>(selected_item->seed)]; + std::string name = std::string(def.name) + " seed"; + draw_line(name); + return; + } + if (selected_item->item) { auto* inv_item = @@ -600,6 +643,7 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) { int index = 0; + // RESOURCE for (auto& pair : resources) { if (pair.second <= 0) continue; @@ -617,6 +661,7 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) { index++; } + // VEGETABLE for (auto& pair : vegetables) { if (pair.second.count <= 0) continue; @@ -636,6 +681,27 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) { index++; } + // SEEDS + for (auto& pair : seeds) { + if (pair.second.count <= 0) continue; + + //std::cout << "ITM: " << (int)pair.first << " " << pair.second << std::endl; + if (index >= inventory_grid_cols * inventory_grid_rows) break; + + + VegetableData::Type type = pair.first; + const VegetableData::CropDefinition* data = VegetableData::get_DataByType(type); + + auto pos = get_tile_position(index); + bool highlight = (selected_inventory.is_valid && + selected_inventory.seed == pair.first); + + //std::cout << "DAT: " <<data.icon_tile_x << " " << data.icon_tile_y << std::endl; + draw_icon(pos.first, pos.second, {data->icon_tile_x-1, data->icon_tile_y}, pair.second.count, highlight); + index++; + } + + // ITEM -> TOOL/WEAPON for (auto& inv_item : items) { if (index >= inventory_grid_cols * inventory_grid_rows) break; @@ -716,6 +782,30 @@ Inventory::hit_InventoryGrid(const SDL_FPoint& mouse) { index++; } + for (auto& pair : seeds) { + if (pair.second.count <= 0) continue; + + if (index >= inventory_grid_cols * inventory_grid_rows) break; + + + VegetableData::Type type = pair.first; + const VegetableData::CropDefinition* data = VegetableData::get_DataByType(type); + + SDL_FRect r = rect_for_slot(index); + + if (mouse.x >= r.x && mouse.x <= r.x + r.w && + mouse.y >= r.y && mouse.y <= r.y + r.h) { + sel.is_valid = true; + sel.seed = type; + sel.vegetable = VegetableData::Type::NONE; + sel.resource = ResourceType::NONE; + sel.item = nullptr; + sel.tile = {data->icon_tile_x, data->icon_tile_y}; + return sel; + } + + index++; + } for (auto &inv_item : items) { @@ -865,6 +955,14 @@ Inventory::draw_Hotbar(SDL_Renderer* renderer, TTF_Font* font) { SDL_FRect src{ data->icon_tile_x * 16.f, data->icon_tile_y * 16.f, 16.f, 16.f }; SDL_FRect dst{ x, y, slot_size, slot_size }; SDL_RenderTexture(renderer, Icon::icons_texture, &src, &dst); + } else + if (hotbar[i].type == InventoryObjectType::SEED) { + InventoryVegetable& item = get_SeedById(hotbar[i].item_id); + const VegetableData::CropDefinition* + data = get_DataByType(item.type); + SDL_FRect src{ (data->icon_tile_x-1) * 16.f, data->icon_tile_y * 16.f, 16.f, 16.f }; + SDL_FRect dst{ x, y, slot_size, slot_size }; + SDL_RenderTexture(renderer, Icon::icons_texture, &src, &dst); } } @@ -904,6 +1002,9 @@ Inventory_s* Inventory::get_SelectedHotbarItem() { else if (eq.type == InventoryObjectType::VEGETABLE) item = &get_VegetableById(hotbar[selected_hotbar].item_id); + else + if (eq.type == InventoryObjectType::SEED) + item = &get_SeedById(hotbar[selected_hotbar].item_id); if (selected_hotbar == 0 || !item) { std::cout << "Something is broken,... " << selected_hotbar << " " << hotbar[selected_hotbar].item_id << std::endl; @@ -926,6 +1027,13 @@ InventoryVegetable& Inventory::get_VegetableById(size_t id) { throw std::out_of_range("Vegetable not found"); } +InventoryVegetable& Inventory::get_SeedById(size_t id) { + for (auto &item : seeds) + if (item.second.id == id) + return item.second; + throw std::out_of_range("Vegetable not found"); +} + @@ -958,6 +1066,15 @@ static void WriteVegetable(std::ofstream &file, const InventoryVegetable &veg) { } +static void WriteSeed(std::ofstream &file, const InventoryVegetable &veg) { + file.write(reinterpret_cast<const char*>(&veg.object_type), sizeof(veg.object_type)); + + file.write(reinterpret_cast<const char*>(&veg.id), sizeof(veg.id)); + file.write(reinterpret_cast<const char*>(&veg.equipement_slot), sizeof(veg.equipement_slot)); + file.write(reinterpret_cast<const char*>(&veg.type), sizeof(veg.type)); + file.write(reinterpret_cast<const char*>(&veg.count), sizeof(veg.count)); +} + bool Inventory::Save(const std::string &path) const { std::ofstream file(path + "/inventory", std::ios::binary | std::ios::trunc); std::cout << "Save Inventory\n"; @@ -993,6 +1110,14 @@ bool Inventory::Save(const std::string &path) const { for (const auto &pair : vegetables) WriteVegetable(file, pair.second); + + // seed + count = seeds.size(); + std::cout << "Seeds COUNT WRITE: " << count << std::endl; + file.write(reinterpret_cast<const char*>(&count), sizeof(count)); + + for (const auto &pair : seeds) + WriteSeed(file, pair.second); } // equipment slot item_id @@ -1045,7 +1170,16 @@ static InventoryItem* ReadItem(std::ifstream &file) { return it; } static InventoryVegetable* ReadVegetable(std::ifstream &file) { - auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE); + auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE, false); + ReadBase(file, veg); + + file.read(reinterpret_cast<char*>(&veg->type), sizeof(veg->type)); + file.read(reinterpret_cast<char*>(&veg->count), sizeof(veg->count)); + + return veg; +} +static InventoryVegetable* ReadSeed(std::ifstream &file) { + auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE, true); ReadBase(file, veg); file.read(reinterpret_cast<char*>(&veg->type), sizeof(veg->type)); @@ -1069,6 +1203,11 @@ static Inventory_s* ReadObject(std::ifstream &file) veg->object_type = ot; return veg; } + case InventoryObjectType::SEED: { + auto* veg = ReadSeed(file); + veg->object_type = ot; + return veg; + } default: return nullptr; @@ -1136,6 +1275,20 @@ bool Inventory::Load(const std::string &path) { // we no longer need the allocated pointer after copying delete veg; } + count = 0; + file.read(reinterpret_cast<char*>(&count), sizeof(count)); + for (uint32_t i = 0; i < count; ++i) { + Inventory_s *obj = ReadObject(file); + InventoryVegetable* veg = static_cast<InventoryVegetable*>(obj); + + seeds.try_emplace(veg->type, *veg); + if (veg->id > next_item_id) + next_item_id = veg->id; + + std::cout << "SEED SIZ " << seeds.size() << std::endl; + // we no longer need the allocated pointer after copying + delete veg; + } next_item_id++; } diff --git a/src/inventory/inventory.hpp b/src/inventory/inventory.hpp index e4aefe7..e1d7cda 100644 --- a/src/inventory/inventory.hpp +++ b/src/inventory/inventory.hpp @@ -15,7 +15,8 @@ enum class InventoryObjectType : uint8_t { NONE, ITEM, - VEGETABLE + VEGETABLE, + SEED }; struct Inventory_s { @@ -49,13 +50,15 @@ struct InventoryItem : Inventory_s { struct InventoryVegetable : Inventory_s { size_t count = 0; + bool is_seed = false; VegetableData::Type type; - InventoryVegetable(size_t d, VegetableData::Type t) - : Inventory_s(d, InventoryObjectType::VEGETABLE), type(t) + InventoryVegetable(size_t d, VegetableData::Type t, bool s) + : Inventory_s(d, s ? InventoryObjectType::SEED : InventoryObjectType::VEGETABLE), is_seed(s), type(t) { } }; + static constexpr int HOTBAR_SLOTS = 7; // 0 == HANDS struct Equipement { @@ -67,6 +70,7 @@ struct InventorySelection { Inventory_s* item = nullptr; ResourceType resource = ResourceType::NONE; VegetableData::Type vegetable = VegetableData::Type::NONE; + VegetableData::Type seed = VegetableData::Type::NONE; Icon::TilePos tile; bool is_valid = false; }; @@ -92,6 +96,8 @@ public: std::unordered_map<ResourceType, int> resources; std::unordered_map<VegetableData::Type, InventoryVegetable> vegetables; + std::unordered_map<VegetableData::Type, InventoryVegetable> + seeds; std::list<std::unique_ptr<InventoryItem>> items; @@ -106,6 +112,10 @@ public: bool remove_Vegetable(VegetableData::Type type, size_t amount); int get_Vegetable(VegetableData::Type type) const; + void add_Seed(VegetableData::Type, size_t amount, Messages*); + bool remove_Seed(VegetableData::Type type, size_t amount); + int get_Seed(VegetableData::Type type) const; + void add_Resource(ResourceType type, int amount, Messages* messages); bool remove_Resource(ResourceType type, int amount); int get_Resource(ResourceType type) const; @@ -118,6 +128,8 @@ public: get_ItemById(size_t id); InventoryVegetable& get_VegetableById(size_t id); + InventoryVegetable& + get_SeedById(size_t id); // EQUIPEMENT void Unequip(EquipmentSlot); diff --git a/src/map/map.cpp b/src/map/map.cpp index e8039c1..c26ec35 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -372,6 +372,8 @@ namespace Map { auto type = static_cast<int>(v->type); file.write(reinterpret_cast<const char*>(&type), sizeof(type)); + file.write(reinterpret_cast<const char*>(&v->is_seed), + sizeof(v->is_seed)); file.write(reinterpret_cast<const char*>(&v->quantity), sizeof(v->quantity)); @@ -579,9 +581,11 @@ namespace Map { case ObjectCategory::FARM_CROP: { int type_i; + bool is_seed; file.read(reinterpret_cast<char*>(&type_i), sizeof(type_i)); + file.read(reinterpret_cast<char*>(&is_seed), sizeof(is_seed)); - Vegetable* v = new Vegetable(static_cast<VegetableData::Type>(type_i), wp); + Vegetable* v = new Vegetable(static_cast<VegetableData::Type>(type_i), wp, is_seed); file.read(reinterpret_cast<char*>(&v->quantity), sizeof(v->quantity)); file.read(reinterpret_cast<char*>(&v->growth_stage), diff --git a/src/vegetables/vegetables.cpp b/src/vegetables/vegetables.cpp index 3070e93..42e34cb 100644 --- a/src/vegetables/vegetables.cpp +++ b/src/vegetables/vegetables.cpp @@ -8,13 +8,13 @@ namespace VegetableData { const CropDefinition crop_defs[(int)Type::COUNT] = { // STAGE: 0 1 2 3 4 - { "",0,0,0,0,0,0,0,0,0,0,0 }, - { "carrot", 2,1, 5,1, 6,1, 7,1, 23,0, (5-2+1)+1}, - { "raddish", 2,3, 5,3, 6,3, 7,3, 23,1, (5-2+1)+1}, - { "cabbage", 2,5, 5,5, 6,5, 7,5, 23,2, (5-2+1)+1}, - { "salad", 2,7, 5,7, 6,7, 7,7, 23,3, (5-2+1)+1}, - { "broccoli", 2,9, 5,9, 6,9, 7,9, 23,4, (5-2+1)+1}, - { "onion", 2,11,5,11,6,11,7,11,23,5, (5-2+1)+1} + { "",0,0,0,0,0,0,0,0,0,0,0,false }, + { "carrot", 2,1, 5,1, 6,1, 7,1, 23,0, (5-2+1)+1, false}, + { "raddish", 2,3, 5,3, 6,3, 7,3, 23,1, (5-2+1)+1, false}, + { "cabbage", 2,5, 5,5, 6,5, 7,5, 23,2, (5-2+1)+1, false}, + { "salad", 2,7, 5,7, 6,7, 7,7, 23,3, (5-2+1)+1, false}, + { "broccoli", 2,9, 5,9, 6,9, 7,9, 23,4, (5-2+1)+1, false}, + { "onion", 2,11,5,11,6,11,7,11,23,5, (5-2+1)+1, false} }; const CropDefinition* get_DataByType(Type type) { @@ -27,7 +27,7 @@ namespace VegetableData { } } -Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos) +Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos, bool is_s) : Object(ObjectType::VEGETABLE, ObjectCategory::FARM_CROP, @@ -37,7 +37,7 @@ Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos) world_pos, {1,1}, 0), - type(t), + type(t), is_seed(is_s), growth_stage(0), next_update_sec(Default::get_TimeSinceStartInSec()), equipement_slot(EquipmentSlot::HAND_RIGHT) diff --git a/src/vegetables/vegetables.hpp b/src/vegetables/vegetables.hpp index f5c4b99..c83aa42 100644 --- a/src/vegetables/vegetables.hpp +++ b/src/vegetables/vegetables.hpp @@ -37,6 +37,7 @@ namespace VegetableData { int icon_tile_x; int icon_tile_y; size_t total_stages; // auto-calculated = (grown-start)+1 + rotten + bool is_seed; }; @@ -55,6 +56,7 @@ public: VegetableData::Type type; const VegetableData::CropDefinition* definition; size_t quantity = 2; + bool is_seed = false; size_t growth_stage; // 0 = planted, last = rotten double next_update_sec; // seconds since game start float collecting_duration_max; @@ -64,7 +66,7 @@ public: EquipmentSlot equipement_slot; - Vegetable(VegetableData::Type t, SDL_Point world_pos); + Vegetable(VegetableData::Type t, SDL_Point world_pos, bool is_s); SDL_Point get_SetPosition() override;