diff options
| -rw-r--r-- | queen/graphics.cpp | 14 | ||||
| -rw-r--r-- | queen/graphics.h | 6 | ||||
| -rw-r--r-- | queen/logic.cpp | 269 | ||||
| -rw-r--r-- | queen/logic.h | 13 | ||||
| -rw-r--r-- | queen/structs.h | 11 | ||||
| -rw-r--r-- | queen/walk.cpp | 51 | ||||
| -rw-r--r-- | queen/walk.h | 10 |
7 files changed, 314 insertions, 60 deletions
diff --git a/queen/graphics.cpp b/queen/graphics.cpp index bbf969db8d..d9a808c76a 100644 --- a/queen/graphics.cpp +++ b/queen/graphics.cpp @@ -385,15 +385,15 @@ void Graphics::bobSetupControl() { } -void Graphics::bobAnimString(uint32 bobnum, uint8* animBuf) { +void Graphics::bobAnimString(uint32 bobnum, uint16* animBuf) { BobSlot *pbs = &_bobs[bobnum]; pbs->active = true; pbs->animating = true; pbs->anim.string.buffer = animBuf; pbs->anim.string.curPos = animBuf; - pbs->frameNum = READ_LE_UINT16(animBuf); - pbs->anim.speed = READ_LE_UINT16(animBuf + 2) / 4; + pbs->frameNum = animBuf[0]; + pbs->anim.speed = animBuf[1] / 4; } @@ -499,16 +499,16 @@ void BobSlot::animOneStep() { if (anim.string.buffer != NULL) { --anim.speed; if(anim.speed == 0) { - anim.string.curPos += 4; - uint16 nextFrame = READ_LE_UINT16(anim.string.curPos); + anim.string.curPos += 2; + uint16 nextFrame = anim.string.curPos[0]; if (nextFrame == 0) { anim.string.curPos = anim.string.buffer; - frameNum = READ_LE_UINT16(anim.string.curPos); + frameNum = anim.string.curPos[0]; } else { frameNum = nextFrame; } - anim.speed = READ_LE_UINT16(anim.string.curPos + 2) / 4; + anim.speed = anim.string.curPos[1] / 4; // FIXME: handle that when QueenSound class is ready // play memory sfx and move on to next frame diff --git a/queen/graphics.h b/queen/graphics.h index 6911d85486..787e7da5e7 100644 --- a/queen/graphics.h +++ b/queen/graphics.h @@ -64,8 +64,8 @@ struct BobSlot { //! string based animation struct { - uint8* buffer; - uint8* curPos; + uint16* buffer; + uint16* curPos; } string; //! normal moving animation @@ -115,7 +115,7 @@ public: void bankErase(uint32 bankslot); // erase() void bobSetupControl(); - void bobAnimString(uint32 bobnum, uint8* animBuf); // stringanim() + void bobAnimString(uint32 bobnum, uint16* animBuf); // stringanim() void bobAnimNormal(uint32 bobnum, uint16 firstFrame, uint16 lastFrame, uint16 speed, bool rebound, bool xflip); // makeanim() void bobMove(uint32 bobnum, uint16 endx, uint16 endy, int16 speed); // movebob() void bobDraw(uint32 bobnum, uint16 x, uint16 y, uint16 scale, bool xflip, const Box& box); // bob() diff --git a/queen/logic.cpp b/queen/logic.cpp index 21b947b252..5bebb30619 100644 --- a/queen/logic.cpp +++ b/queen/logic.cpp @@ -32,6 +32,7 @@ Logic::Logic(Resource *resource, Graphics *graphics) _jas = _resource->loadFile("QUEEN.JAS", 20); _joe.x = _joe.y = 0; _walk = new Walk(this, _graphics); + memset(_gameState, 0, sizeof(_gameState)); initialise(); } @@ -360,7 +361,7 @@ void Logic::initialise() { _graphicAnim[i].frame3 = (int16)READ_BE_UINT16(ptr); ptr += 2; } - + _currentRoom = _objectData[_entryObj].room; _entryObj = 0; @@ -438,6 +439,7 @@ void Logic::initialise() { _graphics->panelLoad(); _graphics->bobSetupControl(); _walk->joeSetup(); + zoneSetupPanel(); memset(_zones, 0, sizeof(_zones)); _oldRoom = 0; @@ -855,7 +857,15 @@ void Logic::roomErase() { // TODO: TALKHEAD=0; // TODO: _display->fadeOut(); // TODO: credits system - // TODO: person animations + + // invalidates all persons animations + uint16 i; + for (i = 0; i <= 3; ++i) { + _personFrames[i] = 0; + } + for (i = 1; i <= 16; ++i) { + _newAnim[i][0] = 0; + } uint16 cur = _roomData[_oldRoom] + 1; uint16 last = _roomData[_oldRoom + 1]; @@ -889,13 +899,12 @@ void Logic::roomSetupFurniture() { // count the furniture and update gameState uint16 furnitureTotal = 0; uint16 i; - // FIXME: uncomment when Array< FurnitureData > available in Logic -// for (i = 1; i <= _numFurnitureData; ++i) { -// if (_furnitureData[i].room == _currentRoom) { -// ++furnitureTotal; -// _gameState[furnitureTotal] = _furnitureData[i].gameStateValue; -// } -// } + for (i = 1; i <= _numFurniture; ++i) { + if (_furnitureData[i].room == _currentRoom) { + ++furnitureTotal; + _gameState[furnitureTotal] = _furnitureData[i].gameStateValue; + } + } if (furnitureTotal == 0) { return; } @@ -1018,20 +1027,17 @@ void Logic::roomSetupObjects() { } // persons Bobs - uint16 bobNum = 0; for (i = firstRoomObj; i <= lastRoomObj; ++i) { ObjectData *pod = &_objectData[i]; if (pod->image == -3 || pod->image == -4) { - ++bobNum; - uint16 noun = i - firstRoomObj; - // FIXME: need Person stuff -// if (pod->name > 0) { -// curImage = personSetup(noun, curImage); -// } -// else { -// curImage = personAllocate(noun, curImage); -// } - warning("Logic::roomSetupObjects() - Person object number %d not handled", noun); + debug(9, "Logic::roomSetupObjects() - Setting up person %d", i); + uint16 noun = i - _roomData[_currentRoom]; + if (pod->name > 0) { + curImage = personSetup(noun, curImage); + } + else { + curImage = personAllocate(noun, curImage); + } } } @@ -1108,5 +1114,228 @@ uint16 Logic::findScale(uint16 x, uint16 y) { } +void Logic::personSetData(int16 noun, const char *actorName, bool loadBank, Person *pp) { + + if (noun <= 0) { + warning("Logic::personSetData() - Negative object number"); + } + + uint16 i; + uint16 obj = _roomData[_currentRoom] + noun; + int16 img = _objectData[obj].image; + if (img != -3 && img != -4) { + warning("Logic::personSetData() - Object %d is not a person", obj); + return; + } + + // search Bob number for the person + uint16 bobNum = 0; + for (i = _roomData[_currentRoom] + 1; i <= obj; ++i) { + img = _objectData[i].image; + if (img == -3 || img == -4) { + ++bobNum; + } + } + + // search for a matching actor + uint16 actor = 1; + for (i = 1; i <= _numActors; ++i) { + ActorData *pad = &_actorData[i]; + if (pad->room == _currentRoom) { + if (_gameState[pad->gameStateSlot] == pad->gameStateValue) { + if ((bobNum > 0 && bobNum == pad->bobNum) || strcmp(pp->name, actorName) == 0) { + actor = i; + break; + } + } + } + } + + pp->actor = &_actorData[actor]; + pp->name = _aName[pp->actor->name]; + if (pp->actor->anim != 0) { + pp->anim = _aAnim[pp->actor->anim]; + } + else { + pp->anim = NULL; + } + + if (loadBank) { + const char *actorFile = _aFile[pp->actor->actorFile]; + if (actorFile) { + _graphics->bankLoad(actorFile, pp->bankNum); + } + else { + pp->bankNum = 15; + } + } + + if (pp->actor->bobNum >= 1 && pp->actor->bobNum <= 3) { + pp->bobFrame = 29 + FRAMES_JOE_XTRA + pp->actor->bobNum; + } + else { + warning("Logic::personSetData() - The bob number for actor is not in the [1:3] range"); + } +} + + +uint16 Logic::personSetup(uint16 noun, uint16 curImage) { + + Person p; + personSetData(noun, "", true, &p); + + const ActorData *pad = p.actor; + uint16 scale = 100; + uint16 a = zoneInArea(ZONE_ROOM, pad->x, pad->y); + if (a > 0) { + // person is not standing in the area box, scale it accordingly + scale = currentRoomArea(a)->calcScale(pad->y); + } + _graphics->bankUnpack(pad->bobFrameStanding, p.bobFrame, p.bankNum); + bool xflip = false; + uint16 person = _roomData[_currentRoom] + noun; + if (_objectData[person].image == -3) { + // person is facing left + xflip = true; + } + BobSlot *pbs = _graphics->bob(pad->bobNum); + pbs->active = true; + pbs->scale = scale; + pbs->x = pad->x; + pbs->y = pad->y; + pbs->frameNum = p.bobFrame; + pbs->xflip = xflip; + + if (p.anim != NULL) { + _personFrames[pad->bobNum] = curImage + 1; + curImage = animCreate(curImage, &p); + } + else { + animErase(pad->bobNum); + } + return curImage; +} + + +uint16 Logic::personAllocate(uint16 noun, uint16 curImage) { + + uint16 i; + uint16 person = _roomData[_currentRoom] + noun; + + // search Bob number for the person + uint16 bobNum = 0; + for (i = _roomData[_currentRoom] + 1; i <= person; ++i) { + int16 img = _objectData[i].image; + if (img == -3 || img == -4) { + ++bobNum; + } + } + + // search for a matching actor + uint16 actor = 0; + for (i = 1; i <= _numActors; ++i) { + ActorData *pad = &_actorData[i]; + if (pad->room == _currentRoom) { + if (_gameState[pad->gameStateSlot] == pad->gameStateValue) { + if (bobNum > 0 && bobNum == pad->bobNum) { + actor = i; + break; + } + } + } + } + + if (actor > 0) { + const char *animStr = _aAnim[_actorData[actor].actorFile]; + if (animStr[0] != '\0') { + bool allocatedFrames[256]; + memset(allocatedFrames, 0, sizeof(allocatedFrames)); + uint16 f1, f2; + do { + sscanf(animStr, "%3hu,%3hu", &f1, &f2); + animStr += 8; + allocatedFrames[f1] = true; + } while(f1 != 0); + for (i = 1; i <= 255; ++i) { + if (allocatedFrames[i]) { + ++curImage; + } + } + _personFrames[bobNum] = curImage + 1; + } + } + return curImage; +} + + +uint16 Logic::animCreate(uint16 curImage, const Person *person) { + + uint16 *animFrames = _newAnim[person->actor->bobNum]; + + uint16 allocatedFrames[256]; + memset(allocatedFrames, 0, sizeof(allocatedFrames)); + const char *p = person->anim; + int frame = 0; + uint16 f1, f2; + do { + sscanf(p, "%3hu,%3hu", &f1, &f2); + animFrames[frame + 0] = f1; + animFrames[frame + 1] = f2; + + if (f1 > 500) { + // SFX + allocatedFrames[f1 - 500] = 1; + } + else { + allocatedFrames[f1] = 1; + } + + p += 8; + frame += 2; + } while(f1 != 0); + + // ajust frame numbers + uint16 n = 1; + uint16 i; + for (i = 1; i <= 255; ++i) { + if (allocatedFrames[i] != 0) { + allocatedFrames[i] = n; + ++n; + } + } + for (i = 0; animFrames[i] != 0; i += 2) { + uint16 frameNum = animFrames[i]; + if (frameNum > 500) { + animFrames[i] = curImage + allocatedFrames[frameNum - 500] + 500; + } + else { + animFrames[i] = curImage + allocatedFrames[frameNum]; + } + } + + // unpack necessary frames + for (i = 1; i <= 255; ++i) { + if (allocatedFrames[i] != 0) { + ++curImage; + _graphics->bankUnpack(i, curImage, person->bankNum); + } + } + + // start animation + _graphics->bobAnimString(person->actor->bobNum, animFrames); + + return curImage; +} + + +void Logic::animErase(uint16 bobNum) { + _newAnim[bobNum][0] = 0; + BobSlot *pbs = _graphics->bob(bobNum); + pbs->animating = false; + pbs->anim.string.buffer = NULL; +} + + + } // End of namespace Queen diff --git a/queen/logic.h b/queen/logic.h index a8bcc6b6a7..860b5bebd6 100644 --- a/queen/logic.h +++ b/queen/logic.h @@ -63,7 +63,7 @@ public: uint16 findBob(uint16 obj); uint16 findFrame(uint16 obj); - uint16 objectForPerson(uint16 bobnum); + uint16 objectForPerson(uint16 bobnum); // OBJ_PERSON WalkOffData *walkOffPointForObject(uint16 obj); Area *area(int room, int num); @@ -112,6 +112,13 @@ public: int16 entryObj() const { return _entryObj; } void entryObj(int16 obj) { _entryObj = obj; } + void personSetData(int16 noun, const char *actorName, bool loadBank, Person *pp); // SET_PERSON_DATA + uint16 personSetup(uint16 noun, uint16 curImage); // SETUP_PERSON + uint16 personAllocate(uint16 noun, uint16 curImage); // ALLOCATE_PERSON + + uint16 animCreate(uint16 curImage, const Person *person); // CREATE_ANIM + void animErase(uint16 bobNum); + protected: bool _textToggle; @@ -191,6 +198,10 @@ protected: uint16 _numFurnitureStatic; // FMAX uint16 _numFurnitureAnimatedLen; // FMAXLEN uint16 _numFrames; // FRAMES + uint16 _personFrames[4]; + + //! contains the animation frames (max 60) to use for a bob (whose number must be < 17) + uint16 _newAnim[17][60]; Resource *_resource; Graphics *_graphics; diff --git a/queen/structs.h b/queen/structs.h index 4eea8176fc..f9b501b261 100644 --- a/queen/structs.h +++ b/queen/structs.h @@ -184,6 +184,17 @@ struct GraphicAnim { }; +struct Person { + const ActorData *actor; // P_ROOM, P_BNUM, P_GAMES, P_VALUE, P_COLOR, P_STAND, P_X, P_Y + const char *name; // P_NAMEstr + const char *anim; // P_ANIMstr + uint16 bobFrame; // SFRAME + //! As the bank number may change, we can't re-use actor->bankNum + uint16 bankNum; // P_BANK +}; + + + } // End of namespace Queen #endif diff --git a/queen/walk.cpp b/queen/walk.cpp index 26678e3a25..cc3b635f89 100644 --- a/queen/walk.cpp +++ b/queen/walk.cpp @@ -210,7 +210,7 @@ void Walk::animateJoe() { } -void Walk::animatePersonPrepare(const MovePersonData *mpd, const Person *pp) { +void Walk::animatePersonPrepare(const MovePersonData *mpd, int direction) { // queen.c l.2469-2572 int i; for (i = 1; i <= _walkDataCount; ++i) { @@ -229,7 +229,7 @@ void Walk::animatePersonPrepare(const MovePersonData *mpd, const Person *pp) { } else { // we have specific moves for this actor, see what direction they were last facing - if (pp->direction == -3) { + if (direction == -3) { // previously facing right pwd->anim.set(mpd->walkLeft1, mpd->walkLeft2, DIR_LEFT); } @@ -272,7 +272,7 @@ void Walk::animatePersonPrepare(const MovePersonData *mpd, const Person *pp) { } else { // we have a special move for left/right, so select that instead! - if (pp->direction == -3) { + if (direction == -3) { // previously facing right pwd->anim.set(mpd->walkLeft1, mpd->walkLeft2, DIR_FRONT); } @@ -287,14 +287,14 @@ void Walk::animatePersonPrepare(const MovePersonData *mpd, const Person *pp) { } -void Walk::animatePerson(const MovePersonData *mpd, const Person *pp) { +void Walk::animatePerson(const MovePersonData *mpd, uint16 image, uint16 bobNum, uint16 bankNum, int direction) { // queen.c l.2572-2651 - BobSlot *pbs = _graphics->bob(pp->bobNum); + BobSlot *pbs = _graphics->bob(bobNum); // check to see which way person should be facing if (mpd->walkLeft1 == mpd->walkRight1) { - pbs->xflip = (pp->direction == -3); + pbs->xflip = (direction == -3); } else { // they have special walk for left and right, so don't flip @@ -305,24 +305,24 @@ void Walk::animatePerson(const MovePersonData *mpd, const Person *pp) { for (i = 1; i <= _walkDataCount; ++i) { WalkData *pwd = &_walkData[i]; // unpack necessary frames for bob animation - uint16 dstFrame = pp->image; + uint16 dstFrame = image; uint16 srcFrame = ABS(pwd->anim.firstFrame); while (srcFrame <= ABS(pwd->anim.lastFrame)) { - _graphics->bankUnpack(srcFrame, dstFrame, pp->bankNum); + _graphics->bankUnpack(srcFrame, dstFrame, bankNum); ++dstFrame; ++srcFrame; } // pass across bobs direction ONLY if walk is a mirror flip! if (ABS(mpd->walkLeft1) == ABS(mpd->walkRight1)) { - _graphics->bobAnimNormal(pp->bobNum, pp->image, dstFrame - 1, mpd->animSpeed, false, pbs->xflip); + _graphics->bobAnimNormal(bobNum, image, dstFrame - 1, mpd->animSpeed, false, pbs->xflip); } else { - _graphics->bobAnimNormal(pp->bobNum, pp->image, dstFrame - 1, mpd->animSpeed, false, false); + _graphics->bobAnimNormal(bobNum, image, dstFrame - 1, mpd->animSpeed, false, false); } // move other actors at correct speed relative to scale uint16 moveSpeed = _logic->findScale(pbs->x, pbs->y) * mpd->moveSpeed / 100; - _graphics->bobMove(pp->bobNum, pbs->x + pwd->dx, pbs->y + pwd->dy, moveSpeed); + _graphics->bobMove(bobNum, pbs->x + pwd->dx, pbs->y + pwd->dy, moveSpeed); // flip if one set of frames for actor if (mpd->walkLeft1 < 0 || ABS(mpd->walkLeft1) == ABS(mpd->walkRight1)) { @@ -477,18 +477,21 @@ void Walk::joeMove(int direction, uint16 endx, uint16 endy, bool inCutaway) { -void Walk::personMove(Person* pp, uint16 endx, uint16 endy) { +void Walk::personMove(const Person *pp, uint16 endx, uint16 endy, uint16 curImage, int direction) { // CAN = 0; initWalkData(); - uint16 oldx = _graphics->bob(pp->bobNum)->x; - uint16 oldy = _graphics->bob(pp->bobNum)->y; + uint16 bobNum = pp->actor->bobNum; + uint16 bankNum = pp->bankNum; + + uint16 oldx = _graphics->bob(bobNum)->x; + uint16 oldy = _graphics->bob(bobNum)->y; uint16 oldPos = _logic->zoneInArea(ZONE_ROOM, oldx, oldy); uint16 newPos = _logic->zoneInArea(ZONE_ROOM, endx, endy); - debug(9, "Walk::personMove(%d, %d, %d, %d, %d), old = %d, new = %d", pp->direction, oldx, oldy, endx, endy, oldPos, newPos); + debug(9, "Walk::personMove(%d, %d, %d, %d, %d), old = %d, new = %d", direction, oldx, oldy, endx, endy, oldPos, newPos); calc(oldPos, newPos, oldx, oldy, endx, endy); @@ -505,30 +508,30 @@ void Walk::personMove(Person* pp, uint16 endx, uint16 endy) { } if (_walkDataCount > 0) { - animatePersonPrepare(mpd, pp); - animatePerson(mpd, pp); + animatePersonPrepare(mpd, direction); + animatePerson(mpd, curImage, bobNum, bankNum, direction); } uint16 standingFrame = 0; - if (pp->bobNum <= 3) { - standingFrame = 29 + FRAMES_JOE_XTRA + pp->bobNum; + if (bobNum <= 3) { + standingFrame = 29 + FRAMES_JOE_XTRA + bobNum; } else { - warning("Walk::personMove() - Wrong bob number : %d", pp->bobNum); + warning("Walk::personMove() - Wrong bob number : %d", bobNum); } // make other person face the right direction - BobSlot *pbs = _graphics->bob(pp->bobNum); + BobSlot *pbs = _graphics->bob(bobNum); pbs->endx = endx; pbs->endy = endy; pbs->animating = false; pbs->scale = _walkData[_walkDataCount].area->calcScale(endy); if (_walkData[_walkDataCount].anim.facing == DIR_BACK) { - _graphics->bankUnpack(mpd->backStandingFrame, standingFrame, pp->bankNum); + _graphics->bankUnpack(mpd->backStandingFrame, standingFrame, bankNum); } else { - _graphics->bankUnpack(mpd->frontStandingFrame, standingFrame, pp->bankNum); + _graphics->bankUnpack(mpd->frontStandingFrame, standingFrame, bankNum); } - uint16 obj = _logic->objectForPerson(pp->bobNum); + uint16 obj = _logic->objectForPerson(bobNum); if (_walkData[_walkDataCount].dx < 0) { _logic->objectData(obj)->image = -3; pbs->xflip = true; diff --git a/queen/walk.h b/queen/walk.h index 54d502f65a..3c80024c26 100644 --- a/queen/walk.h +++ b/queen/walk.h @@ -64,7 +64,7 @@ struct MovePersonData { uint16 moveSpeed; }; - +/* struct Person { const char* name; uint16 bobNum; // P_BOB @@ -72,7 +72,7 @@ struct Person { uint16 image; // MOVE_OTHER, CI arg int direction; // MOVE_OTHER, dir arg }; - +*/ class Logic; class Graphics; @@ -95,7 +95,7 @@ public: uint16 joeFace(); //! MOVE_OTHER - void personMove(Person* name, uint16 endx, uint16 endy); + void personMove(const Person *pp, uint16 endx, uint16 endy, uint16 curImage, int direction); private: @@ -105,8 +105,8 @@ private: void animateJoePrepare(); void animateJoe(); - void animatePersonPrepare(const MovePersonData *mpd, const Person* pp); - void animatePerson(const MovePersonData *mpd, const Person* pp); + void animatePersonPrepare(const MovePersonData *mpd, int direction); + void animatePerson(const MovePersonData *mpd, uint16 image, uint16 bobNum, uint16 bankNum, int direction); //! CALC_X, CALC_Y static uint16 calcC(uint16 c1, uint16 c2, uint16 c3, uint16 c4, uint16 lastc); |
