aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorNicola Mettifogo2008-07-26 04:01:11 +0000
committerNicola Mettifogo2008-07-26 04:01:11 +0000
commit7950a9183b34fe60f979576c6f4d5b6f9d56a3dc (patch)
treeb944447d67c72ceb375e3c3d8ec09d5432b9c064 /engines
parentaee128467893daa3e3482ad3c9a90b66cbc1bcdf (diff)
downloadscummvm-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.cpp4
-rw-r--r--engines/parallaction/parallaction.cpp52
-rw-r--r--engines/parallaction/parallaction.h5
-rw-r--r--engines/parallaction/walk.cpp117
-rw-r--r--engines/parallaction/walk.h27
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);
};