aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/walk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/parallaction/walk.cpp')
-rw-r--r--engines/parallaction/walk.cpp99
1 files changed, 75 insertions, 24 deletions
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 4357f19474..2ccbedff44 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -31,9 +31,38 @@ namespace Parallaction {
#define IS_PATH_CLEAR(x,y) _vm->_gfx->_backgroundInfo->_path->getValue((x), (y))
+enum {
+ WALK_LEFT = 0,
+ WALK_RIGHT = 1,
+ WALK_DOWN = 2,
+ WALK_UP = 3
+};
+
+struct WalkFrames {
+ int16 stillFrame[4];
+ int16 firstWalkFrame[4];
+ int16 numWalkFrames[4];
+ int16 frameRepeat[4];
+};
+
+WalkFrames _char20WalkFrames_NS = {
+ { 0, 7, 14, 17 },
+ { 1, 8, 15, 18 },
+ { 6, 6, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
+WalkFrames _char24WalkFrames_NS = {
+ { 0, 9, 18, 21 },
+ { 1, 10, 19, 22 },
+ { 8, 8, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
+
// adjusts position towards nearest walkable point
//
-void PathBuilder_NS::correctPathPoint(Common::Point &to) {
+void PathWalker_NS::correctPathPoint(Common::Point &to) {
if (IS_PATH_CLEAR(to.x, to.y)) return;
@@ -84,7 +113,7 @@ void PathBuilder_NS::correctPathPoint(Common::Point &to) {
}
-uint32 PathBuilder_NS::buildSubPath(const Common::Point& pos, const Common::Point& stop) {
+uint32 PathWalker_NS::buildSubPath(const Common::Point& pos, const Common::Point& stop) {
uint32 v28 = 0;
uint32 v2C = 0;
@@ -132,10 +161,12 @@ uint32 PathBuilder_NS::buildSubPath(const Common::Point& pos, const Common::Poin
//
// x, y: mouse click (foot) coordinates
//
-void PathBuilder_NS::buildPath(uint16 x, uint16 y) {
+void PathWalker_NS::buildPath(AnimationPtr a, uint16 x, uint16 y) {
debugC(1, kDebugWalk, "PathBuilder::buildPath to (%i, %i)", x, y);
- _ch->_walkPath.clear();
+ _a = a;
+
+ _walkPath.clear();
Common::Point to(x, y);
correctPathPoint(to);
@@ -148,26 +179,26 @@ void PathBuilder_NS::buildPath(uint16 x, uint16 y) {
if (v38 == 1) {
// destination directly reachable
debugC(1, kDebugWalk, "direct move to (%i, %i)", to.x, to.y);
- _ch->_walkPath.push_back(v48);
+ _walkPath.push_back(v48);
return;
}
// path is obstructed: look for alternative
- _ch->_walkPath.push_back(v48);
+ _walkPath.push_back(v48);
Common::Point pos;
- _ch->getFoot(pos);
+ _a->getFoot(pos);
uint32 v34 = buildSubPath(pos, v48);
if (v38 != 0 && v34 > v38) {
// no alternative path (gap?)
- _ch->_walkPath.clear();
- _ch->_walkPath.push_back(v44);
+ _walkPath.clear();
+ _walkPath.push_back(v44);
return;
}
- _ch->_walkPath.insert(_ch->_walkPath.begin(), _subPath.begin(), _subPath.end());
+ _walkPath.insert(_walkPath.begin(), _subPath.begin(), _subPath.end());
- buildSubPath(pos, *_ch->_walkPath.begin());
- _ch->_walkPath.insert(_ch->_walkPath.begin(), _subPath.begin(), _subPath.end());
+ buildSubPath(pos, *_walkPath.begin());
+ _walkPath.insert(_walkPath.begin(), _subPath.begin(), _subPath.end());
return;
}
@@ -180,14 +211,14 @@ void PathBuilder_NS::buildPath(uint16 x, uint16 y) {
// 1 : Point reachable in a straight line
// other values: square distance to target (point not reachable in a straight line)
//
-uint16 PathBuilder_NS::walkFunc1(const Common::Point &to, Common::Point& node) {
+uint16 PathWalker_NS::walkFunc1(const Common::Point &to, Common::Point& node) {
Common::Point arg(to);
Common::Point v4;
Common::Point foot;
- _ch->getFoot(foot);
+ _a->getFoot(foot);
Common::Point v8(foot);
@@ -286,10 +317,10 @@ void PathWalker_NS::finalizeWalk() {
_engineFlags &= ~kEngineWalking;
Common::Point foot;
- _ch->getFoot(foot);
+ _a->getFoot(foot);
checkDoor(foot);
- _ch->_walkPath.clear();
+ _walkPath.clear();
}
void PathWalker_NS::walk() {
@@ -298,20 +329,20 @@ void PathWalker_NS::walk() {
}
Common::Point curPos;
- _ch->getFoot(curPos);
+ _a->getFoot(curPos);
// update target, if previous was reached
- PointList::iterator it = _ch->_walkPath.begin();
- if (it != _ch->_walkPath.end()) {
+ PointList::iterator it = _walkPath.begin();
+ if (it != _walkPath.end()) {
if (*it == curPos) {
debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it).x, (*it).y);
- it = _ch->_walkPath.erase(it);
+ it = _walkPath.erase(it);
}
}
// advance character towards the target
Common::Point targetPos;
- if (it == _ch->_walkPath.end()) {
+ if (it == _walkPath.end()) {
debugC(1, kDebugWalk, "walk reached last node");
finalizeWalk();
targetPos = curPos;
@@ -321,7 +352,7 @@ void PathWalker_NS::walk() {
Common::Point newPos(curPos);
clipMove(newPos, targetPos);
- _ch->setFoot(newPos);
+ _a->setFoot(newPos);
if (newPos == curPos) {
debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
@@ -336,12 +367,32 @@ void PathWalker_NS::walk() {
// from curPos to newPos is prone to abrutply change in direction, thus making the
// code select 'too different' frames when walking diagonally against obstacles,
// and yielding an annoying shaking effect in the character.
- _ch->updateDirection(curPos, targetPos);
+ updateDirection(curPos, targetPos);
}
+void PathWalker_NS::updateDirection(const Common::Point& pos, const Common::Point& to) {
+
+ Common::Point dist(to.x - pos.x, to.y - pos.y);
+ WalkFrames *frames = (_a->getFrameNum() == 20) ? &_char20WalkFrames_NS : &_char24WalkFrames_NS;
+
+ _step++;
+
+ if (dist.x == 0 && dist.y == 0) {
+ _a->setF(frames->stillFrame[_direction]);
+ return;
+ }
+
+ if (dist.x < 0)
+ dist.x = -dist.x;
+ if (dist.y < 0)
+ dist.y = -dist.y;
+
+ _direction = (dist.x > dist.y) ? ((to.x > pos.x) ? WALK_LEFT : WALK_RIGHT) : ((to.y > pos.y) ? WALK_DOWN : WALK_UP);
+ _a->setF(frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction]);
+}
-PathBuilder_NS::PathBuilder_NS(Character *ch) : PathBuilder(ch) {
+PathWalker_NS::PathWalker_NS() : _direction(WALK_DOWN), _step(0) {
}