Player changes:

- reimplemented & improved player inventory
- now player has "Action2" which means he can interact with the
environment
- added weapon energy cost
- updated player action interface
This commit is contained in:
Tiberiu Chibici 2016-12-12 23:28:41 +02:00
parent 6fe33a99a8
commit 6a35b11ec2
34 changed files with 885 additions and 573 deletions

View File

@ -11,7 +11,8 @@
<Weapon damage="0.5" <Weapon damage="0.5"
critProbability="0" critProbability="0"
critDamage="0" critDamage="0"
attackDuration="0.2" /> attackDuration="0.2"
energyCost="1" />
<Hoe /> <Hoe />
</GameObject> </GameObject>
@ -25,7 +26,8 @@
<Weapon damage="0" <Weapon damage="0"
critProbability="0" critProbability="0"
critDamage="0" critDamage="0"
attackDuration="0.2" /> attackDuration="0.2"
energyCost="1" />
<WateringCan capacity="10" amountLeft="10" /> <WateringCan capacity="10" amountLeft="10" />
</GameObject> </GameObject>

View File

@ -11,7 +11,8 @@
<Weapon damage="3" <Weapon damage="3"
critProbability="0.01" critProbability="0.01"
critDamage="9" critDamage="9"
attackDuration="0.4" /> attackDuration="0.4"
energyCost="1.5" />
</GameObject> </GameObject>
<GameObject name="Level 2 Sword"> <GameObject name="Level 2 Sword">
@ -24,7 +25,8 @@
<Weapon damage="6" <Weapon damage="6"
critProbability="0.01" critProbability="0.01"
critDamage="18" critDamage="18"
attackDuration="0.4" /> attackDuration="0.4"
energyCost="0.9" />
</GameObject> </GameObject>
</ItemCollection> </ItemCollection>

View File

@ -26,12 +26,10 @@
<Transform x="120" y="100" /> <Transform x="120" y="100" />
<Sprite src="sprites/Player.sprite" /> <Sprite src="sprites/Player.sprite" />
<SpriteRenderer /> <SpriteRenderer />
<PlayerMovement /> <Inventory capacity="30" />
<PlayerInventory capacity="30" /> <Player hp="100" maxHp="100"
energy="100" maxEnergy="100"
<GameObject name="Inventory"> money="50" />
<Transform />
</GameObject>
</GameObject> </GameObject>
<!-- Debug object --> <!-- Debug object -->

View File

@ -0,0 +1,148 @@
/*
* Inventory.cpp
*
* Created on: Dec 11, 2016
* Author: tibi
*/
#include <components/basic/Inventory.h>
#include <components/basic/InventoryItem.h>
#include <iostream>
namespace farmlands {
namespace components {
namespace basic {
Inventory::Inventory()
: m_capacity(10),
m_items(nullptr)
{
}
Inventory::~Inventory()
{
delete[] m_items;
}
model::Component* Inventory::clone()
{
Inventory* clone = new Inventory();
clone->m_capacity = m_capacity;
return clone;
}
void Inventory::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: Inventory capacity=" << m_capacity << "\n";
}
void Inventory::onCreate()
{
// Allocate items array
m_items = new model::GameObject*[m_capacity];
memset(m_items, 0, sizeof(m_items[0]) * m_capacity);
// Find all children
for (auto it = gameObject->childrenBegin(); it != gameObject->childrenEnd(); it++)
{
InventoryItem* item = (*it)->component<InventoryItem>();
if (item)
{
Assert(item->slot >= 0 && item->slot < m_capacity, "Inventory item slot out of range.");
Assert(m_items[item->slot] == nullptr, "Multiple items on one slot.");
m_items[item->slot] = *it;
}
}
}
bool Inventory::add(model::GameObject* item)
{
Assert(m_items != nullptr, "Inventory not initialized");
Assert(item != nullptr, "Cannot add null object.");
// Find an empty slot
size_t slot = (size_t)-1;
for (size_t i = 0; i < m_capacity; i++)
if (m_items[i] == nullptr)
{
slot = i;
break;
}
if (slot != (size_t)-1)
{
set(slot, item);
return true;
}
return false;
}
void Inventory::remove(size_t slot)
{
Assert(m_items != nullptr, "Inventory not initialized.");
Assert(slot < m_capacity, "Slot out of range.");
if (m_items[slot] != nullptr)
{
m_items[slot]->removeComponent<InventoryItem>();
m_items[slot] = nullptr;
}
}
void Inventory::set(size_t slot, model::GameObject* item)
{
Assert(m_items != nullptr, "Inventory not initialized.");
Assert(slot < m_capacity, "Slot out of range.");
Assert(item != nullptr, "Cannot set null element.");
remove(slot);
m_items[slot] = item;
// Update InventoryItem
if (!item->haveComponent<InventoryItem>())
item->addComponent(new InventoryItem);
InventoryItem* invItem = item->component<InventoryItem>();
invItem->slot = slot;
}
model::GameObject* Inventory::get(size_t slot)
{
Assert(m_items != nullptr, "Inventory not initialized.");
Assert(slot < m_capacity, "Slot out of range.");
return m_items[slot];
}
void Inventory::setCapacity(size_t capacity)
{
if (m_items != nullptr)
{
// Remove extra items
for (size_t i = m_capacity; i < capacity; i++)
remove(i);
// Reallocate
model::GameObject** old = m_items;
m_items = new model::GameObject*[capacity];
memset(m_items, 0, sizeof(m_items[0]) * capacity);
// Copy old objects
for (size_t i = 0; i < std::min(m_capacity, capacity); i++)
m_items[i] = old[i];
// Finish
delete[] old;
}
m_capacity = capacity;
}
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */

View File

@ -0,0 +1,77 @@
/*
* Inventory.h
*
* Created on: Dec 11, 2016
* Author: tibi
*/
#ifndef COMPONENTS_INVENTORY_INVENTORY_H_
#define COMPONENTS_INVENTORY_INVENTORY_H_
#include <model/Component.h>
#include <model/GameObject.h>
namespace farmlands {
namespace components {
namespace basic {
class Inventory: public model::Component
{
public:
Inventory();
virtual ~Inventory();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
virtual void onCreate() override;
// Inventory management
/**
* Adds a game object to first available slot.
* Game object should be already added as a child of the parent game object.
* If object doesn't have an "InventoryItem" component, it will be added.
* @returns true if added successfully, false if no empty slot was found.
*/
bool add(model::GameObject* item);
/**
* Removes the game object from the given slot.
* Doesn't delete/destroy the game object from the parent game object.
* Destroys the "InventoryItem" component of the object.
*/
void remove(size_t slot);
/**
* Sets the given game object (which should be a child of the parent game object) to have the given slot.
* If there is an item in that slot, it is removed.
*/
void set(size_t slot, model::GameObject* item);
/**
* Gets the game object in the given slot.
* Returns null if slot is empty.
*/
model::GameObject* get(size_t slot);
/**
* Modifies the capacity of the inventory.
* If the inventory is already initialized, objects might be removed.
*/
void setCapacity(size_t capacity);
/**
* Gets the capacity
*/
size_t capacity() const { return m_capacity; }
private:
size_t m_capacity;
model::GameObject** m_items;
};
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */
#endif /* COMPONENTS_INVENTORY_INVENTORY_H_ */

View File

@ -0,0 +1,36 @@
/*
* InventoryItem.cpp
*
* Created on: Dec 11, 2016
* Author: tibi
*/
#include <components/basic/InventoryItem.h>
#include <iostream>
namespace farmlands {
namespace components {
namespace basic {
InventoryItem::~InventoryItem()
{
}
model::Component* InventoryItem::clone()
{
InventoryItem* item = new InventoryItem();
item->slot = slot;
return item;
}
void InventoryItem::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: InventoryItem slot=" << slot << "\n";
}
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */

View File

@ -0,0 +1,32 @@
/*
* InventoryItem.h
*
* Created on: Dec 11, 2016
* Author: tibi
*/
#ifndef COMPONENTS_INVENTORY_INVENTORYITEM_H_
#define COMPONENTS_INVENTORY_INVENTORYITEM_H_
#include <model/Component.h>
namespace farmlands {
namespace components {
namespace basic {
class InventoryItem: public model::Component
{
public:
virtual ~InventoryItem();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
size_t slot;
};
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */
#endif /* COMPONENTS_INVENTORY_INVENTORYITEM_H_ */

View File

@ -34,7 +34,7 @@ void Axe::dump(unsigned level)
std::cout << " .Component: Axe\n"; std::cout << " .Component: Axe\n";
} }
void Axe::performAction(float x, float y, model::Direction d) void Axe::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
} }

View File

@ -8,14 +8,14 @@
#ifndef COMPONENTS_ITEMS_AXE_H_ #ifndef COMPONENTS_ITEMS_AXE_H_
#define COMPONENTS_ITEMS_AXE_H_ #define COMPONENTS_ITEMS_AXE_H_
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <model/Component.h> #include <model/Component.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Axe: public model::Component, public IPlayerAction class Axe: public model::Component, public model::IPlayerAction
{ {
public: public:
Axe(); Axe();
@ -24,7 +24,7 @@ namespace items {
virtual model::Component* clone() override; virtual model::Component* clone() override;
virtual void dump(unsigned level) override; virtual void dump(unsigned level) override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
}; };
} /* namespace items */ } /* namespace items */

View File

@ -26,7 +26,7 @@ model::Component* Giftable::clone()
return new Giftable(); return new Giftable();
} }
void Giftable::performAction(float x, float y, model::Direction d) void Giftable::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
} }

View File

@ -8,14 +8,14 @@
#ifndef CONTROLLER_ITEMS_GIFTABLE_H_ #ifndef CONTROLLER_ITEMS_GIFTABLE_H_
#define CONTROLLER_ITEMS_GIFTABLE_H_ #define CONTROLLER_ITEMS_GIFTABLE_H_
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <model/Component.h> #include <model/Component.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Giftable: public model::Component, public IPlayerAction class Giftable: public model::Component, public model::IPlayerAction
{ {
public: public:
Giftable(); Giftable();
@ -24,7 +24,7 @@ namespace items {
virtual model::Component* clone() override; virtual model::Component* clone() override;
virtual void dump(unsigned level) override; virtual void dump(unsigned level) override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
}; };
} /* namespace items */ } /* namespace items */

