aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicola Mettifogo2008-07-13 13:04:36 +0000
committerNicola Mettifogo2008-07-13 13:04:36 +0000
commitef95c6ff70c1b428ab1d086a9b0b551fc82c8451 (patch)
tree8b997de3ca63b500d31a53002c1486c8533c06c5
parentba5f14692febafdad9c58be67eb6aa87b9afba2f (diff)
downloadscummvm-rg350-ef95c6ff70c1b428ab1d086a9b0b551fc82c8451.tar.gz
scummvm-rg350-ef95c6ff70c1b428ab1d086a9b0b551fc82c8451.tar.bz2
scummvm-rg350-ef95c6ff70c1b428ab1d086a9b0b551fc82c8451.zip
More refactoring of walk code.
svn-id: r33033
-rw-r--r--engines/parallaction/parallaction.cpp56
-rw-r--r--engines/parallaction/parallaction.h10
-rw-r--r--engines/parallaction/parallaction_ns.cpp2
-rw-r--r--engines/parallaction/walk.cpp133
4 files changed, 107 insertions, 94 deletions
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index d03d61fc59..3cde21b49c 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -503,6 +503,34 @@ void Parallaction::freeZones() {
}
+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 = {
+ { 0, 7, 14, 17 },
+ { 1, 8, 15, 18 },
+ { 6, 6, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
+WalkFrames _char24WalkFrames = {
+ { 0, 9, 18, 21 },
+ { 1, 10, 19, 22 },
+ { 8, 8, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
const char Character::_prefixMini[] = "mini";
const char Character::_suffixTras[] = "tras";
const char Character::_empty[] = "\0";
@@ -513,6 +541,9 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder(
_head = NULL;
_objs = NULL;
+ _direction = WALK_DOWN;
+ _step = 0;
+
_dummy = false;
_ani->_left = 150;
@@ -633,4 +664,29 @@ void Parallaction::scheduleLocationSwitch(const char *location) {
}
+
+
+
+void Character::updateDirection(const Common::Point& pos, const Common::Point& to) {
+
+ Common::Point dist(to.x - pos.x, to.y - pos.y);
+ WalkFrames *frames = (_ani->getFrameNum() == 20) ? &_char20WalkFrames : &_char24WalkFrames;
+
+ _step++;
+
+ if (dist.x == 0 && dist.y == 0) {
+ _ani->_frame = 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);
+ _ani->_frame = frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction];
+}
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 2d0a201686..ef2dad9884 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -229,12 +229,17 @@ protected:
static const char _suffixTras[];
static const char _empty[];
+ int16 _direction, _step;
+
public:
void setName(const char *name);
const char *getName() const;
const char *getBaseName() const;
const char *getFullName() const;
bool dummy() const;
+
+ void updateDirection(const Common::Point& pos, const Common::Point& to);
+
};
@@ -263,7 +268,7 @@ public:
void finalizeWalk(Character &character);
int16 selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to);
- void clipMove(Common::Point& pos, const WalkNodePtr to);
+ void clipMove(Common::Point& pos, const Common::Point& to);
ZonePtr findZone(const char *name);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
@@ -357,7 +362,7 @@ protected: // members
void displayComment(ExamineData *data);
- void checkDoor(Character &character);
+ void checkDoor(const Common::Point &foot);
void freeCharacter();
@@ -384,6 +389,7 @@ public:
void beep();
+ ZonePtr _zoneTrap;
public:
// const char **_zoneFlagNamesRes;
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 850123de97..d1b25f189a 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -305,6 +305,8 @@ void Parallaction_ns::changeLocation(char *location) {
_gfx->hideFloatingLabel();
_gfx->freeLabels();
+ _zoneTrap = nullZonePtr;
+
_input->stopHovering();
if (_engineFlags & kEngineBlockInput) {
setArrowCursor();
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 7a16960cbf..40dfddb903 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -27,14 +27,6 @@
namespace Parallaction {
-// should be reset on location switch
-static uint16 _doorData1 = 1000;
-static ZonePtr _zoneTrap;
-
-// should be reset on character switch
-static uint16 walkData1 = 0;
-static uint16 walkData2 = 0; // next walk frame
-
inline byte PathBuffer::getValue(uint16 x, uint16 y) {
byte m = data[(x >> 3) + y * internalWidth];
@@ -261,99 +253,43 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNodePtr Node) {
return 1;
}
-void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr to) {
+void Parallaction::clipMove(Common::Point& pos, const Common::Point& to) {
- if ((pos.x < to->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
- pos.x = (pos.x + 2 < to->_x) ? pos.x + 2 : to->_x;
+ if ((pos.x < to.x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
+ pos.x = (pos.x + 2 < to.x) ? pos.x + 2 : to.x;
}
- if ((pos.x > to->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
- pos.x = (pos.x - 2 > to->_x) ? pos.x - 2 : to->_x;
+ if ((pos.x > to.x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
+ pos.x = (pos.x - 2 > to.x) ? pos.x - 2 : to.x;
}
- if ((pos.y < to->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
- pos.y = (pos.y + 2 <= to->_y) ? pos.y + 2 : to->_y;
+ if ((pos.y < to.y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
+ pos.y = (pos.y + 2 <= to.y) ? pos.y + 2 : to.y;
}
- if ((pos.y > to->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
- pos.y = (pos.y - 2 >= to->_y) ? pos.y - 2 : to->_y;
+ if ((pos.y > to.y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
+ pos.y = (pos.y - 2 >= to.y) ? pos.y - 2 : to.y;
}
return;
}
-int16 Parallaction::selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to) {
-
- Common::Point dist(to->_x - pos.x, to->_y - pos.y);
-
- if (dist.x < 0)
- dist.x = -dist.x;
- if (dist.y < 0)
- dist.y = -dist.y;
-
- walkData1++;
-
- // walk frame selection
- int16 v16;
- if (character._ani->getFrameNum() == 20) {
-
- if (dist.x > dist.y) {
- walkData2 = (to->_x > pos.x) ? 0 : 7;
- walkData1 %= 12;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (to->_y > pos.y) ? 14 : 17;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- } else {
-
- if (dist.x > dist.y) {
- walkData2 = (to->_x > pos.x) ? 0 : 9;
- walkData1 %= 16;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (to->_y > pos.y) ? 18 : 21;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- }
-
- return v16;
-}
-
-void Parallaction::checkDoor(Character &character) {
- if (_currentLocationIndex != _doorData1) {
- _doorData1 = _currentLocationIndex;
- _zoneTrap = nullZonePtr;
- }
-
- _engineFlags &= ~kEngineWalking;
- Common::Point foot;
+void Parallaction::checkDoor(const Common::Point &foot) {
- character.getFoot(foot);
ZonePtr z = hitZone(kZoneDoor, foot.x, foot.y);
-
if (z) {
-
if ((z->_flags & kFlagsClosed) == 0) {
_location._startPosition = z->u.door->_startPos;
_location._startFrame = z->u.door->_startFrame;
-
scheduleLocationSwitch(z->u.door->_location);
_zoneTrap = nullZonePtr;
-
} else {
_cmdExec->run(z->_commands, z);
}
}
- character.getFoot(foot);
z = hitZone(kZoneTrap, foot.x, foot.y);
-
if (z) {
setLocationFlags(kFlagsEnter);
_cmdExec->run(z->_commands, z);
@@ -371,11 +307,14 @@ void Parallaction::checkDoor(Character &character) {
void Parallaction::finalizeWalk(Character &character) {
- checkDoor(character);
+ _engineFlags &= ~kEngineWalking;
+
+ Common::Point foot;
+ character.getFoot(foot);
+ checkDoor(foot);
+
delete character._walkPath;
character._walkPath = 0;
-
- character._ani->_frame = walkData2;
}
void Parallaction_ns::walk(Character &character) {
@@ -386,35 +325,45 @@ void Parallaction_ns::walk(Character &character) {
Common::Point curPos;
character.getFoot(curPos);
+ // update target, if previous was reached
WalkNodeList::iterator it = character._walkPath->begin();
-
if (it != character._walkPath->end()) {
if ((*it)->_x == curPos.x && (*it)->_y == curPos.y) {
debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it)->_x, (*it)->_y);
it = character._walkPath->erase(it);
}
}
+
+ // advance character towards the target
+ Common::Point targetPos;
if (it == character._walkPath->end()) {
debugC(1, kDebugWalk, "walk reached last node");
finalizeWalk(character);
- return;
- }
-
- // selectWalkFrame must be performed before position is changed by clipMove
- int16 walkFrame = selectWalkFrame(character, curPos, *it);
+ targetPos = curPos;
+ } else {
+ if (*it) {
+ // targetPos is saved to help setting character direction
+ targetPos.x = (*it)->_x;
+ targetPos.y = (*it)->_y;
+ }
- Common::Point newPos(curPos);
- clipMove(newPos, *it);
- character.setFoot(newPos);
+ Common::Point newPos(curPos);
+ clipMove(newPos, targetPos);
+ character.setFoot(newPos);
- if (newPos == curPos) {
- debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
- finalizeWalk(character);
- } else {
- character._ani->_frame = walkFrame + walkData2 + 1;
+ if (newPos == curPos) {
+ debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
+ finalizeWalk(character);
+ }
}
- return;
+ // targetPos is used to select the direction (and the walkFrame) of a character,
+ // since it doesn't cause the sudden changes in orientation that newPos would.
+ // Since newPos is 'adjusted' according to walkable areas, an imaginary line drawn
+ // 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.
+ character.updateDirection(curPos, targetPos);
}