From eb6dd6d8c8077f417332ab28dee08aacfd1a75e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Boutonn=C3=A9?= Date: Mon, 25 Oct 2010 09:13:57 +0000 Subject: [PATCH] HUGO: Add specific v1d object class svn-id: r53810 --- engines/hugo/hugo.cpp | 7 +- engines/hugo/module.mk | 2 + engines/hugo/object.cpp | 316 ---------------------------------------- engines/hugo/object.h | 30 +++- 4 files changed, 33 insertions(+), 322 deletions(-) diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index cd7d8ac2fcb..1f560acca81 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -167,7 +167,6 @@ Common::Error HugoEngine::run() { _inventory = new InventoryHandler(this); _route = new Route(this); _sound = new SoundHandler(this); - _object = new ObjectHandler(this); switch (_gameVariant) { case 0: // H1 Win @@ -176,6 +175,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v1w(this); _screen = new Screen_v1w(this); _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 1: _file = new FileManager_v2d(this); @@ -183,6 +183,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v2w(this); _screen = new Screen_v1w(this); _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 2: _file = new FileManager_v2d(this); @@ -190,6 +191,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v3w(this); _screen = new Screen_v1w(this); _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 3: // H1 DOS _file = new FileManager_v1d(this); @@ -197,6 +199,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v1d(this); _screen = new Screen_v1d(this); _parser = new Parser_v1d(this); + _object = new ObjectHandler_v1d(this); break; case 4: _file = new FileManager_v2d(this); @@ -204,6 +207,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v2d(this); _screen = new Screen_v1d(this); _parser = new Parser_v2d(this); + _object = new ObjectHandler_v1d(this); break; case 5: _file = new FileManager_v3d(this); @@ -211,6 +215,7 @@ Common::Error HugoEngine::run() { _intro = new intro_v3d(this); _screen = new Screen_v1d(this); _parser = new Parser_v3d(this); + _object = new ObjectHandler_v1d(this); break; } diff --git a/engines/hugo/module.mk b/engines/hugo/module.mk index 12d671f7641..440cf6b265a 100644 --- a/engines/hugo/module.mk +++ b/engines/hugo/module.mk @@ -21,6 +21,8 @@ MODULE_OBJS := \ inventory.o \ mouse.o \ object.o \ + object_v1d.o \ + object_v1w.o \ parser.o \ parser_v1w.o \ parser_v1d.o \ diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp index e594e6918fa..8f4374a7a12 100644 --- a/engines/hugo/object.cpp +++ b/engines/hugo/object.cpp @@ -51,143 +51,6 @@ ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm) { ObjectHandler::~ObjectHandler() { } -// Draw all objects on screen as follows: -// 1. Sort 'FLOATING' objects in order of y2 (base of object) -// 2. Display new object frames/positions in dib -// Finally, cycle any animating objects to next frame -void ObjectHandler::updateImages() { - debugC(5, kDebugEngine, "updateImages"); - - // Initialise the index array to visible objects in current screen - int num_objs = 0; - byte objindex[MAXOBJECTS]; // Array of indeces to objects - - for (int i = 0; i < _vm->_numObj; i++) { - object_t *obj = &_objects[i]; - if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling >= ALMOST_INVISIBLE)) - objindex[num_objs++] = i; - } - - // Sort the objects into increasing y+y2 (painter's algorithm) - qsort(objindex, num_objs, sizeof(objindex[0]), y2comp); - - // Add each visible object to display list - for (int i = 0; i < num_objs; i++) { - object_t *obj = &_objects[objindex[i]]; - // Count down inter-frame timer - if (obj->frameTimer) - obj->frameTimer--; - - if (obj->cycling > ALMOST_INVISIBLE) { // Only if visible - switch (obj->cycling) { - case NOT_CYCLING: - _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); - break; - case CYCLE_FORWARD: - if (obj->frameTimer) // Not time to see next frame yet - _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); - else - _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr->nextSeqPtr, obj->priority == OVEROVL); - break; - case CYCLE_BACKWARD: { - seq_t *seqPtr = obj->currImagePtr; - if (!obj->frameTimer) { // Show next frame - while (seqPtr->nextSeqPtr != obj->currImagePtr) - seqPtr = seqPtr->nextSeqPtr; - } - _vm->_screen->displayFrame(obj->x, obj->y, seqPtr, obj->priority == OVEROVL); - break; - } - default: - break; - } - } - } - - // Cycle any animating objects - for (int i = 0; i < num_objs; i++) { - object_t *obj = &_objects[objindex[i]]; - if (obj->cycling != INVISIBLE) { - // Only if it's visible - if (obj->cycling == ALMOST_INVISIBLE) - obj->cycling = INVISIBLE; - - // Now Rotate to next picture in sequence - switch (obj->cycling) { - case NOT_CYCLING: - break; - case CYCLE_FORWARD: - if (!obj->frameTimer) { - // Time to step to next frame - obj->currImagePtr = obj->currImagePtr->nextSeqPtr; - // Find out if this is last frame of sequence - // If so, reset frame_timer and decrement n_cycle - if (obj->frameInterval || obj->cycleNumb) { - obj->frameTimer = obj->frameInterval; - for (int j = 0; j < obj->seqNumb; j++) { - if (obj->currImagePtr->nextSeqPtr == obj->seqList[j].seqPtr) { - if (obj->cycleNumb) { // Decr cycleNumb if Non-continous - if (!--obj->cycleNumb) - obj->cycling = NOT_CYCLING; - } - } - } - } - } - break; - case CYCLE_BACKWARD: { - if (!obj->frameTimer) { - // Time to step to prev frame - seq_t *seqPtr = obj->currImagePtr; - while (obj->currImagePtr->nextSeqPtr != seqPtr) - obj->currImagePtr = obj->currImagePtr->nextSeqPtr; - // Find out if this is first frame of sequence - // If so, reset frame_timer and decrement n_cycle - if (obj->frameInterval || obj->cycleNumb) { - obj->frameTimer = obj->frameInterval; - for (int j = 0; j < obj->seqNumb; j++) { - if (obj->currImagePtr == obj->seqList[j].seqPtr) { - if (obj->cycleNumb){ // Decr cycleNumb if Non-continous - if (!--obj->cycleNumb) - obj->cycling = NOT_CYCLING; - } - } - } - } - } - break; - } - default: - break; - } - obj->oldx = obj->x; - obj->oldy = obj->y; - } - } -} - -void ObjectHandler::swapImages(int objNumb1, int objNumb2) { -// Swap all the images of one object with another. Set hero_image (we make -// the assumption for now that the first obj is always the HERO) to the object -// number of the swapped image - debugC(1, kDebugSchedule, "swapImages(%d, %d)", objNumb1, objNumb2); - - saveSeq(&_objects[objNumb1]); - - seqList_t tmpSeqList[MAX_SEQUENCES]; - int seqListSize = sizeof(seqList_t) * MAX_SEQUENCES; - - memcpy(tmpSeqList, _objects[objNumb1].seqList, seqListSize); - memcpy(_objects[objNumb1].seqList, _objects[objNumb2].seqList, seqListSize); - memcpy(_objects[objNumb2].seqList, tmpSeqList, seqListSize); - restoreSeq(&_objects[objNumb1]); - _objects[objNumb2].currImagePtr = _objects[objNumb2].seqList[0].seqPtr; - _vm->_heroImage = (_vm->_heroImage == HERO) ? objNumb2 : HERO; - - // Make sure baseline stays constant - _objects[objNumb1].y += _objects[objNumb2].currImagePtr->y2 - _objects[objNumb1].currImagePtr->y2; -} - void ObjectHandler::saveSeq(object_t *obj) { // Save sequence number and image number in given object debugC(1, kDebugFile, "saveSeq"); @@ -217,185 +80,6 @@ void ObjectHandler::restoreSeq(object_t *obj) { obj->currImagePtr = q; } -// Update all object positions. Process object 'local' events -// including boundary events and collisions -void ObjectHandler::moveObjects() { - debugC(4, kDebugEngine, "moveObjects"); - - // If route mode enabled, do special route processing - if (_vm->getGameStatus().routeIndex >= 0) - _vm->_route->processRoute(); - - // Perform any adjustments to velocity based on special path types - // and store all (visible) object baselines into the boundary file. - // Don't store foreground or background objects - for (int i = 0; i < _vm->_numObj; i++) { - object_t *obj = &_objects[i]; // Get pointer to object - seq_t *currImage = obj->currImagePtr; // Get ptr to current image - if (obj->screenIndex == *_vm->_screen_p) { - switch (obj->pathType) { - case CHASE: - case CHASE2: { - int8 radius = obj->radius; // Default to object's radius - if (radius < 0) // If radius infinity, use closer value - radius = DX; - - // Allowable motion wrt boundary - int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1; - int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; - if (abs(dx) <= radius) - obj->vx = 0; - else - obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); - if (abs(dy) <= radius) - obj->vy = 0; - else - obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); - - // Set first image in sequence (if multi-seq object) - switch (obj->seqNumb) { - case 4: - if (!obj->vx) { // Got 4 directions - if (obj->vx != obj->oldvx) { // vx just stopped - if (dy >= 0) - obj->currImagePtr = obj->seqList[DOWN].seqPtr; - else - obj->currImagePtr = obj->seqList[_UP].seqPtr; - } - } else if (obj->vx != obj->oldvx) { - if (dx > 0) - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - break; - case 3: - case 2: - if (obj->vx != obj->oldvx) { // vx just stopped - if (dx > 0) // Left & right only - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - break; - } - - if (obj->vx || obj->vy) - obj->cycling = CYCLE_FORWARD; - else { - obj->cycling = NOT_CYCLING; - _vm->boundaryCollision(obj); // Must have got hero! - } - obj->oldvx = obj->vx; - obj->oldvy = obj->vy; - currImage = obj->currImagePtr; // Get (new) ptr to current image - break; - } - case WANDER2: - case WANDER: - if (!_vm->_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval - obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; - obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; - - // Set first image in sequence (if multi-seq object) - if (obj->seqNumb > 1) { - if (!obj->vx && (obj->seqNumb >= 4)) { - if (obj->vx != obj->oldvx) { // vx just stopped - if (obj->vy > 0) - obj->currImagePtr = obj->seqList[DOWN].seqPtr; - else - obj->currImagePtr = obj->seqList[_UP].seqPtr; - } - } else if (obj->vx != obj->oldvx) { - if (obj->vx > 0) - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - } - obj->oldvx = obj->vx; - obj->oldvy = obj->vy; - currImage = obj->currImagePtr; // Get (new) ptr to current image - } - if (obj->vx || obj->vy) - obj->cycling = CYCLE_FORWARD; - break; - default: - ; // Really, nothing - } - // Store boundaries - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); - } - } - - // Move objects, allowing for boundaries - for (int i = 0; i < _vm->_numObj; i++) { - object_t *obj = &_objects[i]; // Get pointer to object - if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) { - // Only process if it's moving - - // Do object movement. Delta_x,y return allowed movement in x,y - // to move as close to a boundary as possible without crossing it. - seq_t *currImage = obj->currImagePtr; // Get ptr to current image - // object coordinates - int x1 = obj->x + currImage->x1; // Left edge of object - int x2 = obj->x + currImage->x2; // Right edge - int y1 = obj->y + currImage->y1; // Top edge - int y2 = obj->y + currImage->y2; // Bottom edge - - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - _vm->clearBoundary(x1, x2, y2); // Clear our own boundary - - // Allowable motion wrt boundary - int dx = _vm->deltaX(x1, x2, obj->vx, y2); - if (dx != obj->vx) { - // An object boundary collision! - _vm->boundaryCollision(obj); - obj->vx = 0; - } - - int dy = _vm->deltaY(x1, x2, obj->vy, y2); - if (dy != obj->vy) { - // An object boundary collision! - _vm->boundaryCollision(obj); - obj->vy = 0; - } - - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary - - obj->x += dx; // Update object position - obj->y += dy; - - // Don't let object go outside screen - if (x1 < EDGE) - obj->x = EDGE2; - if (x2 > (XPIX - EDGE)) - obj->x = XPIX - EDGE2 - (x2 - x1); - if (y1 < EDGE) - obj->y = EDGE2; - if (y2 > (YPIX - EDGE)) - obj->y = YPIX - EDGE2 - (y2 - y1); - - if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != WANDER2) && (obj->pathType != CHASE2)) - obj->cycling = NOT_CYCLING; - } - } - - // Clear all object baselines from the boundary file. - for (int i = 0; i < _vm->_numObj; i++) { - object_t *obj = &_objects[i]; // Get pointer to object - seq_t *currImage = obj->currImagePtr; // Get ptr to current image - if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); - } - - // If maze mode is enabled, do special maze processing - if (_maze.enabledFl) - _vm->processMaze(); -} - // If status.objid = -1, pick up objid, else use status.objid on objid, // if objid can't be picked up, use it directly void ObjectHandler::useObject(int16 objId) { diff --git a/engines/hugo/object.h b/engines/hugo/object.h index 0f7f4e9e105..4337cf373d2 100644 --- a/engines/hugo/object.h +++ b/engines/hugo/object.h @@ -46,7 +46,11 @@ public: ~ObjectHandler(); object_t *_objects; - + + virtual void moveObjects() = 0; + virtual void updateImages() = 0; + virtual void swapImages(int objNumb1, int objNumb2) = 0; + bool isCarrying(uint16 wordIndex); bool findObjectSpace(object_t *obj, int16 *destx, int16 *desty); @@ -55,12 +59,9 @@ public: void freeObjects(); void loadObject(Common::File &in); void lookObject(object_t *obj); - void moveObjects(); void restoreSeq(object_t *obj); void saveSeq(object_t *obj); void showTakeables(); - void swapImages(int objNumb1, int objNumb2); - void updateImages(); void useObject(int16 objId); static int y2comp(const void *a, const void *b); @@ -83,10 +84,29 @@ public: _objects[objIndex].vxPath = vxPath; _objects[objIndex].vyPath = vyPath; } -private: +protected: HugoEngine *_vm; }; +class ObjectHandler_v1d : public ObjectHandler { +public: + ObjectHandler_v1d(HugoEngine *vm); + ~ObjectHandler_v1d(); + + void moveObjects(); + void updateImages(); + void swapImages(int objNumb1, int objNumb2); +}; + +class ObjectHandler_v1w : public ObjectHandler { +public: + ObjectHandler_v1w(HugoEngine *vm); + ~ObjectHandler_v1w(); + + void moveObjects(); + void updateImages(); + void swapImages(int objNumb1, int objNumb2); +}; } // End of namespace Hugo #endif //HUGO_OBJECT_H