View File

@ -53,16 +53,13 @@ void Hoe::onInitialize()
m_map = (*it)->component<Map>(); m_map = (*it)->component<Map>();
} }
void Hoe::performAction(float x, float y, model::Direction d) void Hoe::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
Assert(m_map, "No background object!!!"); Assert(m_map, "No background object!!!");
// Compute watering position // Compute watering position
float digX, digY; size_t col = floorf(lookX);
translate(x, y, d, 0.5f, &digX, &digY); size_t row = floorf(lookY);
size_t col = floorf(digX);
size_t row = floorf(digY);
// See what the cell contains // See what the cell contains
Cell backCell = m_map->layer(0).get(row, col); Cell backCell = m_map->layer(0).get(row, col);

View File

@ -8,7 +8,7 @@
#ifndef COMPONENTS_ITEMS_HOE_H_ #ifndef COMPONENTS_ITEMS_HOE_H_
#define COMPONENTS_ITEMS_HOE_H_ #define COMPONENTS_ITEMS_HOE_H_
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <components/Map.h> #include <components/Map.h>
#include <model/Component.h> #include <model/Component.h>
#include <model/Direction.h> #include <model/Direction.h>
@ -17,7 +17,7 @@ namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Hoe: public model::Component, public IPlayerAction class Hoe: public model::Component, public model::IPlayerAction
{ {
public: public:
Hoe(); Hoe();
@ -28,7 +28,7 @@ namespace items {
virtual void onInitialize() override; virtual void onInitialize() override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
private: private:
Map* m_map; Map* m_map;

View File

@ -34,7 +34,7 @@ void Pickaxe::dump(unsigned level)
std::cout << " .Component: Pickaxe\n"; std::cout << " .Component: Pickaxe\n";
} }
void Pickaxe::performAction(float x, float y, model::Direction d) void Pickaxe::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
} }

View File

@ -8,14 +8,14 @@
#ifndef COMPONENTS_ITEMS_PICKAXE_H_ #ifndef COMPONENTS_ITEMS_PICKAXE_H_
#define COMPONENTS_ITEMS_PICKAXE_H_ #define COMPONENTS_ITEMS_PICKAXE_H_
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <model/Component.h> #include <model/Component.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Pickaxe: public model::Component, public IPlayerAction class Pickaxe: public model::Component, public model::IPlayerAction
{ {
public: public:
Pickaxe(); Pickaxe();
@ -24,7 +24,7 @@ namespace items {
virtual model::Component* clone() override; virtual model::Component* clone() override;
virtual void dump(unsigned level) override; virtual void dump(unsigned level) override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
}; };
} /* namespace items */ } /* namespace items */

View File

@ -34,7 +34,7 @@ void Scythe::dump(unsigned level)
std::cout << " .Component: Scythe\n"; std::cout << " .Component: Scythe\n";
} }
void Scythe::performAction(float x, float y, model::Direction d) void Scythe::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
} }

View File

