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:
parent
6fe33a99a8
commit
6a35b11ec2
@ -11,7 +11,8 @@
|
||||
<Weapon damage="0.5"
|
||||
critProbability="0"
|
||||
critDamage="0"
|
||||
attackDuration="0.2" />
|
||||
attackDuration="0.2"
|
||||
energyCost="1" />
|
||||
<Hoe />
|
||||
</GameObject>
|
||||
|
||||
@ -25,7 +26,8 @@
|
||||
<Weapon damage="0"
|
||||
critProbability="0"
|
||||
critDamage="0"
|
||||
attackDuration="0.2" />
|
||||
attackDuration="0.2"
|
||||
energyCost="1" />
|
||||
<WateringCan capacity="10" amountLeft="10" />
|
||||
</GameObject>
|
||||
|
||||
|
@ -11,7 +11,8 @@
|
||||
<Weapon damage="3"
|
||||
critProbability="0.01"
|
||||
critDamage="9"
|
||||
attackDuration="0.4" />
|
||||
attackDuration="0.4"
|
||||
energyCost="1.5" />
|
||||
</GameObject>
|
||||
|
||||
<GameObject name="Level 2 Sword">
|
||||
@ -24,7 +25,8 @@
|
||||
<Weapon damage="6"
|
||||
critProbability="0.01"
|
||||
critDamage="18"
|
||||
attackDuration="0.4" />
|
||||
attackDuration="0.4"
|
||||
energyCost="0.9" />
|
||||
</GameObject>
|
||||
|
||||
</ItemCollection>
|
@ -26,12 +26,10 @@
|
||||
<Transform x="120" y="100" />
|
||||
<Sprite src="sprites/Player.sprite" />
|
||||
<SpriteRenderer />
|
||||
<PlayerMovement />
|
||||
<PlayerInventory capacity="30" />
|
||||
|
||||
<GameObject name="Inventory">
|
||||
<Transform />
|
||||
</GameObject>
|
||||
<Inventory capacity="30" />
|
||||
<Player hp="100" maxHp="100"
|
||||
energy="100" maxEnergy="100"
|
||||
money="50" />
|
||||
</GameObject>
|
||||
|
||||
<!-- Debug object -->
|
||||
|
148
src/components/basic/Inventory.cpp
Normal file
148
src/components/basic/Inventory.cpp
Normal 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 */
|
||||
|
77
src/components/basic/Inventory.h
Normal file
77
src/components/basic/Inventory.h
Normal 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_ */
|
36
src/components/basic/InventoryItem.cpp
Normal file
36
src/components/basic/InventoryItem.cpp
Normal 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 */
|
32
src/components/basic/InventoryItem.h
Normal file
32
src/components/basic/InventoryItem.h
Normal 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_ */
|
@ -34,7 +34,7 @@ void Axe::dump(unsigned level)
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
#ifndef COMPONENTS_ITEMS_AXE_H_
|
||||
#define COMPONENTS_ITEMS_AXE_H_
|
||||
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Axe: public model::Component, public IPlayerAction
|
||||
class Axe: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Axe();
|
||||
@ -24,7 +24,7 @@ namespace items {
|
||||
virtual model::Component* clone() 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 */
|
||||
|
@ -26,7 +26,7 @@ model::Component* Giftable::clone()
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
#ifndef CONTROLLER_ITEMS_GIFTABLE_H_
|
||||
#define CONTROLLER_ITEMS_GIFTABLE_H_
|
||||
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Giftable: public model::Component, public IPlayerAction
|
||||
class Giftable: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Giftable();
|
||||
@ -24,7 +24,7 @@ namespace items {
|
||||
virtual model::Component* clone() 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 */
|
||||
|
@ -53,16 +53,13 @@ void Hoe::onInitialize()
|
||||
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!!!");
|
||||
|
||||
// Compute watering position
|
||||
float digX, digY;
|
||||
translate(x, y, d, 0.5f, &digX, &digY);
|
||||
|
||||
size_t col = floorf(digX);
|
||||
size_t row = floorf(digY);
|
||||
size_t col = floorf(lookX);
|
||||
size_t row = floorf(lookY);
|
||||
|
||||
// See what the cell contains
|
||||
Cell backCell = m_map->layer(0).get(row, col);
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef COMPONENTS_ITEMS_HOE_H_
|
||||
#define COMPONENTS_ITEMS_HOE_H_
|
||||
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <components/Map.h>
|
||||
#include <model/Component.h>
|
||||
#include <model/Direction.h>
|
||||
@ -17,7 +17,7 @@ namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Hoe: public model::Component, public IPlayerAction
|
||||
class Hoe: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Hoe();
|
||||
@ -28,7 +28,7 @@ namespace items {
|
||||
|
||||
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:
|
||||
Map* m_map;
|
||||
|
@ -34,7 +34,7 @@ void Pickaxe::dump(unsigned level)
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
#ifndef COMPONENTS_ITEMS_PICKAXE_H_
|
||||
#define COMPONENTS_ITEMS_PICKAXE_H_
|
||||
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Pickaxe: public model::Component, public IPlayerAction
|
||||
class Pickaxe: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Pickaxe();
|
||||
@ -24,7 +24,7 @@ namespace items {
|
||||
virtual model::Component* clone() 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 */
|
||||
|
@ -34,7 +34,7 @@ void Scythe::dump(unsigned level)
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
#ifndef COMPONENTS_ITEMS_SCYTHE_H_
|
||||
#define COMPONENTS_ITEMS_SCYTHE_H_
|
||||
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Scythe: public model::Component, public IPlayerAction
|
||||
class Scythe: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Scythe();
|
||||
@ -24,7 +24,7 @@ namespace items {
|
||||
virtual model::Component* clone() 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 */
|
||||
|
@ -23,7 +23,8 @@ namespace items {
|
||||
WateringCan::WateringCan()
|
||||
: capacity(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>();
|
||||
}
|
||||
|
||||
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!!!");
|
||||
|
||||
// Compute watering position
|
||||
float digX, digY;
|
||||
translate(x, y, d, 0.5f, &digX, &digY);
|
||||
|
||||
size_t col = floorf(digX);
|
||||
size_t row = floorf(digY);
|
||||
size_t col = floorf(lookX);
|
||||
size_t row = floorf(lookY);
|
||||
|
||||
// See what the cell contains
|
||||
Cell backCell = m_map->layer(0).get(row, col);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define COMPONENTS_ITEMS_WATERINGCAN_H_
|
||||
|
||||
#include <components/basic/Grid.h>
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <components/Map.h>
|
||||
#include <model/Component.h>
|
||||
#include <model/Direction.h>
|
||||
@ -18,7 +18,7 @@ namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class WateringCan: public model::Component, public IPlayerAction
|
||||
class WateringCan: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
WateringCan();
|
||||
@ -29,7 +29,7 @@ namespace items {
|
||||
|
||||
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();
|
||||
|
||||
|
@ -20,6 +20,7 @@ Weapon::Weapon()
|
||||
critDamage(0),
|
||||
attackDuration(1.0f),
|
||||
attackTimeLeft(0),
|
||||
energyCost(0),
|
||||
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)
|
||||
{
|
||||
attackTimeLeft = attackDuration;
|
||||
}
|
||||
*timeCost = attackTimeLeft = attackDuration;
|
||||
*energCost = energyCost;
|
||||
}
|
||||
|
||||
void Weapon::dump(unsigned level)
|
||||
|
@ -9,15 +9,15 @@
|
||||
#define CONTROLLER_ITEMS_WEAPON_H_
|
||||
|
||||
#include <components/basic/Sprite.h>
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <graphics/SpriteRenderer.h>
|
||||
#include <model/Component.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
|
||||
class Weapon: public model::Component, public IPlayerAction
|
||||
class Weapon: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Weapon();
|
||||
@ -33,7 +33,7 @@ namespace items {
|
||||
/**
|
||||
* 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
|
||||
float damage;
|
||||
@ -43,6 +43,8 @@ namespace items {
|
||||
float attackDuration; // In seconds
|
||||
float attackTimeLeft;
|
||||
|
||||
float energyCost;
|
||||
|
||||
private:
|
||||
basic::Sprite* m_sprite;
|
||||
};
|
||||
|
@ -70,14 +70,11 @@ void Seed::onInitialize()
|
||||
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
|
||||
float digX, digY;
|
||||
translate(x, y, d, 0.5f, &digX, &digY);
|
||||
|
||||
size_t col = floorf(digX);
|
||||
size_t row = floorf(digY);
|
||||
size_t col = floorf(lookX);
|
||||
size_t row = floorf(lookY);
|
||||
|
||||
// Soil is located on layer 1
|
||||
Cell cell = m_map->layer(1).get(row, col);
|
||||
|
@ -9,15 +9,15 @@
|
||||
#define COMPONENTS_ITEMS_SEED_H_
|
||||
|
||||
#include <components/basic/Grid.h>
|
||||
#include <components/items/IPlayerAction.h>
|
||||
#include <components/Map.h>
|
||||
#include <model/IPlayerAction.h>
|
||||
#include <model/Component.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace plants {
|
||||
|
||||
class Seed: public model::Component, public items::IPlayerAction
|
||||
class Seed: public model::Component, public model::IPlayerAction
|
||||
{
|
||||
public:
|
||||
Seed();
|
||||
@ -28,7 +28,7 @@ namespace plants {
|
||||
|
||||
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;
|
||||
|
||||
|
349
src/components/player/Player.cpp
Normal file
349
src/components/player/Player.cpp
Normal 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 */
|
87
src/components/player/Player.h
Normal file
87
src/components/player/Player.h
Normal 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_ */
|
@ -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 */
|
@ -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_ */
|
@ -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 */
|
@ -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_ */
|
@ -158,7 +158,7 @@ namespace model {
|
||||
auto it = m_components.find(typeIndex);
|
||||
if (it != m_components.end())
|
||||
{
|
||||
comp = it->second;
|
||||
comp = dynamic_cast<T*>(it->second);
|
||||
m_components.erase(it);
|
||||
}
|
||||
|
||||
|
@ -11,20 +11,16 @@
|
||||
#include <model/Direction.h>
|
||||
|
||||
namespace farmlands {
|
||||
namespace components {
|
||||
namespace items {
|
||||
namespace model {
|
||||
|
||||
class IPlayerAction
|
||||
{
|
||||
public:
|
||||
virtual ~IPlayerAction() { }
|
||||
virtual void performAction(float playerX, float playerY, model::Direction) = 0;
|
||||
|
||||
float actionCost;
|
||||
virtual void performAction(float lookX, float lookY, float* timeCost, float* hpCost, float* energyCost) = 0;
|
||||
};
|
||||
|
||||
} /* namespace items */
|
||||
} /* namespace components */
|
||||
} /* namespace model */
|
||||
} /* namespace farmlands */
|
||||
|
||||
#endif /* COMPONENTS_ITEMS_IPLAYERACTION_H_ */
|
@ -93,14 +93,20 @@ void ResourceManager::loadGame()
|
||||
// Get to "Inventory" object
|
||||
model::GameObject* root = &GameState::current().scene->root;
|
||||
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
|
||||
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)
|
||||
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)
|
||||
|
@ -97,7 +97,6 @@ components::Map* parse<components::Map> (boost::property_tree::ptree& root)
|
||||
parseMapCells(cellsId, map, layer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return map;
|
||||
@ -158,6 +157,34 @@ components::basic::Grid* parse<components::basic::Grid> (boost::property_tree::p
|
||||
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 <>
|
||||
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->critDamage = root.get<float>("<xmlattr>.critDamage");
|
||||
weapon->attackDuration = root.get<float>("<xmlattr>.attackDuration");
|
||||
weapon->energyCost = root.get<float>("<xmlattr>.energyCost");
|
||||
return weapon;
|
||||
}
|
||||
|
||||
@ -423,34 +451,58 @@ components::plants::Seed* parse<components::plants::Seed> (boost::property_tree:
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <>
|
||||
components::player::PlayerInventory* parse<components::player::PlayerInventory> (boost::property_tree::ptree& root)
|
||||
model::Direction parseDirection(std::string directionStr)
|
||||
{
|
||||
// Ensure we are on the correct node (property tree seems to add root of its own)
|
||||
if (root.size() > 0 && root.front().first == "PlayerInventory")
|
||||
root = root.front().second;
|
||||
model::Direction direction = model::Direction::None;
|
||||
boost::to_lower(directionStr);
|
||||
|
||||
components::player::PlayerInventory* controller = new components::player::PlayerInventory();
|
||||
controller->capacity = root.get<uint32_t>("<xmlattr>.capacity");
|
||||
controller->currentItemIndex = root.get<int>("<xmlattr>.currentItemIndex", -1);
|
||||
if (boost::contains(directionStr, "east"))
|
||||
direction = (model::Direction) (direction | model::Direction::East);
|
||||
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 <>
|
||||
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)
|
||||
if (root.size() > 0 && root.front().first == "PlayerMovement")
|
||||
if (root.size() > 0 && root.front().first == "Player")
|
||||
root = root.front().second;
|
||||
|
||||
components::player::PlayerMovement* controller = new components::player::PlayerMovement();
|
||||
controller->facingDirection = (model::Direction)root.get<int>("<xmlattr>.facingDirection", model::Direction::South);
|
||||
components::player::Player* player = new components::player::Player();
|
||||
|
||||
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 ******/
|
||||
|
||||
template <>
|
||||
@ -503,6 +555,12 @@ model::GameObject* parse<model::GameObject> (boost::property_tree::ptree& root)
|
||||
else if (child.first == "Grid")
|
||||
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")
|
||||
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));
|
||||
|
||||
// Components::player
|
||||
else if (child.first == "PlayerInventory")
|
||||
gameObj->addComponent(parse<components::player::PlayerInventory>(child.second));
|
||||
|
||||
else if (child.first == "PlayerMovement")
|
||||
gameObj->addComponent(parse<components::player::PlayerMovement>(child.second));
|
||||
else if (child.first == "Player")
|
||||
gameObj->addComponent(parse<components::player::Player>(child.second));
|
||||
|
||||
// Components
|
||||
else if (child.first == "DebugController")
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <components/basic/Camera.h>
|
||||
#include <components/basic/Grid.h>
|
||||
#include <components/basic/Inventory.h>
|
||||
#include <components/basic/InventoryItem.h>
|
||||
#include <components/basic/Sprite.h>
|
||||
#include <components/basic/Transform.h>
|
||||
#include <components/DebugController.h>
|
||||
@ -26,8 +28,7 @@
|
||||
#include <components/Map.h>
|
||||
#include <components/plants/Plant.h>
|
||||
#include <components/plants/Seed.h>
|
||||
#include <components/player/PlayerInventory.h>
|
||||
#include <components/player/PlayerMovement.h>
|
||||
#include <components/player/Player.h>
|
||||
#include <graphics/MapRenderer.h>
|
||||
#include <graphics/SpriteRenderer.h>
|
||||
#include <model/GameObject.h>
|
||||
@ -54,6 +55,12 @@ namespace storage {
|
||||
template <>
|
||||
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 <>
|
||||
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);
|
||||
|
||||
template <>
|
||||
components::player::PlayerInventory* parse<components::player::PlayerInventory> (boost::property_tree::ptree& root);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/****** Graphics ******/
|
||||
|
Loading…
Reference in New Issue
Block a user