refactor: Move player controls to the Player class
This commit is contained in:
parent
252ab735cc
commit
11dc80a3aa
10 changed files with 245 additions and 118 deletions
|
@ -94,6 +94,7 @@ set(HEADERS
|
|||
src/game/object/waypoint.h
|
||||
src/game/pathfinding.h
|
||||
src/game/paths.h
|
||||
src/game/player.h
|
||||
src/game/room.h
|
||||
src/game/script/routines.h
|
||||
src/game/script/util.h
|
||||
|
@ -225,6 +226,7 @@ set(SOURCES
|
|||
src/game/object/waypoint.cpp
|
||||
src/game/pathfinding.cpp
|
||||
src/game/paths.cpp
|
||||
src/game/player.cpp
|
||||
src/game/room.cpp
|
||||
src/game/script/routines.cpp
|
||||
src/game/script/routines_common.cpp
|
||||
|
|
|
@ -33,7 +33,8 @@ class Camera {
|
|||
public:
|
||||
virtual bool handle(const SDL_Event &event) = 0;
|
||||
virtual void update(float dt) = 0;
|
||||
virtual void clearUserInput() = 0;
|
||||
|
||||
virtual void stopMovement() = 0;
|
||||
|
||||
float heading() const;
|
||||
std::shared_ptr<render::CameraSceneNode> sceneNode() const;
|
||||
|
|
|
@ -152,7 +152,7 @@ void FirstPersonCamera::update(float dt) {
|
|||
}
|
||||
}
|
||||
|
||||
void FirstPersonCamera::clearUserInput() {
|
||||
void FirstPersonCamera::stopMovement() {
|
||||
_moveForward = false;
|
||||
_moveLeft = false;
|
||||
_moveBackward = false;
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
bool handle(const SDL_Event &event) override;
|
||||
void update(float dt) override;
|
||||
void clearUserInput() override;
|
||||
void stopMovement() override;
|
||||
|
||||
void setPosition(const glm::vec3 &position);
|
||||
void setHeading(float heading);
|
||||
|
|
|
@ -121,7 +121,7 @@ void ThirdPersonCamera::updateSceneNode() {
|
|||
_sceneNode->setLocalTransform(transform);
|
||||
}
|
||||
|
||||
void ThirdPersonCamera::clearUserInput() {
|
||||
void ThirdPersonCamera::stopMovement() {
|
||||
_rotateCCW = false;
|
||||
_rotateCW = false;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
bool handle(const SDL_Event &event) override;
|
||||
void update(float dt) override;
|
||||
void clearUserInput() override;
|
||||
void stopMovement() override;
|
||||
|
||||
void setTargetPosition(const glm::vec3 &position);
|
||||
void setHeading(float heading);
|
||||
|
|
|
@ -57,6 +57,7 @@ void Module::load(const string &name, const GffStruct &ifo) {
|
|||
loadInfo(ifo);
|
||||
loadArea(ifo);
|
||||
loadCameras();
|
||||
loadPlayer();
|
||||
|
||||
_loaded = true;
|
||||
}
|
||||
|
@ -127,6 +128,10 @@ void Module::loadCameras() {
|
|||
}
|
||||
}
|
||||
|
||||
void Module::loadPlayer() {
|
||||
_player = make_unique<Player>(this, _area.get(), _thirdPersonCamera.get());
|
||||
}
|
||||
|
||||
bool Module::findObstacle(const glm::vec3 &from, const glm::vec3 &to, glm::vec3 &intersection) const {
|
||||
SpatialObject *obstacle = nullptr;
|
||||
if (_area->findObstacleByWalkmesh(from, to, kObstacleRoom | kObstacleDoor, intersection, &obstacle)) {
|
||||
|
@ -146,6 +151,8 @@ void Module::loadParty(const PartyConfiguration &party, const string &entry) {
|
|||
_area->loadParty(_party, position, heading);
|
||||
_area->updateRoomVisibility();
|
||||
|
||||
_player->setCreature(static_cast<Creature *>(_area->player().get()));
|
||||
|
||||
update3rdPersonCameraTarget();
|
||||
update3rdPersonCameraHeading();
|
||||
switchTo3rdPersonCamera();
|
||||
|
@ -199,7 +206,10 @@ void Module::switchTo3rdPersonCamera() {
|
|||
|
||||
bool Module::handle(const SDL_Event &event) {
|
||||
if (!_loaded) return false;
|
||||
|
||||
if (getCamera()->handle(event)) return true;
|
||||
if (_player->handle(event)) return true;
|
||||
if (_area->handle(event)) return true;
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
|
@ -208,16 +218,11 @@ bool Module::handle(const SDL_Event &event) {
|
|||
case SDL_MOUSEBUTTONUP:
|
||||
if (handleMouseButtonUp(event.button)) return true;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
if (handleKeyDown(event.key)) return true;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
if (handleKeyUp(event.key)) return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_area->handle(event)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -280,8 +285,8 @@ bool Module::handleMouseButtonUp(const SDL_MouseButtonEvent &event) {
|
|||
Creature *creature = dynamic_cast<Creature *>(object);
|
||||
if (creature) {
|
||||
if (!creature->conversation().empty() && _startDialog) {
|
||||
resetPlayerMovement();
|
||||
getCamera()->clearUserInput();
|
||||
_player->stopMovement();
|
||||
getCamera()->stopMovement();
|
||||
|
||||
if (_startDialog) {
|
||||
_startDialog(*creature, creature->conversation());
|
||||
|
@ -293,38 +298,6 @@ bool Module::handleMouseButtonUp(const SDL_MouseButtonEvent &event) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Module::resetPlayerMovement() {
|
||||
_moveForward = false;
|
||||
_moveLeft = false;
|
||||
_moveBackward = false;
|
||||
_moveRight = false;
|
||||
}
|
||||
|
||||
bool Module::handleKeyDown(const SDL_KeyboardEvent &event) {
|
||||
switch (event.keysym.scancode) {
|
||||
case SDL_SCANCODE_W:
|
||||
_moveForward = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_Z:
|
||||
_moveLeft = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_S:
|
||||
_moveBackward = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_C:
|
||||
_moveRight = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Module::handleKeyUp(const SDL_KeyboardEvent &event) {
|
||||
switch (event.keysym.scancode) {
|
||||
case SDL_SCANCODE_V:
|
||||
|
@ -339,31 +312,9 @@ bool Module::handleKeyUp(const SDL_KeyboardEvent &event) {
|
|||
cycleDebugMode(true);
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_W:
|
||||
_moveForward = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_Z:
|
||||
_moveLeft = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_S:
|
||||
_moveBackward = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_C:
|
||||
_moveRight = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_X:
|
||||
static_cast<Creature &>(*_area->player()).playGreetingAnimation();
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Module::toggleCameraType() {
|
||||
|
@ -416,8 +367,9 @@ void Module::update(float dt, GuiContext &guiCtx) {
|
|||
shared_ptr<Camera> camera(getCamera());
|
||||
camera->update(dt);
|
||||
|
||||
updatePlayer(dt);
|
||||
|
||||
if (_cameraType == CameraType::ThirdPerson) {
|
||||
_player->update(dt);
|
||||
}
|
||||
UpdateContext ctx;
|
||||
ctx.deltaTime = dt;
|
||||
ctx.cameraPosition = camera->sceneNode()->absoluteTransform()[3];
|
||||
|
@ -428,47 +380,6 @@ void Module::update(float dt, GuiContext &guiCtx) {
|
|||
_area->fill(ctx, guiCtx);
|
||||
}
|
||||
|
||||
void Module::updatePlayer(float dt) {
|
||||
if (_cameraType != CameraType::ThirdPerson) return;
|
||||
|
||||
ThirdPersonCamera &camera = static_cast<ThirdPersonCamera &>(*_thirdPersonCamera);
|
||||
shared_ptr<Object> playerObject(_area->player());
|
||||
if (!playerObject) return;
|
||||
|
||||
Creature &player = static_cast<Creature &>(*playerObject);
|
||||
|
||||
float heading = 0.0f;
|
||||
bool movement = true;
|
||||
|
||||
if (_moveForward) {
|
||||
heading = camera.heading();
|
||||
} else if (_moveBackward) {
|
||||
heading = camera.heading() + glm::pi<float>();
|
||||
} else if (_moveLeft) {
|
||||
heading = camera.heading() + glm::half_pi<float>();
|
||||
} else if (_moveRight) {
|
||||
heading = camera.heading() - glm::half_pi<float>();
|
||||
} else {
|
||||
movement = false;
|
||||
}
|
||||
|
||||
if (movement) {
|
||||
glm::vec3 target(player.position());
|
||||
target.x -= 100.0f * glm::sin(heading);
|
||||
target.y += 100.0f * glm::cos(heading);
|
||||
|
||||
if (_area->moveCreatureTowards(player, target, dt)) {
|
||||
player.setMovementType(MovementType::Run);
|
||||
update3rdPersonCameraTarget();
|
||||
_area->updateRoomVisibility();
|
||||
_area->selectNearestObject();
|
||||
}
|
||||
|
||||
} else {
|
||||
player.setMovementType(MovementType::None);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::saveTo(GameState &state) const {
|
||||
state.party = _party;
|
||||
_area->saveTo(state);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "area.h"
|
||||
#include "camera/firstperson.h"
|
||||
#include "camera/thirdperson.h"
|
||||
#include "player.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
|
@ -49,6 +50,7 @@ public:
|
|||
|
||||
bool handle(const SDL_Event &event);
|
||||
void update(float dt, GuiContext &guiCtx);
|
||||
void update3rdPersonCameraTarget();
|
||||
void update3rdPersonCameraHeading();
|
||||
void saveTo(GameState &state) const;
|
||||
|
||||
|
@ -82,10 +84,7 @@ private:
|
|||
CameraType _cameraType { CameraType::FirstPerson };
|
||||
std::shared_ptr<FirstPersonCamera> _firstPersonCamera;
|
||||
std::shared_ptr<ThirdPersonCamera> _thirdPersonCamera;
|
||||
bool _moveForward { false };
|
||||
bool _moveLeft { false };
|
||||
bool _moveBackward { false };
|
||||
bool _moveRight { false };
|
||||
std::unique_ptr<Player> _player;
|
||||
|
||||
// Callbacks
|
||||
std::function<void(CameraType)> _onCameraChanged;
|
||||
|
@ -95,12 +94,9 @@ private:
|
|||
|
||||
void toggleCameraType();
|
||||
void cycleDebugMode(bool forward);
|
||||
void updatePlayer(float dt);
|
||||
bool findObstacle(const glm::vec3 &from, const glm::vec3 &to, glm::vec3 &intersection) const;
|
||||
void getEntryPoint(const std::string &waypoint, glm::vec3 &position, float &heading) const;
|
||||
void update3rdPersonCameraTarget();
|
||||
void switchTo3rdPersonCamera();
|
||||
void resetPlayerMovement();
|
||||
SpatialObject *getObjectAt(int x, int y) const;
|
||||
|
||||
// Loading
|
||||
|
@ -108,6 +104,7 @@ private:
|
|||
void loadInfo(const resources::GffStruct &ifo);
|
||||
void loadArea(const resources::GffStruct &ifo);
|
||||
void loadCameras();
|
||||
void loadPlayer();
|
||||
|
||||
// END Loading
|
||||
|
||||
|
@ -115,7 +112,6 @@ private:
|
|||
|
||||
bool handleMouseMotion(const SDL_MouseMotionEvent &event);
|
||||
bool handleMouseButtonUp(const SDL_MouseButtonEvent &event);
|
||||
bool handleKeyDown(const SDL_KeyboardEvent &event);
|
||||
bool handleKeyUp(const SDL_KeyboardEvent &event);
|
||||
|
||||
// END Events
|
||||
|
|
154
src/game/player.cpp
Normal file
154
src/game/player.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright © 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "area.h"
|
||||
#include "camera/camera.h"
|
||||
#include "module.h"
|
||||
#include "object/creature.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
Player::Player(Module *module, Area *area, Camera *camera) : _module(module), _area(area), _camera(camera) {
|
||||
if (!module) {
|
||||
throw invalid_argument("Module must not be null");
|
||||
}
|
||||
if (!area) {
|
||||
throw invalid_argument("Area must not be null");
|
||||
}
|
||||
if (!camera) {
|
||||
throw invalid_argument("Camera must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::handle(const SDL_Event &event) {
|
||||
if (!_creature) return false;
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
return handleKeyDown(event.key);
|
||||
case SDL_KEYUP:
|
||||
return handleKeyUp(event.key);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::handleKeyDown(const SDL_KeyboardEvent &event) {
|
||||
switch (event.keysym.scancode) {
|
||||
case SDL_SCANCODE_W:
|
||||
_moveForward = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_Z:
|
||||
_moveLeft = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_S:
|
||||
_moveBackward = true;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_C:
|
||||
_moveRight = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::handleKeyUp(const SDL_KeyboardEvent &event) {
|
||||
switch (event.keysym.scancode) {
|
||||
case SDL_SCANCODE_W:
|
||||
_moveForward = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_Z:
|
||||
_moveLeft = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_S:
|
||||
_moveBackward = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_C:
|
||||
_moveRight = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_X:
|
||||
_creature->playGreetingAnimation();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::update(float dt) {
|
||||
if (!_creature) return;
|
||||
|
||||
float heading = 0.0f;
|
||||
bool movement = true;
|
||||
|
||||
if (_moveForward) {
|
||||
heading = _camera->heading();
|
||||
} else if (_moveBackward) {
|
||||
heading = _camera->heading() + glm::pi<float>();
|
||||
} else if (_moveLeft) {
|
||||
heading = _camera->heading() + glm::half_pi<float>();
|
||||
} else if (_moveRight) {
|
||||
heading = _camera->heading() - glm::half_pi<float>();
|
||||
} else {
|
||||
movement = false;
|
||||
}
|
||||
if (movement) {
|
||||
glm::vec2 dest(_creature->position());
|
||||
dest.x -= 100.0f * glm::sin(heading);
|
||||
dest.y += 100.0f * glm::cos(heading);
|
||||
|
||||
if (_area->moveCreatureTowards(*_creature, dest, dt)) {
|
||||
_creature->setMovementType(MovementType::Run);
|
||||
_module->update3rdPersonCameraTarget();
|
||||
_area->updateRoomVisibility();
|
||||
_area->selectNearestObject();
|
||||
}
|
||||
} else {
|
||||
_creature->setMovementType(MovementType::None);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::stopMovement() {
|
||||
_moveForward = false;
|
||||
_moveLeft = false;
|
||||
_moveBackward = false;
|
||||
_moveRight = false;
|
||||
}
|
||||
|
||||
void Player::setCreature(Creature *creature) {
|
||||
_creature = creature;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
63
src/game/player.h
Normal file
63
src/game/player.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright © 2020 Vsevolod Kremianskii
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SDL_events.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
class Area;
|
||||
class Camera;
|
||||
class Creature;
|
||||
class Module;
|
||||
|
||||
/**
|
||||
* Encapsulates third-person player controls.
|
||||
*/
|
||||
class Player {
|
||||
public:
|
||||
Player(Module *module, Area *area, Camera *camera);
|
||||
|
||||
bool handle(const SDL_Event &event);
|
||||
void update(float dt);
|
||||
|
||||
void stopMovement();
|
||||
|
||||
void setCreature(Creature *creature);
|
||||
|
||||
Module *_module { nullptr };
|
||||
Area *_area { nullptr };
|
||||
Camera *_camera { nullptr };
|
||||
Creature *_creature { nullptr };
|
||||
bool _moveForward { false };
|
||||
bool _moveLeft { false };
|
||||
bool _moveBackward { false };
|
||||
bool _moveRight { false };
|
||||
|
||||
Player(const Player &) = delete;
|
||||
Player &operator=(const Player &) = delete;
|
||||
|
||||
bool handleKeyDown(const SDL_KeyboardEvent &event);
|
||||
bool handleKeyUp(const SDL_KeyboardEvent &event);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
Loading…
Reference in a new issue