@ -8,14 +8,14 @@
#ifndef COMPONENTS_ITEMS_SCYTHE_H_ #ifndef COMPONENTS_ITEMS_SCYTHE_H_
#define COMPONENTS_ITEMS_SCYTHE_H_ #define COMPONENTS_ITEMS_SCYTHE_H_
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <model/Component.h> #include <model/Component.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Scythe: public model::Component, public IPlayerAction class Scythe: public model::Component, public model::IPlayerAction
{ {
public: public:
Scythe(); Scythe();
@ -24,7 +24,7 @@ namespace items {
virtual model::Component* clone() override; virtual model::Component* clone() override;
virtual void dump(unsigned level) override; virtual void dump(unsigned level) override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
}; };
} /* namespace items */ } /* namespace items */

View File

@ -23,7 +23,8 @@ namespace items {
WateringCan::WateringCan() WateringCan::WateringCan()
: capacity(10), : capacity(10),
amountLeft(10), amountLeft(10),
m_map(nullptr) m_map(nullptr),
m_grid(nullptr)
{ {
} }
@ -62,16 +63,13 @@ void WateringCan::onInitialize()
m_grid = (*gridIt)->component<basic::Grid>(); m_grid = (*gridIt)->component<basic::Grid>();
} }
void WateringCan::performAction(float x, float y, model::Direction d) void WateringCan::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
Assert(m_map, "No background object!!!"); Assert(m_map, "No background object!!!");
// Compute watering position // Compute watering position
float digX, digY; size_t col = floorf(lookX);
translate(x, y, d, 0.5f, &digX, &digY); size_t row = floorf(lookY);
size_t col = floorf(digX);
size_t row = floorf(digY);
// See what the cell contains // See what the cell contains
Cell backCell = m_map->layer(0).get(row, col); Cell backCell = m_map->layer(0).get(row, col);

View File

@ -9,7 +9,7 @@
#define COMPONENTS_ITEMS_WATERINGCAN_H_ #define COMPONENTS_ITEMS_WATERINGCAN_H_
#include <components/basic/Grid.h> #include <components/basic/Grid.h>
#include <components/items/IPlayerAction.h> #include <model/IPlayerAction.h>
#include <components/Map.h> #include <components/Map.h>
#include <model/Component.h> #include <model/Component.h>
#include <model/Direction.h> #include <model/Direction.h>
@ -18,7 +18,7 @@ namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class WateringCan: public model::Component, public IPlayerAction class WateringCan: public model::Component, public model::IPlayerAction
{ {
public: public:
WateringCan(); WateringCan();
@ -29,7 +29,7 @@ namespace items {
virtual void onInitialize() override; virtual void onInitialize() override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
void fillCan(); void fillCan();

View File

@ -20,6 +20,7 @@ Weapon::Weapon()
critDamage(0), critDamage(0),
attackDuration(1.0f), attackDuration(1.0f),
attackTimeLeft(0), attackTimeLeft(0),
energyCost(0),
m_sprite(nullptr) m_sprite(nullptr)
{ {
} }
@ -57,12 +58,10 @@ void Weapon::onUpdateLogic()
} }
} }
void Weapon::performAction(float x, float y, model::Direction d) void Weapon::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energCost)
{ {
if (attackTimeLeft <= 0) *timeCost = attackTimeLeft = attackDuration;
{ *energCost = energyCost;
attackTimeLeft = attackDuration;
}
} }
void Weapon::dump(unsigned level) void Weapon::dump(unsigned level)

View File

