diff options
author | Nicola Mettifogo | 2008-07-26 04:01:11 +0000 |
---|---|---|
committer | Nicola Mettifogo | 2008-07-26 04:01:11 +0000 |
commit | 7950a9183b34fe60f979576c6f4d5b6f9d56a3dc (patch) | |
tree | b944447d67c72ceb375e3c3d8ec09d5432b9c064 /engines | |
parent | aee128467893daa3e3482ad3c9a90b66cbc1bcdf (diff) | |
download | scummvm-rg350-7950a9183b34fe60f979576c6f4d5b6f9d56a3dc.tar.gz scummvm-rg350-7950a9183b34fe60f979576c6f4d5b6f9d56a3dc.tar.bz2 scummvm-rg350-7950a9183b34fe60f979576c6f4d5b6f9d56a3dc.zip |
* Added walk calculations to BRA (doesn't walk yet, though).
* Adapted Character and Animation to handle both versions of the engine.
svn-id: r33296
Diffstat (limited to 'engines')
-rw-r--r-- | engines/parallaction/objects.cpp | 4 | ||||
-rw-r--r-- | engines/parallaction/parallaction.cpp | 52 | ||||
-rw-r--r-- | engines/parallaction/parallaction.h | 5 | ||||
-rw-r--r-- | engines/parallaction/walk.cpp | 117 | ||||
-rw-r--r-- | engines/parallaction/walk.h | 27 |
5 files changed, 176 insertions, 29 deletions
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 66025cf0f7..e04a7d5342 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -60,14 +60,14 @@ Animation::~Animation() { uint16 Animation::width() const { if (!gfxobj) return 0; Common::Rect r; - gfxobj->getRect(0, r); + gfxobj->getRect(_frame, r); return r.width(); } uint16 Animation::height() const { if (!gfxobj) return 0; Common::Rect r; - gfxobj->getRect(0, r); + gfxobj->getRect(_frame, r); return r.height(); } diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index b5f2de851b..78e7af6343 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -497,7 +497,7 @@ const char Character::_suffixTras[] = "tras"; const char Character::_empty[] = "\0"; -Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder(_ani) { +Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation) { _talk = NULL; _head = NULL; _objs = NULL; @@ -516,25 +516,63 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder( _ani->_flags = kFlagsActive | kFlagsNoName; _ani->_type = kZoneYou; strncpy(_ani->_name, "yourself", ZONENAME_LENGTH); + + // TODO: move creation into Parallaction. Needs to make Character a pointer first. + if (_vm->getGameType() == GType_Nippon) + _builder = new PathBuilder_NS(this); + else + _builder = new PathBuilder_BR(this); +} + +Character::~Character() { + delete _builder; + _builder = 0; + + free(); } void Character::getFoot(Common::Point &foot) { - foot.x = _ani->_left + _ani->width() / 2; - foot.y = _ani->_top + _ani->height(); + Common::Rect rect; + _ani->gfxobj->getRect(_ani->_frame, rect); + + foot.x = _ani->_left + (rect.left + rect.width() / 2); + foot.y = _ani->_top + (rect.top + rect.height()); } void Character::setFoot(const Common::Point &foot) { - _ani->_left = foot.x - _ani->width() / 2; - _ani->_top = foot.y - _ani->height(); + Common::Rect rect; + _ani->gfxobj->getRect(_ani->_frame, rect); + + _ani->_left = foot.x - (rect.left + rect.width() / 2); + _ani->_top = foot.y - (rect.top + rect.height()); } +#if 0 +void dumpPath(PointList *list, const char* text) { + for (PointList::iterator it = list->begin(); it != list->end(); it++) + printf("node (%i, %i)\n", it->x, it->y); + + return; +} +#endif + void Character::scheduleWalk(int16 x, int16 y) { if ((_ani->_flags & kFlagsRemove) || (_ani->_flags & kFlagsActive) == 0) { return; } - _walkPath = _builder.buildPath(x, y); - _engineFlags |= kEngineWalking; + _walkPath = _builder->buildPath(x, y); +#if 0 + dumpPath(_walkPath, _name); +#endif + + if (_vm->getGameType() == GType_Nippon) { + _engineFlags |= kEngineWalking; + } else { + // BRA can't walk yet! + delete _walkPath; + _walkPath = 0; + } } void Character::free() { diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 24e9b18ba9..03bff44981 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -198,10 +198,12 @@ struct Character { GfxObj *_head; GfxObj *_talk; GfxObj *_objs; - PathBuilder _builder; + PathBuilder *_builder; PointList *_walkPath; Character(Parallaction *vm); + ~Character(); + void getFoot(Common::Point &foot); void setFoot(const Common::Point &foot); void scheduleWalk(int16 x, int16 y); @@ -379,6 +381,7 @@ public: void beep(); ZonePtr _zoneTrap; + PathBuilder* getPathBuilder(Character *ch); public: // const char **_zoneFlagNamesRes; diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 98557bf22c..fa6c7d5ede 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -28,15 +28,29 @@ namespace Parallaction { + inline byte PathBuffer::getValue(uint16 x, uint16 y) { byte m = data[(x >> 3) + y * internalWidth]; - uint n = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7)); - return ((1 << n) & m) >> n; + uint bit = 0; + switch (_vm->getGameType()) { + case GType_Nippon: + bit = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7)); + break; + + case GType_BRA: + // Amiga and PC versions pack the path bits the same way in BRA + bit = 7 - (x & 7); + break; + + default: + error("path mask not yet implemented for this game type"); + } + return ((1 << bit) & m) >> bit; } // adjusts position towards nearest walkable point // -void PathBuilder::correctPathPoint(Common::Point &to) { +void PathBuilder_NS::correctPathPoint(Common::Point &to) { if (_vm->_pathBuffer->getValue(to.x, to.y)) return; @@ -84,7 +98,7 @@ void PathBuilder::correctPathPoint(Common::Point &to) { } -uint32 PathBuilder::buildSubPath(const Common::Point& pos, const Common::Point& stop) { +uint32 PathBuilder_NS::buildSubPath(const Common::Point& pos, const Common::Point& stop) { uint32 v28 = 0; uint32 v2C = 0; @@ -128,19 +142,11 @@ uint32 PathBuilder::buildSubPath(const Common::Point& pos, const Common::Point& return v34; } -#if 0 -void printNodes(WalkNodeList *list, const char* text) { - printf("%s\n-------------------\n", text); - for (WalkNodeList::iterator it = list->begin(); it != list->end(); it++) - printf("node [%p] (%i, %i)\n", *it, (*it)->_x, (*it)->_y); - return; -} -#endif // // x, y: mouse click (foot) coordinates // -PointList *PathBuilder::buildPath(uint16 x, uint16 y) { +PointList *PathBuilder_NS::buildPath(uint16 x, uint16 y) { debugC(1, kDebugWalk, "PathBuilder::buildPath to (%i, %i)", x, y); Common::Point to(x, y); @@ -169,7 +175,7 @@ PointList *PathBuilder::buildPath(uint16 x, uint16 y) { Common::Point stop(v48.x, v48.y); Common::Point pos; - _vm->_char.getFoot(pos); + _ch->getFoot(pos); uint32 v34 = buildSubPath(pos, stop); if (v38 != 0 && v34 > v38) { @@ -201,14 +207,14 @@ PointList *PathBuilder::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::walkFunc1(int16 x, int16 y, Common::Point& node) { +uint16 PathBuilder_NS::walkFunc1(int16 x, int16 y, Common::Point& node) { Common::Point arg(x, y); Common::Point v4(0, 0); Common::Point foot; - _vm->_char.getFoot(foot); + _ch->getFoot(foot); Common::Point v8(foot); @@ -364,8 +370,85 @@ void Parallaction_ns::walk(Character &character) { -PathBuilder::PathBuilder(AnimationPtr anim) : _anim(anim), _list(0) { +PathBuilder_NS::PathBuilder_NS(Character *ch) : PathBuilder(ch), _list(0) { +} + +#define isPositionOnPath(x,y) _vm->_pathBuffer->getValue((x), (y)) + + +bool PathBuilder_BR::directPathExists(const Common::Point &from, const Common::Point &to) { + + Common::Point copy(from); + Common::Point p(copy); + + while (p != to) { + + if (p.x < to.x && isPositionOnPath(p.x + 1, p.y)) p.x++; + if (p.x > to.x && isPositionOnPath(p.x - 1, p.y)) p.x--; + if (p.y < to.y && isPositionOnPath(p.x, p.y + 1)) p.y++; + if (p.y > to.y && isPositionOnPath(p.x, p.y - 1)) p.y--; + + if (p == copy && p != to) { + return false; + } + + copy = p; + } + + return true; } +PointList* PathBuilder_BR::buildPath(uint16 x, uint16 y) { + Common::Point foot; + _ch->getFoot(foot); + + debugC(1, kDebugWalk, "buildPath: from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y); + + PointList *list = new PointList; + + // look for easy path first + Common::Point dest(x, y); + if (directPathExists(foot, dest)) { + list->push_back(dest); + debugC(3, kDebugWalk, "buildPath: direct path found"); + return list; + } + + // look for short circuit cases + ZonePtr z0 = _vm->hitZone(kZonePath, x, y); + if (z0 == nullZonePtr) { + list->push_back(dest); + debugC(3, kDebugWalk, "buildPath: corner case 0"); + return list; + } + ZonePtr z1 = _vm->hitZone(kZonePath, foot.x, foot.y); + if (z1 == nullZonePtr || z1 == z0) { + list->push_back(dest); + debugC(3, kDebugWalk, "buildPath: corner case 1"); + return list; + } + + // build complex path + int id = atoi(z0->_name); + + if (z1->u.path->_lists[id].empty()) { + list->clear(); + debugC(3, kDebugWalk, "buildPath: no path"); + return list; + } + + PointList::iterator b = z1->u.path->_lists[id].begin(); + PointList::iterator e = z1->u.path->_lists[id].end(); + for ( ; b != e; b++) { + list->push_front(*b); + } + list->push_back(dest); + debugC(3, kDebugWalk, "buildPath: complex path"); + + return list; +} + +PathBuilder_BR::PathBuilder_BR(Character *ch) : PathBuilder(ch) { +} } // namespace Parallaction diff --git a/engines/parallaction/walk.h b/engines/parallaction/walk.h index dddf2857be..4df89faec1 100644 --- a/engines/parallaction/walk.h +++ b/engines/parallaction/walk.h @@ -31,11 +31,25 @@ #include "parallaction/objects.h" + namespace Parallaction { +struct Character; + class PathBuilder { - AnimationPtr _anim; +protected: + Character *_ch; + +public: + PathBuilder(Character *ch) : _ch(ch) { } + virtual ~PathBuilder() { } + + virtual PointList* buildPath(uint16 x, uint16 y) = 0; +}; + + +class PathBuilder_NS : public PathBuilder { PointList *_list; PointList _subPath; @@ -45,9 +59,18 @@ class PathBuilder { uint16 walkFunc1(int16 x, int16 y, Common::Point& node); public: - PathBuilder(AnimationPtr anim); + PathBuilder_NS(Character *ch); PointList* buildPath(uint16 x, uint16 y); +}; + + +class PathBuilder_BR : public PathBuilder { + bool directPathExists(const Common::Point &from, const Common::Point &to); + +public: + PathBuilder_BR(Character *ch); + PointList* buildPath(uint16 x, uint16 y); }; |