DX11 2D Game Programming
DX11_2020_0818_화_Store_Inventory_FileIO(tsv)
HI2
2020. 8. 18. 03:09
200818_Store_Inventory.zip
5.02MB
1. Item
더보기
#pragma once
class Store;
class ItemSlot;
enum ItemType
{
None,
Helmet,
Armor,
Boots,
Gloves,
Shield,
Weapon,
};
//
struct ItemData
{
int key;
ItemType type;
string name;
int value;
int price;
float frameX;
float frameY;
ItemData()
: key(0), type(None), name(""),
value(0), price(0), frameX(0), frameY(0) {};
//
ItemData(int _key, ItemType _type, string _name,
int _value, int _price, float _frameX, float _frameY)
:key(_key), type(_type), name(_name),
value(_value), price(_price), frameX(_frameX), frameY(_frameY) {}
//
~ItemData() {}
};
//
class Item
{
public:
Store* store;
Button* button;
ItemData data;
//
ItemSlot* slot;
public:
Item();
Item(const ItemData& _data);
~Item();
//
void Update();
void Render();
//
void CreateButton(wstring file);
//
void ShowInfo();
void SetStore(Store* value) { store = value; }
//
void SetButtonTextureFrame();
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Item.h"
#include "Store.h"
#include "ItemSlot.h"
Item::Item()
{
}
Item::Item(const ItemData& _data)
:store(nullptr), button(nullptr), data(), slot(nullptr)
{
data = _data;
//
CreateButton(L"Textures/Store/items.png");
//
}
Item::~Item()
{
delete button;
}
void Item::Update()
{
button->Update();
}
void Item::Render()
{
button->Render();
}
void Item::CreateButton(wstring file)
{
Texture* texture = Texture::Add(L"Textures/Store/items.png");
//
button = new Button(texture, { 6.0f, 6.0f }, { data.frameX, data.frameY });
//
button->SetEvent(bind(&Item::ShowInfo, this));
}
void Item::ShowInfo()
{
if(store)
store->selectedItemData = data;
}
void Item::SetButtonTextureFrame()
{
Vector2 textureFrame{ data.frameX, data.frameY };
button->SetTextureFrame(textureFrame);
}
2. ItemSlot
더보기
#pragma once
#include "Object/BasicObject/Quad.h"
#include "Object/GameObject/Item.h"
class Inventory;
class ItemSlot
{
public:
Quad* slot;
Item* item;
Inventory* inven;
//
public:
ItemSlot();
~ItemSlot();
//
void Update();
void Render();
//
void SetItem(Item* _item);
void SelectItem();
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "ItemSlot.h"
#include "Inventory.h"
ItemSlot::ItemSlot()
:item(nullptr), inven(nullptr)
{
slot = new Quad(L"Textures/Store/slot.png", L"TextureShader");
}
ItemSlot::~ItemSlot()
{
delete slot;
}
void ItemSlot::Update()
{
slot->Update();
if(item)
item->Update();
}
void ItemSlot::Render()
{
slot->Render();
if(item)
item->Render();
}
void ItemSlot::SetItem(Item* _item)
{
item = _item;
item->slot = this;
item->button->pos = slot->pos;
item->button->SetEvent(bind(&ItemSlot::SelectItem, this));
item->button->ResetParamEvent();
item->SetButtonTextureFrame();
}
void ItemSlot::SelectItem()
{
if (inven)
inven->selectedItem = item;
}
3. Store
더보기
#pragma once
//
#include "Object/GameObject/Item.h"
//
class Store : public Transform
{
private:
unordered_map<int, Item*> items;
UINT x;
UINT y;
public:
ItemData selectedItemData;
public:
Store(UINT _x, UINT _y);
~Store();
//
void Update();
void Render();
void PostRender();
//
void LoadStoreAndCreateItems();
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Store.h"
Store::Store(UINT _x, UINT _y)
:x(_x), y(_y), selectedItemData()
{
Vector2 itemSize{ 98.0f, 98.0f }; // item frame size
//
LoadStoreAndCreateItems();
// Set Store Transform
pos = itemSize;
scale.x = itemSize.x * x;
scale.y = itemSize.y * y;
// Set Item Transform
Vector2 startPos = pos;
//
for (UINT j = 0; j < y; ++j)
for (UINT i = 0; i < x; ++i)
{
Item* item = items[i + (j * x)];
Vector2 ButtonPos = startPos + Vector2{ itemSize.x * i, itemSize.y * j };
item->button->pos = ButtonPos;
}
}
Store::~Store()
{
for (auto item : items)
delete item.second;
items.clear();
}
void Store::Update()
{
for (auto item : items)
item.second->Update();
}
void Store::Render()
{
for (auto item : items)
item.second->Render();
}
void Store::PostRender()
{
ImGui::Text("[Store]");
ImGui::Text("- Selected Item -");
//
string type = "Type : ";
switch (selectedItemData.type)
{
case None: type += "None"; break;
case Helmet: type += "Helmet"; break;
case Armor: type += "Armor"; break;
case Gloves: type += "Gloves"; break;
case Boots: type += "Boots"; break;
case Shield: type += "Shiled"; break;
case Weapon: type += "Weapon"; break;
default:
break;
}
ImGui::Text(type.c_str());
//
if(selectedItemData.name == "")
ImGui::Text("empty");
else
ImGui::Text(selectedItemData.name.c_str());
//
ImGui::Text("Value : %d", selectedItemData.value);
ImGui::Text("Price : %d", selectedItemData.price);
}
void Store::LoadStoreAndCreateItems()
{
ifstream loadFile("Textures/Store/store.txt", ios::in);
string key{};
//
while (true)
{
ItemData data{};
//
loadFile >> key;
if (key == "key") // 처음 읽은 Data가 key 이면
{ // 첫번째 행 전부 읽어 폐기
string buffer{}; //
getline(loadFile, buffer);
continue;
}
else // data 행이면 key값 형변환 해서 저장(string -> int)
{
//if (key == "15")
// int i = 0;
data.key = stoi(key);
}
/* 참고 : FileStrem 은 -> int, string 을 자동 형변환 해준다 */
// int, string, float data들을 순차적으로 저장
int type{};
loadFile >> type;
data.type = (ItemType)type;
//
loadFile >> data.name >> data.value >> data.price >> data.frameX >> data.frameY;
// 데이터의 key값이 새로운 값이면 아이템 생성
items[data.key] = new Item(data);
//
items[data.key]->SetStore(this);
// 더 Load 할 data가 없으면 loop 종료
if (loadFile.eof())
break;
}
}
4. Inventory
더보기
#pragma once
//
#include "Object/GameObject/Item.h"
#include "Object/GameObject/ItemSlot.h"
#include "Object/GameObject/Status.h"
//
class Inventory : public Transform
{
public:
struct InventoryData
{
int slotNum;
ItemData itemData;
};
//
private:
UINT x;
UINT y;
//
vector<ItemSlot*> slots;
//
UINT money;
//
Status* status;
//
public:
Item* selectedItem;
public:
Inventory(UINT _x, UINT _y);
~Inventory();
//
void Update();
void Render();
void PostRender();
//
void CreateInventory();
//
void SetStatus(Status* value) { status = value; }
//
void Buy(ItemData value);
void Sell();
//
void Save();
void Load();
//
void Equip();
void UnEquip();
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Inventory.h"
Inventory::Inventory(UINT _x, UINT _y)
:x(_x), y(_y), money(100000), status(nullptr)
{
CreateInventory();
}
Inventory::~Inventory()
{
for (auto slot : slots)
delete slot;
slots.clear();
}
void Inventory::Update()
{
for (auto slot : slots)
slot->Update();
}
void Inventory::Render()
{
for (auto slot : slots)
slot->Render();
}
void Inventory::PostRender()
{
ImGui::Text("[Inventory]");
ImGui::Text("- money : %d -", money);
ImGui::Text("- Selected Item -");
string type = "Type : ";
if (selectedItem)
{
switch (selectedItem->data.type)
{
case None: type += "None"; break;
case Helmet: type += "Helmet"; break;
case Armor: type += "Armor"; break;
case Gloves: type += "Gloves"; break;
case Boots: type += "Boots"; break;
case Shield: type += "Shiled"; break;
case Weapon: type += "Weapon"; break;
default:
break;
}
ImGui::Text(type.c_str());
//
if (selectedItem->data.name == "")
ImGui::Text("empty");
else
ImGui::Text(selectedItem->data.name.c_str());
//
ImGui::Text("Value : %d", selectedItem->data.value);
ImGui::Text("Price : %d", selectedItem->data.price);
}
//
ImGui::Text("--------------------------------");
ImGui::Text("- Items -");
for (auto slot : slots)
{
if (slot->item)
{
if (slot->item->data.name == "")
continue;
else
ImGui::Text(slot->item->data.name.c_str());
}
}
ImGui::Text("================================");
}
void Inventory::CreateInventory()
{
Vector2 itemSize{ 98.0f, 98.0f };
// Set Inventory Transform
pos.x = (itemSize.x * (float)x) * 2.2f;
pos.y = itemSize.y;
scale.x = itemSize.x * x;
scale.y = itemSize.y * y;
// Create Slots
for (UINT j = 0; j < y; ++j)
for (UINT i = 0; i < x; ++i)
{
ItemSlot* itemSlot = new ItemSlot;
Vector2 slotPos = pos + Vector2{ itemSize.x * i, itemSize.y * j };
itemSlot->slot->pos = slotPos;
itemSlot->inven = this;
//
slots.emplace_back(itemSlot);
}
}
void Inventory::Buy(ItemData data)
{
// Check Item Slot
int keyIdx = 0;
while (true)
{
if (keyIdx >= 16)
return;
//
if (slots[keyIdx]->item)
{
++keyIdx;
continue;
}
else
break;
}
Item* tempItem = new Item(data);
slots[keyIdx]->SetItem(tempItem);
//
money -= data.price;
}
void Inventory::Sell()
{ // 미구현
if (!selectedItem)
return;
//
money += selectedItem->data.price;
//
selectedItem->slot->item = nullptr;
//
delete selectedItem;
selectedItem = nullptr;
}
void Inventory::Save()
{
BinaryWriter writer(L"TextData/inventory.inv"); // 확장자 무관
//
writer.UInt(money);
//
UINT size{};
for (int i = 0; i < slots.size(); ++i)
if (slots[i]->item)
++size;
//
writer.UInt(size);
//
for (UINT i = 0; i < slots.size() ; ++i)
{
InventoryData invData{};
if (slots[i]->item)
{
invData.slotNum = i;
invData.itemData = slots[i]->item->data;
//
writer.UInt(invData.slotNum);
//
writer.UInt(invData.itemData.key);
writer.UInt(invData.itemData.type);
writer.String(invData.itemData.name);
writer.UInt(invData.itemData.value);
writer.UInt(invData.itemData.price);
writer.Float(invData.itemData.frameX);
writer.Float(invData.itemData.frameY);
}
}
status->Save();
}
void Inventory::Load()
{
// Clear Slots
for (auto slot : slots)
if (slot->item)
{
delete slot->item;
slot->item = nullptr;
}
//
BinaryReader reader(L"TextData/inventory.inv"); // 확장자 무관
// load money
UINT money = reader.UInt();
this->money = money;
//
UINT size = reader.UInt();
//
for(int i = 0; i < size ; ++i)
{
InventoryData invData{};
//
invData.slotNum = reader.UInt();
//
invData.itemData.key = reader.UInt();
invData.itemData.type = (ItemType)reader.UInt();
invData.itemData.name = reader.String();
invData.itemData.value = reader.UInt();
invData.itemData.price = reader.UInt();
invData.itemData.frameX = reader.Float();
invData.itemData.frameY = reader.Float();
//
Item* item = new Item(invData.itemData);
slots[invData.slotNum]->SetItem(item);
}
status->Load();
}
void Inventory::Equip()
{
if (!selectedItem)
return;
//
if (status->equipedItems[((int)(selectedItem->data.type) - 1)])
{ // 착용할 부위에 아이템 있을 시 Swap
Item* tempItem = status->equipedItems[((int)(selectedItem->data.type) - 1)];
status->equipedItems[((int)(selectedItem->data.type) - 1)] = selectedItem;
selectedItem->slot->SetItem(tempItem);
}
else
{
status->equipedItems[((int)(selectedItem->data.type) - 1)] = selectedItem;
selectedItem->slot->item = nullptr;
}
status->SetEquipedItemData();
selectedItem = nullptr;
}
void Inventory::UnEquip()
{
if (!status->selectedItem)
return;
//
// Check Item Slot
int keyIdx = 0;
while (true)
{
if (keyIdx >= 16)
return;
//
if (slots[keyIdx]->item)
{
++keyIdx;
continue;
}
else
break;
}
slots[keyIdx]->SetItem(status->selectedItem);
//
status->equipedItems[((int)(status->selectedItem->data.type) - 1)] = nullptr;
status->selectedItem = nullptr;
}
5. Status
더보기
#pragma once
#include "Object/GameObject/Item.h"
class Status
{
private:
Quad* quad;
//
int hp;
int mp;
int attack;
int armor;
float moveSpeed;
float attackSpeed;
//
Vector2 itemPos[6];
public:
Item* equipedItems[6];
Item* selectedItem;
//
public:
Status();
~Status();
//
void Update();
void Render();
void PostRender();
//
void Open();
void Close();
//
void SetEquipedItemData();
void SelectItem(void* item);
//
void Save();
void Load();
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "Status.h"
Status::Status()
:hp(0), mp(0), attack(0), armor(0), moveSpeed(0), attackSpeed(0),
selectedItem(nullptr)
{
quad = new Quad(L"Textures/Store/status.png", L"TextureShader");
quad->pos = { CENTER_X, CENTER_Y };
// Set Default Item pos To Center
memset(itemPos, 0, 6);
for (int i = 0; i < 6; ++i)
itemPos[i] = quad->pos;
// Set Each Status Item Equip Pos
itemPos[0].y += 120.0f; // Helmet
//
itemPos[1].y += 10.0f; // Armor
//
itemPos[2].y -= 100.0f; // Boots
//
itemPos[3].x -= 110.0f; // Glove
itemPos[3].y += 65.0f; // Glove
//
itemPos[4].x += 110.0f; // Shield
itemPos[4].y -= 45.0f; // Shield
//
itemPos[5].x -= 110.0f; // Weapon
itemPos[5].y -= 45.0f; // Weapon
//
memset(equipedItems, 0, 6);
}
Status::~Status()
{
delete quad;
}
void Status::Update()
{
quad->Update();
//
for (int i = 0; i < 6; ++i)
if(equipedItems[i])
if (equipedItems[i]->button->isActive)
equipedItems[i]->Update();
}
void Status::Render()
{
quad->Render();
//
for (int i = 0; i < 6; ++i)
if(equipedItems[i])
if (equipedItems[i]->button->isActive)
equipedItems[i]->Render();
}
void Status::PostRender()
{
ImGui::Text("[Status]");
ImGui::Text("--------------------------------");
ImGui::Text("HP : %d", hp);
ImGui::Text("MP : %d", mp);
ImGui::Text("Attack : %d", attack);
ImGui::Text("Armor : %d", armor);
ImGui::Text("MoveSpeed : %.3f", moveSpeed);
ImGui::Text("AttackSpeed : %.3f", attackSpeed);
ImGui::Text("--------------------------------");
ImGui::Text("- Equiped Items -");
for(int i = 0 ; i < 6 ; ++i)
if(equipedItems[i])
ImGui::Text(equipedItems[i]->data.name.c_str());
ImGui::Text("--------------------------------");
ImGui::Text("- Selected Item -");
string type = "Type : ";
if (selectedItem)
{
switch (selectedItem->data.type)
{
case None: type += "None"; break;
case Helmet: type += "Helmet"; break;
case Armor: type += "Armor"; break;
case Gloves: type += "Gloves"; break;
case Boots: type += "Boots"; break;
case Shield: type += "Shiled"; break;
case Weapon: type += "Weapon"; break;
default:
break;
}
ImGui::Text(type.c_str());
//
if (selectedItem->data.name == "")
ImGui::Text("empty");
else
ImGui::Text(selectedItem->data.name.c_str());
//
ImGui::Text("Value : %d", selectedItem->data.value);
ImGui::Text("Price : %d", selectedItem->data.price);
}
}
void Status::Open()
{
quad->isActive = true;
//
for (int i = 0; i < 6; ++i)
if (equipedItems[i])
equipedItems[i]->button->isActive = true;
}
void Status::Close()
{
quad->isActive = false;
//
for (int i = 0; i < 6; ++i)
if (equipedItems[i])
equipedItems[i]->button->isActive = false;
}
void Status::SetEquipedItemData()
{
int tempHP{}; int tempMP{};
int tempAttack{}; int tempArmor{};
float tempMoveSpeed{}; float tempAttackSpeed{};
//
for(int i = 0 ; i < 6 ; ++i)
{
if (equipedItems[i])
{
if(!quad->isActive)
equipedItems[i]->button->isActive = false;
//
equipedItems[i]->button->pos = itemPos[i];
switch (equipedItems[i]->data.type)
{
case Helmet: tempMP += equipedItems[i]->data.value; break;
case Armor: tempHP += equipedItems[i]->data.value; break;
case Boots: tempMoveSpeed += equipedItems[i]->data.value; break;
case Gloves: tempAttackSpeed += equipedItems[i]->data.value; break;
case Shield: tempArmor += equipedItems[i]->data.value; break;
case Weapon: tempAttack += equipedItems[i]->data.value; break;
default: break;
}
equipedItems[i]->button->SetEvent(bind(&Status::SelectItem, this, placeholders::_1), equipedItems[i]);
equipedItems[i]->button->ResetEvent();
}
}
hp = tempHP; mp = tempMP;
attack = tempAttack; armor = tempArmor;
moveSpeed = tempMoveSpeed; attackSpeed = tempAttackSpeed;
//
}
void Status::SelectItem(void* item)
{
selectedItem = (Item*)item;
}
void Status::Save()
{
BinaryWriter writer(L"TextData/status.stat"); // 확장자 무관
//
UINT size{};
for (int i = 0; i < 6; ++i)
if (equipedItems[i])
++size;
//
writer.UInt(size);
//
for (UINT i = 0; i < 6 ; ++i)
{
if (equipedItems[i])
{
writer.UInt(i);
//
writer.UInt(equipedItems[i]->data.key);
writer.UInt(equipedItems[i]->data.type);
writer.String(equipedItems[i]->data.name);
writer.UInt(equipedItems[i]->data.value);
writer.UInt(equipedItems[i]->data.price);
writer.Float(equipedItems[i]->data.frameX);
writer.Float(equipedItems[i]->data.frameY);
}
}
}
void Status::Load()
{
// Clear equipedItems
for (auto item : equipedItems)
if (item)
{
delete item;
item = nullptr;
}
//
BinaryReader reader(L"TextData/status.stat"); // 확장자 무관
//
UINT size = reader.UInt();
//
for(int i = 0; i < size ; ++i)
{
int index = reader.UInt();
//
ItemData data{};
data.key = reader.UInt();
data.type = (ItemType)reader.UInt();
data.name = reader.String();
data.value = reader.UInt();
data.price = reader.UInt();
data.frameX = reader.Float();
data.frameY = reader.Float();
//
Item* tempItem = new Item(data);
//
equipedItems[index] = tempItem;
}
//
SetEquipedItemData();
}
6. GameScene
더보기
#pragma once
//
#include "Object/GameObject/Store.h"
#include "Object/GameObject/Inventory.h"
#include "Object/GameObject/Status.h"
//
class StoreScene : public Scene
{
private:
Store* store;
Inventory* inven;
Status* status;
//
public:
StoreScene();
~StoreScene();
//
virtual void Update() override;
virtual void Render() override;
virtual void PostRender() override;
};
////////////////////////////////////////////////////////////////////////////////////////////
#include "Framework.h"
#include "StoreScene.h"
StoreScene::StoreScene()
{
store = new Store(6, 6);
inven = new Inventory(4, 4);
status = new Status;
//
inven->SetStatus(status);
}
StoreScene::~StoreScene()
{
delete status;
delete inven;
delete store;
}
void StoreScene::Update()
{
store->Update();
inven->Update();
status->Update();
}
void StoreScene::Render()
{
store->Render();
inven->Render();
status->Render();
}
void StoreScene::PostRender()
{
ImGui::Text("================================");
// store
store->PostRender();
if (ImGui::Button("Buy", { 64, 32 }))
inven->Buy(store->selectedItemData);
if (ImGui::Button("Sell", { 64, 32 }))
inven->Sell();
ImGui::Text("================================");
// inventory
inven->PostRender();
if (ImGui::Button("Equip", { 64, 32 }))
inven->Equip();
if (ImGui::Button("UnEquip", { 64, 32 }))
inven->UnEquip();
ImGui::Text("================================");
// status
status->PostRender();
if (ImGui::Button("Open", { 64, 32 }))
status->Open();
if (ImGui::Button("Close", { 64, 32 }))
status->Close();
// save & load
ImGui::Text("================================");
if (ImGui::Button("Save", { 64, 32 }))
inven->Save();
if (ImGui::Button("Load", { 64, 32 }))
inven->Load();
}