@ -9,15 +9,15 @@
#define CONTROLLER_ITEMS_WEAPON_H_ #define CONTROLLER_ITEMS_WEAPON_H_
#include <components/basic/Sprite.h> #include <components/basic/Sprite.h>
#include <components/items/IPlayerAction.h>
#include <graphics/SpriteRenderer.h> #include <graphics/SpriteRenderer.h>
#include <model/Component.h> #include <model/Component.h>
#include <model/IPlayerAction.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace items { namespace items {
class Weapon: public model::Component, public IPlayerAction class Weapon: public model::Component, public model::IPlayerAction
{ {
public: public:
Weapon(); Weapon();
@ -33,7 +33,7 @@ namespace items {
/** /**
* Performs everything required to attacking an enemy with a weapon. To be called from player controller. * Performs everything required to attacking an enemy with a weapon. To be called from player controller.
*/ */
virtual void performAction(float x, float y, model::Direction d); virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
// Properties // Properties
float damage; float damage;
@ -43,6 +43,8 @@ namespace items {
float attackDuration; // In seconds float attackDuration; // In seconds
float attackTimeLeft; float attackTimeLeft;
float energyCost;
private: private:
basic::Sprite* m_sprite; basic::Sprite* m_sprite;
}; };

View File

@ -70,14 +70,11 @@ void Seed::onInitialize()
m_map = (*mapIt)->component<Map>(); m_map = (*mapIt)->component<Map>();
} }
void Seed::performAction(float x, float y, model::Direction d) void Seed::performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost)
{ {
// Compute planting position // Compute planting position
float digX, digY; size_t col = floorf(lookX);
translate(x, y, d, 0.5f, &digX, &digY); size_t row = floorf(lookY);
size_t col = floorf(digX);
size_t row = floorf(digY);
// Soil is located on layer 1 // Soil is located on layer 1
Cell cell = m_map->layer(1).get(row, col); Cell cell = m_map->layer(1).get(row, col);

View File

@ -9,15 +9,15 @@
#define COMPONENTS_ITEMS_SEED_H_ #define COMPONENTS_ITEMS_SEED_H_
#include <components/basic/Grid.h> #include <components/basic/Grid.h>
#include <components/items/IPlayerAction.h>
#include <components/Map.h> #include <components/Map.h>
#include <model/IPlayerAction.h>
#include <model/Component.h> #include <model/Component.h>
namespace farmlands { namespace farmlands {
namespace components { namespace components {
namespace plants { namespace plants {
class Seed: public model::Component, public items::IPlayerAction class Seed: public model::Component, public model::IPlayerAction
{ {
public: public:
Seed(); Seed();
@ -28,7 +28,7 @@ namespace plants {
virtual void onInitialize() override; virtual void onInitialize() override;
virtual void performAction(float x, float y, model::Direction d) override; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) override;
std::string plantName; std::string plantName;

View File

@ -0,0 +1,349 @@
/*
* Player.cpp
*
* Created on: Dec 10, 2016
* Author: tibi
*/
#include <GameState.h>
#include <components/player/Player.h>
#include <input/Input.h>
#include <math/GameMath.h>
#include <iostream>
using namespace farmlands::components::basic;
using namespace farmlands::components::items;
using namespace farmlands::graphics;
using namespace farmlands::input;
using namespace farmlands::model;
namespace farmlands {
namespace components {
namespace player {
static const float PlayerWalkVelocity = 2.0f; // The default velocity of the player when walking (units/sec).
static const float PlayerRunVelocity = 4.0f; // The default velocity of the player when running (units/sec).
static const float PlayerAttackVelocity = 0.1f; // Movement speed when attacking.
/**
* Distance from player position to "look" position.
* This position is used for picking the cell which will be affected by the player's actions.
*/
static const float PlayerLookDistance = 0.5f;
/**
* Map between velocity and direction.
*/
static const Direction VelocitySignDirections[3][3] =
{
{ Direction::NorthWest, Direction::West, Direction::SouthWest },
{ Direction::North, Direction::None, Direction::South },
{ Direction::NorthEast, Direction::East, Direction::SouthEast },
};
Player::Player()
: selectedItemIndex(-1),
selectedItem(nullptr),
selectedWeapon(nullptr),
itemActionTimeLeft(0),
facingDirection(Direction::South),
walking(false),
running(false),
lookX(0), lookY(0),
hp(100), maxHp(100),
energy(100), maxEnergy(100),
money(0),
m_transform(nullptr),
m_inventory(nullptr),
m_grid(nullptr)
{
}
Player::~Player()
{
}
Component* Player::clone()
{
Player* clone = new Player();
// Inventory
clone->selectedItemIndex = selectedItemIndex;
clone->itemActionTimeLeft = itemActionTimeLeft;
// Movement
clone->facingDirection = facingDirection;
clone->walking = walking;
clone->running = running;
// The position at which the player is looking
clone->lookX = lookX;
clone->lookY = lookY;
// Health
clone->hp = hp;
clone->energy = energy;
// Cash
clone->money = money;
return clone;
}
void Player::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: Player\n";
}
void Player::onInitialize()
{
m_transform = gameObject->component<Transform>();
m_inventory = gameObject->component<Inventory>();
// Search for the object which has the grid
auto root = &GameState::current().scene->root;
auto gridIt = root->findByComponent<Grid>();
Assert(gridIt != root->childrenEnd(), "Cannot find grid component.");
m_grid = (*gridIt)->component<Grid>();
initializeInventory();
}
bool Player::onEvent(SDL_Event& event)
{
handleInventoryDropEvent(event);
handleInventorySetEvent(event);
handleActionEvents(event);
return false;
}
void Player::onUpdateLogic()
{
itemActionTimeLeft -= GameState::current().deltaTime;
hp = clamp(hp, 0, maxHp);
energy = clamp(energy, 0, maxEnergy);
updateMovement();
}
void Player::onPreRender()
{
preRenderSelectedItem();
preRenderMovement();
}
void Player::initializeInventory()
{
Assert(m_inventory != nullptr, "Inventory component is missing!");
// Get currently selected item
if (selectedItem >= 0 && selectedItemIndex < m_inventory->capacity())
{
selectedItem = m_inventory->get(static_cast<size_t>(selectedItemIndex));
selectedWeapon = (selectedItem != nullptr) ? selectedItem->component<items::Weapon>() : nullptr;
}
// Set enabled state of inventory items
for (size_t i = 0; i < m_inventory->capacity(); i++)
{
GameObject* obj = m_inventory->get(i);
if (obj)
{
obj->setEnabled(i == static_cast<size_t>(selectedItemIndex));
}
}
}
void Player::handleInventoryDropEvent(SDL_Event& event)
{
bool inventoryDrop = Input::instance().down(GameKey::InventoryDrop, event);
if (inventoryDrop && selectedItemIndex >= 0)
{
// TODO: convert to 'pickable' item instead of destroying
m_inventory->remove(static_cast<size_t>(selectedItemIndex));
gameObject->destroyChild(selectedItem);
selectedItemIndex = -1;
selectedItem = nullptr;
selectedWeapon = nullptr;
}
}
void Player::handleInventorySetEvent(SDL_Event& event)
{
// See what key was pressed
int slot = -1;
if (Input::instance().down(GameKey::Inventory1, event)) slot = 0;
if (Input::instance().down(GameKey::Inventory2, event)) slot = 1;
if (Input::instance().down(GameKey::Inventory3, event)) slot = 2;
if (Input::instance().down(GameKey::Inventory4, event)) slot = 3;
if (Input::instance().down(GameKey::Inventory5, event)) slot = 4;
if (Input::instance().down(GameKey::Inventory6, event)) slot = 5;
if (Input::instance().down(GameKey::Inventory7, event)) slot = 6;
if (Input::instance().down(GameKey::Inventory8, event)) slot = 7;
if (Input::instance().down(GameKey::Inventory9, event)) slot = 8;
if (Input::instance().down(GameKey::Inventory10, event)) slot = 9;
if (0 <= slot && slot < m_inventory->capacity())
{
// Disable old object
if (selectedItem != nullptr)
selectedItem->setEnabled(false);
// Obtain new object
selectedItemIndex = slot;
selectedItem = m_inventory->get(slot);
selectedWeapon = (selectedItem != nullptr) ? selectedItem->component<items::Weapon>() : nullptr;
// Enable new object
if (selectedItem)
selectedItem->setEnabled(true);
}
}
void Player::preRenderSelectedItem()
{
// Set item position
if (selectedItem)
{
basic::Transform* itemTransf = selectedItem->component<basic::Transform>();
if (facingDirection & Direction::East)
{
itemTransf->x = 0.2f;
itemTransf->y = -0.8f;
}
else if (facingDirection & Direction::West)
{
itemTransf->x = -0.8f;
itemTransf->y = -0.8f;
}
}
}
void Player::preRenderMovement()
{
// Get sprite
Sprite* sprite = gameObject->component<Sprite>();
// Compute current state
std::string stateName = (walking) ? "Walking " : "Idle ";
if (facingDirection & Direction::East)
stateName += "right";
else if (facingDirection & Direction::West)
stateName += "left";
else if (facingDirection & Direction::North)
stateName += "up";
else
stateName += "down";
sprite->setState(stateName);
// Set animation velocity
float animVelocity = (running) ? 1.0f : 0.7f;
if (itemActionTimeLeft > 0)
animVelocity = 0.1f;
// TODO: move this animation velocity change somewhere else
sprite->animationVelocity = animVelocity;
// Set camera
Transform* cam = GameState::current().renderContext.cameraTransform();
cam->x = m_transform->x;
cam->y = m_transform->y - 1;
}
void Player::updateMovement()
{
running = Input::instance().pressed(GameKey::Run);
walking = false;
// Compute movement velocity
float velMultiplier = PlayerWalkVelocity;
if (itemActionTimeLeft > 0)
velMultiplier = PlayerAttackVelocity;
else if (running)
velMultiplier = PlayerRunVelocity;
velMultiplier *= GameState::current().deltaTime;
// Compute movement positions
float vx = Input::instance().getX() * velMultiplier;
float vy = Input::instance().getY() * velMultiplier;
float newX = m_transform->x + vx;
float newY = m_transform->y + vy;
if ((vx || vy) && canMove(newX, newY))
{
m_transform->x = newX;
m_transform->y = newY;
walking = true;
facingDirection = getDirection(vx, vy);
translate(newX, newY, facingDirection, PlayerLookDistance, &lookX, &lookY);
}
}
Direction Player::getDirection(float vx, float vy)
{
int xx = (0 < vx) - (vx < 0);
int yy = (0 < vy) - (vy < 0);
return VelocitySignDirections[xx + 1][yy + 1];
}
void Player::handleActionEvents(SDL_Event& event)
{
bool action1 = Input::instance().down(GameKey::Action, event);
bool action2 = Input::instance().down(GameKey::Action2, event);
if (action1 && itemActionTimeLeft <= 0)
{
performAction(selectedItem);
}
if (action2 && itemActionTimeLeft <= 0)
{
GameObject* obj = m_grid->get(lookX, lookY);
performAction(obj);
}
}
void Player::performAction(model::GameObject* obj)
{
if (obj == nullptr)
return;
// Call components which implement ITool
for (auto it = obj->componentsBegin(); it != obj->componentsEnd(); it++)
{
IPlayerAction* action = dynamic_cast<IPlayerAction*>(it->second);
if (action != nullptr)
{
float timeCost = 0;
float hpCost = 0;
float energyCost = 0;
action->performAction(lookX, lookY, &timeCost, &hpCost, &energyCost);
itemActionTimeLeft += timeCost;
hp -= hpCost;
energy -= energyCost;
}
}
}
} /* namespace player */
} /* namespace components */
} /* namespace farmlands */

View File

@ -0,0 +1,87 @@
/*
* Player.h
*
* Created on: Dec 10, 2016
* Author: tibi
*/
#ifndef COMPONENTS_PLAYER_PLAYER_H_
#define COMPONENTS_PLAYER_PLAYER_H_
#include <components/basic/Grid.h>
#include <components/basic/Inventory.h>
#include <components/basic/Transform.h>
#include <components/items/Weapon.h>
#include <model/Component.h>
#include <model/Direction.h>
#include <model/GameObject.h>
#include <SDL2/SDL.h>
namespace farmlands {
namespace components {
namespace player {
class Player: public model::Component
{
public:
Player();
virtual ~Player();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
virtual void onInitialize() override;
virtual bool onEvent(SDL_Event& event) override;
virtual void onUpdateLogic() override;
virtual void onPreRender() override;
// Inventory
int selectedItemIndex;
model::GameObject* selectedItem;
items::Weapon* selectedWeapon;
float itemActionTimeLeft;
// Movement
model::Direction facingDirection;
bool walking, running;
// The position at which the player is looking
float lookX, lookY;
// Health, energy
float hp, maxHp;
float energy, maxEnergy;
// Cash
uint32_t money;
private:
// Inventory
void initializeInventory();
void handleInventoryDropEvent(SDL_Event& event);
void handleInventorySetEvent(SDL_Event& event);
void preRenderSelectedItem();
// Movement
void preRenderMovement();
void updateMovement();
bool canMove(float x, float y) { return true; }
static model::Direction getDirection(float vx, float vy);
// Actions
void handleActionEvents(SDL_Event& event);
void performAction(model::GameObject* obj);
basic::Transform* m_transform;
basic::Inventory* m_inventory;
basic::Grid* m_grid;
};
} /* namespace player */
} /* namespace components */
} /* namespace farmlands */
#endif /* COMPONENTS_PLAYER_PLAYER_H_ */

View File

@ -1,196 +0,0 @@
/*
* PlayerInventory.cpp
*
* Created on: Dec 3, 2016
* Author: tibi
*/
#include <GameState.h>
#include <components/items/Weapon.h>
#include <components/player/PlayerInventory.h>
#include <components/player/PlayerMovement.h>
#include <input/Input.h>
#include <model/GameObject.h>
#include <iostream>
using namespace farmlands::components::basic;
using namespace farmlands::components::items;
using namespace farmlands::graphics;
using namespace farmlands::input;
using namespace farmlands::model;
namespace farmlands {
namespace components {
namespace player {
PlayerInventory::PlayerInventory()
: capacity(10),
currentItemIndex(-1),
currentItem(nullptr),
currentWeapon(nullptr),
m_inventory(nullptr),
m_playerTransform(nullptr),
m_playerMovement(nullptr)
{
}
PlayerInventory::~PlayerInventory()
{
}
model::Component* PlayerInventory::clone()
{
PlayerInventory* clone = new PlayerInventory();
clone->capacity = capacity;
clone->currentItemIndex = currentItemIndex;
return clone;
}
void PlayerInventory::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: PlayerInventory\n";
}
void PlayerInventory::onInitialize()
{
// Get component named "Inventory" (create it if it doesn't exist)
auto it = gameObject->findByName("Inventory");
if (it == gameObject->childrenEnd())
{
m_inventory = new model::GameObject();
m_inventory->name = "Inventory";
gameObject->addChild(m_inventory);
gameObject->addComponent(new Transform());
m_inventory->onCreate();
}
else
{
m_inventory = *it;
}
// Get current item
if (0 <= currentItemIndex && currentItemIndex < (int)m_inventory->childrenSize())
{
currentItem = *(m_inventory->childrenBegin() + currentItemIndex);
currentWeapon = currentItem->component<Weapon>();
}
// Ensure all items except current item are disabled
for (auto it = m_inventory->childrenBegin(); it != m_inventory->childrenEnd(); it++)
(*it)->setEnabled(*it == currentItem);
// Get transform
m_playerTransform = gameObject->component<Transform>();
m_playerMovement = gameObject->component<PlayerMovement>();
}
bool PlayerInventory::onEvent(SDL_Event& event)
{
handleAttackEvents(event);
handleCurrentInventoryItemEvent(event);
handleInventoryEvents(event);
return false;
}
void PlayerInventory::onUpdateLogic()
{
}
void PlayerInventory::onPreRender()
{
// Set item position
if (currentItem)
{
Transform* itemTransf = currentItem->component<Transform>();
if (m_playerMovement->facingDirection & Direction::East)
{
itemTransf->x = 0.2f;
itemTransf->y = -0.8f;
}
else if (m_playerMovement->facingDirection & Direction::West)
{
itemTransf->x = -0.8f;
itemTransf->y = -0.8f;
}
}
}
void PlayerInventory::handleAttackEvents(SDL_Event& event)
{
bool attack = Input::instance().down(GameKey::Action, event);
if (attack && currentItem != nullptr)
{
float x = m_playerTransform->x;
float y = m_playerTransform->y;
Direction d = m_playerMovement->facingDirection;
// Call components which implement ITool
for (auto it = currentItem->componentsBegin(); it != currentItem->componentsEnd(); it++)
{
IPlayerAction* tool = dynamic_cast<IPlayerAction*>(it->second);
if (tool != nullptr)
tool->performAction(x, y, d);
}
}
}
void PlayerInventory::handleCurrentInventoryItemEvent(SDL_Event& event)
{
// See what key was pressed
int slot = -1;
if (Input::instance().down(GameKey::Inventory1, event)) slot = 0;
if (Input::instance().down(GameKey::Inventory2, event)) slot = 1;
if (Input::instance().down(GameKey::Inventory3, event)) slot = 2;
if (Input::instance().down(GameKey::Inventory4, event)) slot = 3;
if (Input::instance().down(GameKey::Inventory5, event)) slot = 4;
if (Input::instance().down(GameKey::Inventory6, event)) slot = 5;
if (Input::instance().down(GameKey::Inventory7, event)) slot = 6;
if (Input::instance().down(GameKey::Inventory8, event)) slot = 7;
if (Input::instance().down(GameKey::Inventory9, event)) slot = 8;
if (Input::instance().down(GameKey::Inventory10, event)) slot = 9;
if (0 <= slot && slot < (int)m_inventory->childrenSize())
{
// Disable old object
if (currentItem != nullptr)
currentItem->setEnabled(false);
// Obtain new object
currentItemIndex = slot;
currentItem = *(m_inventory->childrenBegin() + slot);
currentWeapon = currentItem->component<Weapon>();
// Enable new object
currentItem->setEnabled(true);
}
else if (0 <= slot)
{
std::cout << "Slot " << slot << "empty\n";
}
}
void PlayerInventory::handleInventoryEvents(SDL_Event& event)
{
bool inventoryDrop = Input::instance().down(GameKey::InventoryDrop, event);
if (inventoryDrop && currentItem != nullptr)
{
// For now we delete the object. We may want to save its state later on
m_inventory->destroyChild(currentItem);
currentItemIndex = -1;
currentItem = nullptr;
currentWeapon = nullptr;
}
}
} /* namespace player */
} /* namespace components */
} /* namespace farmlands */

View File

@ -1,60 +0,0 @@
/*
* PlayerInventory.h
*
* Created on: Dec 3, 2016
* Author: tibi
*/
#ifndef COMPONENTS_PLAYER_PLAYERINVENTORY_H_
#define COMPONENTS_PLAYER_PLAYERINVENTORY_H_
#include <components/basic/Transform.h>
#include <components/items/Weapon.h>
#include <model/Component.h>
namespace farmlands {
namespace components {
namespace player {
class PlayerMovement;
class PlayerInventory: public model::Component
{
public:
PlayerInventory();
virtual ~PlayerInventory();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
virtual void onInitialize() override;
virtual bool onEvent(SDL_Event& event) override;
virtual void onUpdateLogic() override;
virtual void onPreRender() override;
uint32_t capacity;
// Current item
int currentItemIndex;
model::GameObject* currentItem;
items::Weapon* currentWeapon;
private:
void handleAttackEvents(SDL_Event& event);
void handleCurrentInventoryItemEvent(SDL_Event& event);
void handleInventoryEvents(SDL_Event& event);
// Inventory
model::GameObject* m_inventory;
// Player transform
basic::Transform* m_playerTransform;
PlayerMovement* m_playerMovement;
};
} /* namespace player */
} /* namespace components */
} /* namespace farmlands */
#endif /* COMPONENTS_PLAYER_PLAYERINVENTORY_H_ */

View File

@ -1,160 +0,0 @@
/*
* PlayerMovement.cpp
*
* Created on: Nov 27, 2016
* Author: tibi
*/
#include <GameState.h>
#include <components/items/Item.h>
#include <components/items/Weapon.h>
#include <components/player/PlayerInventory.h>
#include <components/player/PlayerMovement.h>
#include <graphics/SpriteRenderer.h>
#include <input/Input.h>
#include <utils/Assert.h>
#include <iostream>
using namespace farmlands::components::basic;
using namespace farmlands::components::items;
using namespace farmlands::graphics;
using namespace farmlands::input;
using namespace farmlands::model;
namespace farmlands {
namespace components {
namespace player {
static const float PlayerWalkVelocity = 2.0f; // The default velocity of the player when walking (units/sec).
static const float PlayerRunVelocity = 4.0f; // The default velocity of the player when running (units/sec).
static const float PlayerAttackVelocity = 0.1f; // Movement speed when attacking.
/**
* Direction enum based on sign of velocity on x and y
*/
static const Direction VelocitySignDirections[3][3] =
{
{ Direction::NorthWest, Direction::West, Direction::SouthWest },
{ Direction::North, Direction::None, Direction::South },
{ Direction::NorthEast, Direction::East, Direction::SouthEast },
};
PlayerMovement::PlayerMovement()
: facingDirection(Direction::South),
walking(false),
running(false),
m_transform(nullptr),
m_inventory(nullptr)
{
}
PlayerMovement::~PlayerMovement()
{
}
model::Component* PlayerMovement::clone()
{
PlayerMovement* clone = new PlayerMovement();
clone->facingDirection = facingDirection;
return clone;
}
void PlayerMovement::onInitialize()
{
m_transform = gameObject->component<components::basic::Transform>();
m_inventory = gameObject->component<PlayerInventory>();
}
void PlayerMovement::onUpdateLogic()
{
running = Input::instance().pressed(GameKey::Run);
walking = false;
// Compute movement velocity
float velMultiplier = PlayerWalkVelocity;
if (m_inventory->currentWeapon && m_inventory->currentWeapon->attackTimeLeft > 0)
velMultiplier = PlayerAttackVelocity;
else if (running)
velMultiplier = PlayerRunVelocity;
// Make movement time independent
velMultiplier *= GameState::current().deltaTime;
// Get velocity of axes
float vx = Input::instance().getX() * velMultiplier;
float vy = Input::instance().getY() * velMultiplier;
// Check if we can move to the new position
float newX = m_transform->x + vx;
float newY = m_transform->y + vy;
if ((vx || vy) && canMove(newX, newY))
{
walking = true;
m_transform->x = newX;
m_transform->y = newY;
facingDirection = getDirection(vx, vy);
}
}
void PlayerMovement::onPreRender()
{
// Get sprite
Sprite* sprite = gameObject->component<Sprite>();
// Compute current state
std::string stateName = (walking) ? "Walking " : "Idle ";
if (facingDirection & Direction::East)
stateName += "right";
else if (facingDirection & Direction::West)
stateName += "left";
else if (facingDirection & Direction::North)
stateName += "up";
else
stateName += "down";
sprite->setState(stateName);
// Set animation velocity
float animVelocity = (running) ? 1.0f : 0.7f;
if (m_inventory->currentWeapon && m_inventory->currentWeapon->attackTimeLeft > 0)
animVelocity = 0.1f;
// TODO: move this animation velocity change somewhere else
sprite->animationVelocity = animVelocity;
// Set camera
components::basic::Transform* cam = GameState::current().renderContext.cameraTransform();
cam->x = m_transform->x;
cam->y = m_transform->y - 1;
}
bool PlayerMovement::canMove(float x, float y)
{
// TODO: check collisions & stuff. For now, nothing
return true;
}
Direction PlayerMovement::getDirection(float vx, float vy)
{
int xx = (0 < vx) - (vx < 0);
int yy = (0 < vy) - (vy < 0);
return VelocitySignDirections[xx + 1][yy + 1];
}
void PlayerMovement::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: PlayerMovement\n";
}
}
} /* namespace controller */
} /* namespace farmlands */

View File

@ -1,57 +0,0 @@
/*
* PlayerController.h
*
* Created on: Nov 27, 2016
* Author: tibi
*/
#ifndef CONTROLLER_PLAYERCONTROLLER_H_
#define CONTROLLER_PLAYERCONTROLLER_H_
#include <components/basic/Transform.h>
#include <components/items/Weapon.h>
#include <model/Component.h>
#include <model/Direction.h>
#include <SDL2/SDL.h>
#define MAX_INVENTORY_SIZE 50
namespace farmlands {
namespace components {
namespace player {
class PlayerInventory;
class PlayerMovement : public model::Component
{
public:
PlayerMovement();
virtual ~PlayerMovement();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
virtual void onInitialize() override;
virtual void onUpdateLogic() override;
virtual void onPreRender() override;
model::Direction facingDirection;
bool walking, running;
private:
static model::Direction getDirection(float vx, float vy);
bool canMove(float x, float y);
// Movement
basic::Transform* m_transform;
// For getting speed
PlayerInventory* m_inventory;
};
}
} /* namespace components */
} /* namespace farmlands */
#endif /* CONTROLLER_PLAYERCONTROLLER_H_ */

View File

@ -158,7 +158,7 @@ namespace model {
auto it = m_components.find(typeIndex); auto it = m_components.find(typeIndex);
if (it != m_components.end()) if (it != m_components.end())
{ {
comp = it->second; comp = dynamic_cast<T*>(it->second);
m_components.erase(it); m_components.erase(it);
} }

View File

@ -11,20 +11,16 @@
#include <model/Direction.h> #include <model/Direction.h>
namespace farmlands { namespace farmlands {
namespace components { namespace model {
namespace items {
class IPlayerAction class IPlayerAction
{ {
public: public:
virtual ~IPlayerAction() { } virtual ~IPlayerAction() { }
virtual void performAction(float playerX, float playerY, model::Direction) = 0; virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) = 0;
float actionCost;
}; };
} /* namespace items */ } /* namespace model */
} /* namespace components */
} /* namespace farmlands */ } /* namespace farmlands */
#endif /* COMPONENTS_ITEMS_IPLAYERACTION_H_ */ #endif /* COMPONENTS_ITEMS_IPLAYERACTION_H_ */

View File

@ -93,14 +93,20 @@ void ResourceManager::loadGame()
// Get to "Inventory" object // Get to "Inventory" object
model::GameObject* root = &GameState::current().scene->root; model::GameObject* root = &GameState::current().scene->root;
model::GameObject* player = *root->findByName("Player"); model::GameObject* player = *root->findByName("Player");
model::GameObject* inventory = *player->findByName("Inventory"); components::basic::Inventory* inventory = player->component<components::basic::Inventory>();
// Give player all items // Give player all items
for (auto prefab : GameState::current().itemPrefabs) for (auto prefab : GameState::current().itemPrefabs)
model::GameObject::instantiate(prefab, "inv item", inventory); {
model::GameObject* item = model::GameObject::instantiate(prefab, "inv item", player);
inventory->add(item);
}
for (auto prefab : GameState::current().seedsPrefabs) for (auto prefab : GameState::current().seedsPrefabs)
model::GameObject::instantiate(prefab, "inv seed", inventory); {
model::GameObject* item = model::GameObject::instantiate(prefab, "inv seed", player);
inventory->add(item);
}
} }
std::string ResourceManager::getPath(ResourceId resourceId) std::string ResourceManager::getPath(ResourceId resourceId)

View File

@ -97,7 +97,6 @@ components::Map* parse<components::Map> (boost::property_tree::ptree& root)
parseMapCells(cellsId, map, layer); parseMapCells(cellsId, map, layer);
} }
} }
} }
return map; return map;
@ -158,6 +157,34 @@ components::basic::Grid* parse<components::basic::Grid> (boost::property_tree::p
return grid; return grid;
} }
template <>
components::basic::Inventory* parse<components::basic::Inventory> (boost::property_tree::ptree& root)
{
// Ensure we are on the correct node (property tree seems to add root of its own)
if (root.size() > 0 && root.front().first == "Inventory")
root = root.front().second;
components::basic::Inventory* inventory = new components::basic::Inventory();
size_t capacity = root.get<size_t>("<xmlattr>.capacity");
inventory->setCapacity(capacity);
return inventory;
}
template <>
components::basic::InventoryItem* parse<components::basic::InventoryItem> (boost::property_tree::ptree& root)
{
// Ensure we are on the correct node (property tree seems to add root of its own)
if (root.size() > 0 && root.front().first == "InventoryItem")
root = root.front().second;
components::basic::InventoryItem* item = new components::basic::InventoryItem();
item->slot = root.get<size_t>("<xmlattr>.slot");
return item;
}
template <> template <>
components::basic::Sprite* parse<components::basic::Sprite> (boost::property_tree::ptree& root) components::basic::Sprite* parse<components::basic::Sprite> (boost::property_tree::ptree& root)
{ {
@ -382,6 +409,7 @@ components::items::Weapon* parse<components::items::Weapon> (boost::property_tre
weapon->critProbability = root.get<float>("<xmlattr>.critProbability"); weapon->critProbability = root.get<float>("<xmlattr>.critProbability");
weapon->critDamage = root.get<float>("<xmlattr>.critDamage"); weapon->critDamage = root.get<float>("<xmlattr>.critDamage");
weapon->attackDuration = root.get<float>("<xmlattr>.attackDuration"); weapon->attackDuration = root.get<float>("<xmlattr>.attackDuration");
weapon->energyCost = root.get<float>("<xmlattr>.energyCost");
return weapon; return weapon;
} }
@ -423,34 +451,58 @@ components::plants::Seed* parse<components::plants::Seed> (boost::property_tree:
return seed; return seed;
} }
template <> model::Direction parseDirection(std::string directionStr)
components::player::PlayerInventory* parse<components::player::PlayerInventory> (boost::property_tree::ptree& root)
{ {
// Ensure we are on the correct node (property tree seems to add root of its own) model::Direction direction = model::Direction::None;
if (root.size() > 0 && root.front().first == "PlayerInventory") boost::to_lower(directionStr);
root = root.front().second;
components::player::PlayerInventory* controller = new components::player::PlayerInventory(); if (boost::contains(directionStr, "east"))
controller->capacity = root.get<uint32_t>("<xmlattr>.capacity"); direction = (model::Direction) (direction | model::Direction::East);
controller->currentItemIndex = root.get<int>("<xmlattr>.currentItemIndex", -1); if (boost::contains(directionStr, "north"))
direction = (model::Direction) (direction | model::Direction::North);
if (boost::contains(directionStr, "west"))
direction = (model::Direction) (direction | model::Direction::West);
if (boost::contains(directionStr, "south"))
direction = (model::Direction) (direction | model::Direction::South);
return controller; return direction;
} }
template <> template <>
components::player::PlayerMovement* parse<components::player::PlayerMovement> (boost::property_tree::ptree& root) components::player::Player* parse<components::player::Player> (boost::property_tree::ptree& root)
{ {
// Ensure we are on the correct node (property tree seems to add root of its own) // Ensure we are on the correct node (property tree seems to add root of its own)
if (root.size() > 0 && root.front().first == "PlayerMovement") if (root.size() > 0 && root.front().first == "Player")
root = root.front().second; root = root.front().second;
components::player::PlayerMovement* controller = new components::player::PlayerMovement(); components::player::Player* player = new components::player::Player();
controller->facingDirection = (model::Direction)root.get<int>("<xmlattr>.facingDirection", model::Direction::South);
return controller; // Inventory
player->selectedItemIndex = root.get<int>("<xmlattr>.selectedItemIndex", -1);
player->itemActionTimeLeft = root.get<float>("<xmlattr>.itemActionTimeLeft", 0.0f);
// Movement
std::string direction = root.get<std::string>("<xmlattr>.facingDirection", "South");
player->facingDirection = parseDirection(direction);
player->walking = root.get<bool>("<xmlattr>.walking", false);
player->running = root.get<bool>("<xmlattr>.running", false);
// Looking
player->lookX = root.get<float>("<xmlattr>.lookX", 0.0f);
player->lookY = root.get<float>("<xmlattr>.lookY", 0.0f);
// Health, energy
player->hp = root.get<float>("<xmlattr>.hp", 100.0f);
player->maxHp = root.get<float>("<xmlattr>.maxHp", 100.0f);
player->energy = root.get<float>("<xmlattr>.energy", 100.0f);
player->maxEnergy = root.get<float>("<xmlattr>.maxEnergy", 100.0f);
// Cash
player->money = root.get<uint32_t>("<xmlattr>.money", 0u);
return player;
} }
/****** Graphics ******/ /****** Graphics ******/
template <> template <>
@ -503,6 +555,12 @@ model::GameObject* parse<model::GameObject> (boost::property_tree::ptree& root)
else if (child.first == "Grid") else if (child.first == "Grid")
gameObj->addComponent(parse<components::basic::Grid>(child.second)); gameObj->addComponent(parse<components::basic::Grid>(child.second));
else if (child.first == "Inventory")
gameObj->addComponent(parse<components::basic::Inventory>(child.second));
else if (child.first == "InventoryItem")
gameObj->addComponent(parse<components::basic::InventoryItem>(child.second));
else if (child.first == "Sprite") else if (child.first == "Sprite")
gameObj->addComponent(parse<components::basic::Sprite>(child.second)); gameObj->addComponent(parse<components::basic::Sprite>(child.second));
@ -542,11 +600,8 @@ model::GameObject* parse<model::GameObject> (boost::property_tree::ptree& root)
gameObj->addComponent(parse<components::plants::Seed>(child.second)); gameObj->addComponent(parse<components::plants::Seed>(child.second));
// Components::player // Components::player
else if (child.first == "PlayerInventory") else if (child.first == "Player")
gameObj->addComponent(parse<components::player::PlayerInventory>(child.second)); gameObj->addComponent(parse<components::player::Player>(child.second));
else if (child.first == "PlayerMovement")
gameObj->addComponent(parse<components::player::PlayerMovement>(child.second));
// Components // Components
else if (child.first == "DebugController") else if (child.first == "DebugController")

