Skip to content

Commit

Permalink
KOTORBASE: Extract PC movement logic to a separate class
Browse files Browse the repository at this point in the history
  • Loading branch information
vkremianskii committed Feb 23, 2019
1 parent 8c48295 commit 7584037
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 72 deletions.
77 changes: 8 additions & 69 deletions src/engines/kotorbase/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,10 @@ Module::Module(::Engines::Console &console) :
_freeCamEnabled(false),
_prevTimestamp(0),
_frameTime(0),
_forwardBtnPressed(false),
_backwardsBtnPressed(false),
_pcRunning(false),
_pcPositionLoaded(false),
_inDialog(false),
_cameraHeight(0.0f) {
_cameraHeight(0.0f),
_playerController(this) {

loadSurfaceTypes();
}
Expand Down Expand Up @@ -177,6 +175,7 @@ void Module::loadModule(const Common::UString &module, const Common::UString &en

void Module::usePC(Creature *pc) {
_pc.reset(pc);
_playerController.setPC(_pc.get());
}

Creature *Module::getPC() {
Expand Down Expand Up @@ -527,7 +526,7 @@ void Module::clickObject(Object *object) {
if (placeable) {
if (placeable->hasInventory()) {
stopCameraMovement();
stopPCMovement();
_playerController.stopMovement();

_ingame->showContainer(placeable->getInventory());
placeable->close(_pc.get());
Expand Down Expand Up @@ -605,24 +604,7 @@ void Module::handleEvents() {
}
}

// PC movement
switch (event->type) {
case Events::kEventKeyDown:
case Events::kEventKeyUp:
if (event->key.keysym.scancode == SDL_SCANCODE_W) {
_forwardBtnPressed = event->type == Events::kEventKeyDown;
} else if (event->key.keysym.scancode == SDL_SCANCODE_S) {
_backwardsBtnPressed = event->type == Events::kEventKeyDown;
}
break;

case Events::kEventControllerAxisMotion:
if (event->caxis.axis == Events::kControllerAxisLeftY) {
_backwardsBtnPressed = event->caxis.value > 10000;
_forwardBtnPressed = event->caxis.value < -10000;
}
break;
}
_playerController.handleEvent(*event);

// Camera
if (!_console->isVisible()) {
Expand Down Expand Up @@ -658,36 +640,7 @@ void Module::handlePCMovement() {
if (!_pc)
return;

bool haveMovement = false;

if (_forwardBtnPressed || _backwardsBtnPressed) {
float x, y, z;
_pc->getPosition(x, y, z);
float yaw = SatelliteCam.getYaw();
float moveRate = _pc->getRunRate();
float newX, newY;

if (_forwardBtnPressed && !_backwardsBtnPressed) {
_pc->setOrientation(0, 0, 1, Common::rad2deg(yaw));
newX = x - moveRate * sin(yaw) * _frameTime;
newY = y + moveRate * cos(yaw) * _frameTime;
haveMovement = true;
} else if (_backwardsBtnPressed && !_forwardBtnPressed) {
_pc->setOrientation(0, 0, 1, 180 + Common::rad2deg(yaw));
newX = x + moveRate * sin(yaw) * _frameTime;
newY = y - moveRate * cos(yaw) * _frameTime;
haveMovement = true;
}

if (haveMovement) {
z = _area->evaluateElevation(newX, newY);
if (z != FLT_MIN) {
if (_area->walkable(glm::vec3(x, y, z + 0.1f),
glm::vec3(newX, newY, z + 0.1f)))
movePC(newX, newY, z);
}
}
}
_playerController.processMovement(_frameTime);

const float *position = CameraMan.getPosition();
SoundMan.setListenerPosition(position[0], position[1], position[2]);
Expand All @@ -696,14 +649,6 @@ void Module::handlePCMovement() {

_ingame->setRotation(Common::rad2deg(SatelliteCam.getYaw()));
_ingame->updateSelection();

if (haveMovement && !_pcRunning) {
_pc->playAnimation(Common::UString("run"), false, -1.0f);
_pcRunning = true;
} else if (!haveMovement && _pcRunning) {
_pc->playDefaultAnimation();
_pcRunning = false;
}
}

void Module::handleActions() {
Expand Down Expand Up @@ -807,6 +752,7 @@ void Module::switchPlayerCharacter(int npc) {
std::advance(iter, npc);
_pc.release();
_pc.reset(*iter);
_playerController.setPC(_pc.get());

Creature *pc = *iter;
_party.erase(iter);
Expand Down Expand Up @@ -1034,7 +980,7 @@ void Module::startConversation(const Common::UString &name, Aurora::NWScript::Ob

if (_dialog->isConversationActive()) {
stopCameraMovement();
stopPCMovement();
_playerController.stopMovement();

_ingame->hide();
_dialog->show();
Expand Down Expand Up @@ -1103,13 +1049,6 @@ void Module::stopCameraMovement() {
SatelliteCam.clearInput();
}

void Module::stopPCMovement() {
_forwardBtnPressed = false;
_backwardsBtnPressed = false;
_pc->playDefaultAnimation();
_pcRunning = false;
}

} // End of namespace KotORBase

} // End of namespace Engines
5 changes: 2 additions & 3 deletions src/engines/kotorbase/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "src/engines/kotorbase/object.h"
#include "src/engines/kotorbase/objectcontainer.h"
#include "src/engines/kotorbase/savedgame.h"
#include "src/engines/kotorbase/playercontroller.h"

#include "src/engines/kotorbase/gui/ingame.h"
#include "src/engines/kotorbase/gui/dialog.h"
Expand Down Expand Up @@ -291,12 +292,10 @@ class Module : public Object, public ObjectContainer {
bool _freeCamEnabled;
uint32 _prevTimestamp;
float _frameTime;
float _forwardBtnPressed;
float _backwardsBtnPressed;
bool _pcRunning;
bool _pcPositionLoaded;
bool _inDialog;
float _cameraHeight;
PlayerController _playerController;


// Surface types
Expand Down
128 changes: 128 additions & 0 deletions src/engines/kotorbase/playercontroller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/* xoreos - A reimplementation of BioWare's Aurora engine
*
* xoreos is the legal property of its developers, whose names
* can be found in the AUTHORS file distributed with this source
* distribution.
*
* xoreos 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.
*
* xoreos 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 xoreos. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file
* Handles player character movement in KotOR games.
*/

#include "src/common/maths.h"

#include "src/engines/aurora/satellitecamera.h"

#include "src/engines/kotorbase/playercontroller.h"
#include "src/engines/kotorbase/module.h"
#include "src/engines/kotorbase/creature.h"
#include "src/engines/kotorbase/area.h"

namespace Engines {

namespace KotORBase {

PlayerController::PlayerController(Module *module) :
_module(module),
_pc(0),
_forwardMovementWanted(false),
_backwardMovementWanted(false),
_moving(false) {
}

void PlayerController::setPC(Creature *pc) {
_pc = pc;
}

void PlayerController::stopMovement() {
_forwardMovementWanted = false;
_backwardMovementWanted = false;
_pc->playDefaultAnimation();
_moving = false;
}

bool PlayerController::handleEvent(const Events::Event &e) {
switch (e.type) {
case Events::kEventKeyDown:
case Events::kEventKeyUp:
if (e.key.keysym.scancode == SDL_SCANCODE_W) {
_forwardMovementWanted = (e.type == Events::kEventKeyDown);
return true;
} else if (e.key.keysym.scancode == SDL_SCANCODE_S) {
_backwardMovementWanted = (e.type == Events::kEventKeyDown);
return true;
}
return false;

case Events::kEventControllerAxisMotion:
if (e.caxis.axis == Events::kControllerAxisLeftY) {
_forwardMovementWanted = (e.caxis.value < -10000);
_backwardMovementWanted = (e.caxis.value > 10000);
return true;
}
return false;

default:
return false;
}
}

bool PlayerController::processMovement(float frameTime) {
bool moveForwards = _forwardMovementWanted && !_backwardMovementWanted;
bool moveBackwards = !_forwardMovementWanted && _backwardMovementWanted;

if (!moveForwards && !moveBackwards) {
if (_moving) {
_pc->playDefaultAnimation();
_moving = false;
}
return false;
}

float x, y, _;
_pc->getPosition(x, y, _);
float yaw = SatelliteCam.getYaw();
float newX, newY;
float moveRate = _pc->getRunRate();

if (moveForwards) {
_pc->setOrientation(0.0f, 0.0f, 1.0f, Common::rad2deg(yaw));
newX = x - moveRate * sin(yaw) * frameTime;
newY = y + moveRate * cos(yaw) * frameTime;
} else {
_pc->setOrientation(0.0f, 0.0f, 1.0f, 180 + Common::rad2deg(yaw));
newX = x + moveRate * sin(yaw) * frameTime;
newY = y - moveRate * cos(yaw) * frameTime;
}

float z = _module->getCurrentArea()->evaluateElevation(newX, newY);
if (z != FLT_MIN) {
if (_module->getCurrentArea()->walkable(glm::vec3(x, y, z + 0.1f),
glm::vec3(newX, newY, z + 0.1f)))
_module->movePC(newX, newY, z);
}

if (!_moving) {
_pc->playAnimation(Common::UString("run"), false, -1.0f);
_moving = true;
}

return true;
}

} // End of namespace KotORBase

} // End of namespace Engines
59 changes: 59 additions & 0 deletions src/engines/kotorbase/playercontroller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* xoreos - A reimplementation of BioWare's Aurora engine
*
* xoreos is the legal property of its developers, whose names
* can be found in the AUTHORS file distributed with this source
* distribution.
*
* xoreos 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.
*
* xoreos 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 xoreos. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file
* Handles player character movement in KotOR games.
*/

#ifndef ENGINES_KOTORBASE_PLAYERCONTROLLER_H
#define ENGINES_KOTORBASE_PLAYERCONTROLLER_H

#include "src/events/events.h"

namespace Engines {

namespace KotORBase {

class Module;
class Creature;

class PlayerController {
public:
PlayerController(Module *module);

void setPC(Creature *pc);

void stopMovement();
bool handleEvent(const Events::Event &e);
bool processMovement(float frameTime);

private:
Module *_module;
Creature *_pc;
bool _forwardMovementWanted;
bool _backwardMovementWanted;
bool _moving;
};

} // End of namespace KotORBase

} // End of namespace Engines

#endif // ENGINES_KOTORBASE_PLAYERCONTROLLER_H
2 changes: 2 additions & 0 deletions src/engines/kotorbase/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ src_engines_kotorbase_libkotorbase_la_SOURCES += \
src/engines/kotorbase/actionexecutor.h \
src/engines/kotorbase/savedgame.h \
src/engines/kotorbase/game.h \
src/engines/kotorbase/playercontroller.h \
$(EMPTY)

src_engines_kotorbase_libkotorbase_la_SOURCES += \
Expand All @@ -67,6 +68,7 @@ src_engines_kotorbase_libkotorbase_la_SOURCES += \
src/engines/kotorbase/actionexecutor.cpp \
src/engines/kotorbase/savedgame.cpp \
src/engines/kotorbase/game.cpp \
src/engines/kotorbase/playercontroller.cpp \
$(EMPTY)

include src/engines/kotorbase/script/rules.mk
Expand Down

0 comments on commit 7584037

Please sign in to comment.