241 lines
6.1 KiB
C++
241 lines
6.1 KiB
C++
/*
|
|
* PlayerController.cpp
|
|
*
|
|
* Created on: Nov 27, 2016
|
|
* Author: tibi
|
|
*/
|
|
|
|
#include <GameState.h>
|
|
#include <controller/items/Giftable.h>
|
|
#include <controller/items/Weapon.h>
|
|
#include <controller/player/PlayerController.h>
|
|
#include <graphics/SpriteRenderer.h>
|
|
#include <input/Input.h>
|
|
#include <model/Item.h>
|
|
#include <utils/Assert.h>
|
|
|
|
#include <iostream>
|
|
|
|
using namespace farmlands::base;
|
|
using namespace farmlands::controller::items;
|
|
using namespace farmlands::graphics;
|
|
using namespace farmlands::input;
|
|
using namespace farmlands::model;
|
|
|
|
namespace farmlands {
|
|
namespace controller {
|
|
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 },
|
|
};
|
|
|
|
PlayerController::PlayerController()
|
|
: m_transform(nullptr),
|
|
m_facingDirection(Direction::South),
|
|
m_walking(false),
|
|
m_running(false),
|
|
m_currentItem(nullptr)
|
|
{
|
|
}
|
|
|
|
PlayerController::~PlayerController()
|
|
{
|
|
}
|
|
|
|
base::Component* PlayerController::clone()
|
|
{
|
|
return new PlayerController();
|
|
}
|
|
|
|
void PlayerController::onInitialize()
|
|
{
|
|
m_transform = gameObject->component<base::Transform>();
|
|
}
|
|
|
|
bool PlayerController::onEvent(SDL_Event& event)
|
|
{
|
|
handleAttackEvents(event);
|
|
handleInventoryEvents(event);
|
|
|
|
return false;
|
|
}
|
|
|
|
void PlayerController::handleAttackEvents(SDL_Event& event)
|
|
{
|
|
bool attack = (Input::instance().down(GameKey::Action, event));
|
|
if (attack && m_currentItem != nullptr)
|
|
{
|
|
// Weapon behavior
|
|
Weapon* weapon = m_currentItem->component<Weapon>();
|
|
if (weapon)
|
|
weapon->performAttack(m_transform->x, m_transform->y, m_facingDirection);
|
|
|
|
// Gift behavior
|
|
Giftable* giftable = m_currentItem->component<Giftable>();
|
|
if (giftable)
|
|
giftable->offerGift(m_transform->x, m_transform->y, m_facingDirection);
|
|
}
|
|
}
|
|
|
|
void PlayerController::handleInventoryEvents(SDL_Event& event)
|
|
{
|
|
// See what key was pressed
|
|
int slot = -1;
|
|
|
|
if (Input::instance().down(GameKey::Inventory1, event)) slot = 1;
|
|
if (Input::instance().down(GameKey::Inventory2, event)) slot = 2;
|
|
if (Input::instance().down(GameKey::Inventory3, event)) slot = 3;
|
|
if (Input::instance().down(GameKey::Inventory4, event)) slot = 4;
|
|
if (Input::instance().down(GameKey::Inventory5, event)) slot = 5;
|
|
if (Input::instance().down(GameKey::Inventory6, event)) slot = 6;
|
|
if (Input::instance().down(GameKey::Inventory7, event)) slot = 7;
|
|
if (Input::instance().down(GameKey::Inventory8, event)) slot = 8;
|
|
if (Input::instance().down(GameKey::Inventory9, event)) slot = 9;
|
|
if (Input::instance().down(GameKey::Inventory10, event)) slot = 10;
|
|
|
|
// For now we don't have an inventory, so just instantiate some object
|
|
if (0 <= slot && slot <= GameState::current().itemPrefabs.size())
|
|
{
|
|
GameObject* itemPrefab = GameState::current().itemPrefabs[slot - 1];
|
|
|
|
// Get rid of old object
|
|
if (m_currentItem != nullptr)
|
|
gameObject->destroyChild(m_currentItem);
|
|
|
|
// Instantiate new object
|
|
m_currentItem = GameObject::instantiate(itemPrefab, "Current item", gameObject);
|
|
|
|
// Print some information
|
|
// Item* item = itemPrefab->component<Item>();
|
|
// std::string name = (item == nullptr) ? "unknown" : item->name;
|
|
// std::cout << "Instantiated object " << slot << " (" << name << ")\n";
|
|
}
|
|
else if (0 <= slot)
|
|
{
|
|
std::cout << "Slot " << slot << "empty\n";
|
|
}
|
|
}
|
|
|
|
void PlayerController::onUpdateLogic()
|
|
{
|
|
m_running = false;
|
|
m_walking = false;
|
|
|
|
// Compute movement velocity
|
|
float velMultiplier = PlayerWalkVelocity;
|
|
|
|
// if (m_attackTimeLeft)
|
|
// {
|
|
// velMultiplier = PlayerAttackVelocity;
|
|
// --m_attackTimeLeft;
|
|
// } else
|
|
|
|
if (Input::instance().pressed(GameKey::Run))
|
|
{
|
|
velMultiplier = PlayerRunVelocity;
|
|
m_running = true;
|
|
}
|
|
|
|
|
|
// Make movement time independent
|
|
velMultiplier *= GameState::current().elapsedTime;
|
|
|
|
// 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))
|
|
{
|
|
m_walking = true;
|
|
m_transform->x = newX;
|
|
m_transform->y = newY;
|
|
|
|
m_facingDirection = getDirection(vx, vy);
|
|
}
|
|
}
|
|
|
|
void PlayerController::onPreRender()
|
|
{
|
|
// Get sprite
|
|
SpriteRenderer* spriteRenderer = gameObject->component<SpriteRenderer>();
|
|
|
|
// Compute current state
|
|
std::string stateName = (m_walking) ? "Walking " : "Idle ";
|
|
|
|
if (m_facingDirection & Direction::East)
|
|
stateName += "right";
|
|
else if (m_facingDirection & Direction::West)
|
|
stateName += "left";
|
|
else if (m_facingDirection & Direction::North)
|
|
stateName += "up";
|
|
else
|
|
stateName += "down";
|
|
|
|
spriteRenderer->sprite->setState(stateName);
|
|
|
|
// Set animation velocity
|
|
float animVelocity = (m_running) ? 1.0f : 0.7f;
|
|
// if (m_attackTimeLeft)
|
|
// animVelocity = 0.1f;
|
|
|
|
spriteRenderer->sprite->setAnimationVelocity(animVelocity);
|
|
|
|
// Set weapon
|
|
if (m_currentItem)
|
|
{
|
|
Transform* itemTransf = m_currentItem->component<Transform>();
|
|
itemTransf->x = 0.2f;
|
|
itemTransf->y = -0.8f;
|
|
}
|
|
|
|
// Set camera
|
|
base::Transform* cam = GameState::current().renderContext.cameraTransform();
|
|
cam->x = m_transform->x;
|
|
cam->y = m_transform->y - 1;
|
|
}
|
|
|
|
bool PlayerController::canMove(float x, float y)
|
|
{
|
|
// TODO: check collisions & stuff. For now, nothing
|
|
return true;
|
|
}
|
|
|
|
Direction PlayerController::getDirection(float vx, float vy)
|
|
{
|
|
int xx = (0 < vx) - (vx < 0);
|
|
int yy = (0 < vy) - (vy < 0);
|
|
|
|
return VelocitySignDirections[xx + 1][yy + 1];
|
|
}
|
|
|
|
void PlayerController::attack()
|
|
{
|
|
// For now - nothing
|
|
}
|
|
|
|
void PlayerController::dump(unsigned level)
|
|
{
|
|
for (unsigned i = 0; i < level; i++)
|
|
std::cout<<" ";
|
|
|
|
std::cout << " .Component: PlayerController\n";
|
|
}
|
|
|
|
}
|
|
} /* namespace controller */
|
|
} /* namespace farmlands */
|