View File

@ -10,6 +10,8 @@
#include <components/basic/Camera.h> #include <components/basic/Camera.h>
#include <components/basic/Grid.h> #include <components/basic/Grid.h>
#include <components/basic/Inventory.h>
#include <components/basic/InventoryItem.h>
#include <components/basic/Sprite.h> #include <components/basic/Sprite.h>
#include <components/basic/Transform.h> #include <components/basic/Transform.h>
#include <components/DebugController.h> #include <components/DebugController.h>
@ -26,8 +28,7 @@
#include <components/Map.h> #include <components/Map.h>
#include <components/plants/Plant.h> #include <components/plants/Plant.h>
#include <components/plants/Seed.h> #include <components/plants/Seed.h>
#include <components/player/PlayerInventory.h> #include <components/player/Player.h>
#include <components/player/PlayerMovement.h>
#include <graphics/MapRenderer.h> #include <graphics/MapRenderer.h>
#include <graphics/SpriteRenderer.h> #include <graphics/SpriteRenderer.h>
#include <model/GameObject.h> #include <model/GameObject.h>
@ -54,6 +55,12 @@ namespace storage {
template <> template <>
components::basic::Grid* parse<components::basic::Grid> (boost::property_tree::ptree& root); components::basic::Grid* parse<components::basic::Grid> (boost::property_tree::ptree& root);
template <>
components::basic::Inventory* parse<components::basic::Inventory> (boost::property_tree::ptree& root);
template <>
components::basic::InventoryItem* parse<components::basic::InventoryItem> (boost::property_tree::ptree& root);
template <> template <>
components::basic::Sprite* parse<components::basic::Sprite> (boost::property_tree::ptree& root); components::basic::Sprite* parse<components::basic::Sprite> (boost::property_tree::ptree& root);
@ -103,10 +110,7 @@ namespace storage {
components::plants::Seed* parse<components::plants::Seed> (boost::property_tree::ptree& root); components::plants::Seed* parse<components::plants::Seed> (boost::property_tree::ptree& root);
template <> template <>
components::player::PlayerInventory* parse<components::player::PlayerInventory> (boost::property_tree::ptree& root); components::player::Player* parse<components::player::Player> (boost::property_tree::ptree& root);
template <>
components::player::PlayerMovement* parse<components::player::PlayerMovement> (boost::property_tree::ptree& root);
/****** Graphics ******/ /****** Graphics ******/