aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-14 13:26:47 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit65d24b04519a5e0bbd7b1efbf6b379d539b424e5 (patch)
tree068d8ab56ab06648faea3b74b3bd9639c4fc8a20
parent0187c795d5e1569105d4cb49a16810f6a50cc261 (diff)
downloadscummvm-rg350-65d24b04519a5e0bbd7b1efbf6b379d539b424e5.tar.gz
scummvm-rg350-65d24b04519a5e0bbd7b1efbf6b379d539b424e5.tar.bz2
scummvm-rg350-65d24b04519a5e0bbd7b1efbf6b379d539b424e5.zip
STARTREK: Basic walking
-rw-r--r--engines/startrek/awaymission.cpp21
-rw-r--r--engines/startrek/awaymission.h2
-rw-r--r--engines/startrek/object.h30
-rw-r--r--engines/startrek/startrek.cpp179
-rw-r--r--engines/startrek/startrek.h11
5 files changed, 215 insertions, 28 deletions
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp
index 73526eeaa2..77576d295c 100644
--- a/engines/startrek/awaymission.cpp
+++ b/engines/startrek/awaymission.cpp
@@ -158,10 +158,10 @@ void StarTrekEngine::handleAwayMissionEvents() {
_gfx->incPaletteFadeLevel();
break;
case TREKEVENT_LBUTTONDOWN:
- if (_awayMission.field1d != 0)
- break;
+ //if (_awayMission.field1d != 0) // FIXME: uncomment
+ // break;
switch (_awayMission.mapFileLoaded) {
- case 0:
+ case 1:
if (_awayMission.field1c == 0) {
_kirkObject->sprite.drawMode = 1; // Hide these objects for function call below?
_spockObject->sprite.drawMode = 1;
@@ -178,11 +178,9 @@ void StarTrekEngine::handleAwayMissionEvents() {
Common::String animFilename = getCrewmanAnimFilename(0, "walk");
Common::Point mousePos = _gfx->getMousePos();
- // objectWalkToPosition(0, animFilename, _kirkObject->pos.x, _kirkObject->pos.y, mousePos.x, mousePos.y);
+ objectWalkToPosition(0, animFilename, _kirkObject->pos.x, _kirkObject->pos.y, mousePos.x, mousePos.y);
}
break;
- case 1:
- break;
case 2:
break;
case 3:
@@ -232,6 +230,17 @@ Room *StarTrekEngine::getRoom() {
}
void StarTrekEngine::runAwayMissionCycle() {
+ // TODO
+}
+
+/**
+ * Returns true if the given position in the room is solid (not walkable).
+ * Reads from a ".map" file which has a bit for each position in the room, which is true
+ * when that position is solid.
+ */
+bool StarTrekEngine::isPositionSolid(int16 x, int16 y) {
+ _mapFile->seek((y * SCREEN_WIDTH + x) / 8, SEEK_SET);
+ return _mapFile->readByte() & (0x80 >> (x % 8));
}
}
diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h
index 290e5e39f5..f2a9ca68c4 100644
--- a/engines/startrek/awaymission.h
+++ b/engines/startrek/awaymission.h
@@ -28,7 +28,7 @@ struct AwayMission {
int16 mouseX;
int16 mouseY;
byte field1c;
- byte field1d;
+ byte field1d; // Set while beaming in?
bool redshirtDead;
byte mapFileLoaded;
int8 field25[4];
diff --git a/engines/startrek/object.h b/engines/startrek/object.h
index d9b16da875..d1cd8fb649 100644
--- a/engines/startrek/object.h
+++ b/engines/startrek/object.h
@@ -54,21 +54,25 @@ struct Object {
uint16 field72;
uint16 field74;
uint16 field76;
- uint16 iwSrcPosition;
- uint16 iwDestPosition;
- uint16 field7c;
- uint16 field7e;
- uint16 field80;
- uint16 field82;
- uint16 field84;
- uint16 field86;
- uint16 field88;
- uint16 field8a;
- uint16 field8c;
- uint16 field8e;
+ int16 iwSrcPosition;
+ int16 iwDestPosition;
+
+ // Fixed-point position values (16.16) used while walking.
+ uint32 granularPosX;
+ uint32 granularPosY;
+
+ // Fixed-point speed values (16.16).
+ uint32 speedX;
+ uint32 speedY;
+
+ Common::Point dest; // Position object is walking toward
uint16 field90;
byte field92;
- char direction; // Can 'n', 's', 'e', 'w', or 0 for uninitialized?
+
+ // Can 'n', 's', 'e', 'w', or 0 for uninitialized?
+ // Can also be capitalized?
+ char direction;
+
uint16 field94;
uint16 field96;
char animationString[9];
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 346cb91081..9cafd44365 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -100,7 +100,7 @@ Common::Error StarTrekEngine::run() {
_gameMode = -1;
_lastGameMode = -1;
- runGameMode(GAMEMODE_BEAMDOWN);
+ runGameMode(GAMEMODE_AWAYMISSION);
return Common::kNoError;
@@ -381,6 +381,43 @@ int StarTrekEngine::loadObjectAnim(int objectIndex, const Common::String &animNa
return objectIndex;
}
+/**
+ * Tries to make an object walk to a position.
+ * Returns true if successful in initiating the walk.
+ */
+bool StarTrekEngine::objectWalkToPosition(int objectIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY) {
+ debugC(6, "Obj %d: walk from (%d,%d) to (%d,%d)", objectIndex, srcX, srcY, destX, destY);
+
+ Object *object = &_objectList[objectIndex];
+
+ object->field64 = 0;
+ if (isPositionSolid(destX, destY))
+ return false;
+
+ if (object->spriteDrawn)
+ releaseAnim(object);
+ else
+ _gfx->addSprite(&object->sprite);
+
+ object->spriteDrawn = true;
+ object->animType = 1;
+ object->frameToStartNextAnim = _frameIndex + 1;
+ strcpy(object->animationString2, animFile.c_str());
+
+ object->dest.x = destX;
+ object->dest.y = destY;
+ object->field92 = 0;
+ object->field64 = 0;
+
+ object->iwDestPosition = -1;
+ object->iwSrcPosition = -1;
+
+ // TODO: if (directPathExists(srcX, srcY, destX, destY)) {
+
+ chooseObjectDirectionForWalking(object, srcX, srcY, destX, destY);
+ updateObjectPositionWhileWalking(object, (object->granularPosX + 0x8000) >> 16, (object->granularPosY + 0x8000) >> 16);
+}
+
void StarTrekEngine::updateObjectAnimations() {
for (int i = 0; i < MAX_OBJECTS; i++) {
Object *object = &_objectList[i];
@@ -388,7 +425,7 @@ void StarTrekEngine::updateObjectAnimations() {
continue;
switch (object->animType) {
- case 0:
+ case 0: // Not walking?
case 2:
if (_frameIndex >= object->frameToStartNextAnim) {
int nextAnimIndex = 0; // TODO: "chooseNextAnimFrame" function
@@ -439,8 +476,60 @@ void StarTrekEngine::updateObjectAnimations() {
}
}
break;
- case 1: // TODO
- warning("Unimplemented anim type %d", object->animType);
+ case 1: // Walking
+ if (_frameIndex < object->frameToStartNextAnim)
+ break;
+ /*
+ if (i == 0) // TODO: Kirk only
+ sub_22c2d(object->pos.x, object->pos.y);
+ */
+ if (object->field90 != 0) {
+ Sprite *sprite = &object->sprite;
+ int loops;
+ if (getObjectScaleAtPosition((object->granularPosY + 0x8000) >> 16) < 0xa0)
+ loops = 1;
+ else
+ loops = 2;
+ for (int k = 0; k < loops; k++) {
+ if (object->field90 == 0)
+ break;
+ object->field90--;
+ uint32 newX = object->granularPosX + object->speedX;
+ uint32 newY = object->granularPosY + object->speedY;
+ if ((object->field90 & 3) == 0) {
+ sprite->bitmap.reset();
+ updateObjectPositionWhileWalking(object, (newX + 0x8000) >> 16, (newY + 0x8000) >> 16);
+ object->field92++;
+ }
+
+ object->granularPosX = newX;
+ object->granularPosY = newY;
+ object->frameToStartNextAnim = _frameIndex;
+ }
+ }
+ else { // object->field90 == 0
+ if (object->iwSrcPosition == -1) {
+ if (object->field64 != 0) {
+ object->field64 = 0;
+ //addCommand(COMMAND_12, object->field66 & 0xff, 0, 0);
+ }
+
+ object->sprite.bitmap.reset();
+ updateObjectPositionWhileWalking(object, (object->granularPosX + 0x8000) >> 16, (object->granularPosY + 0x8000) >> 16);
+ initStandAnim(i);
+ }
+ else { // object->iwSrcPosition != -1
+ if (object->iwSrcPosition == object->iwDestPosition) {
+ object->animationString2[strlen(object->animationString2) - 1] = '\0';
+ object->iwDestPosition = -1;
+ object->iwSrcPosition = -1;
+ // sub_11677(object->pos.x, object->pos.y, object->dest.x, object->dest.y);
+ }
+ else {
+
+ }
+ }
+ }
break;
default:
error("Invalid anim type.");
@@ -477,7 +566,7 @@ void StarTrekEngine::objectFunc1() {
}
}
-void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, uint16 x, uint16 y, uint16 scale, bool addSprite) {
+void StarTrekEngine::drawObjectToScreen(Object *object, const Common::String &_animName, int16 x, int16 y, uint16 scale, bool addSprite) {
Common::String animFilename = _animName;
if (_animName.hasPrefixIgnoreCase("stnd") /* && word_45d20 == -1 */) // TODO
animFilename += 'j';
@@ -571,6 +660,86 @@ void StarTrekEngine::initStandAnim(int objectIndex) {
object->animType = 0;
}
+void StarTrekEngine::updateObjectPositionWhileWalking(Object *object, int16 x, int16 y) {
+ object->scale = getObjectScaleAtPosition(y);
+ Common::String animName = Common::String::format("%s%02d", object->animationString2, object->field92 & 7);
+ object->sprite.setBitmap(loadAnimationFrame(animName, object->scale));
+
+ memset(object->animationString4, 0, 10);
+ strncpy(object->animationString4, animName.c_str(), 9);
+
+ Sprite *sprite = &object->sprite;
+ sprite->drawPriority = _gfx->getPriValue(0, y);
+ sprite->pos.x = x;
+ sprite->pos.y = y;
+ sprite->bitmapChanged = true;
+
+ object->frameToStartNextAnim = _frameIndex;
+ object->pos.x = x;
+ object->pos.y = y;
+}
+
+/**
+ * Chooses a value for the object's speed and direction, based on a source position and
+ * a destination position it's walking to.
+ */
+void StarTrekEngine::chooseObjectDirectionForWalking(Object *object, int16 srcX, int16 srcY, int16 destX, int16 destY) {
+ object->granularPosX = srcX << 16;
+ object->granularPosY = srcY << 16;
+
+ int16 distX = destX - srcX;
+ int16 distY = destY - srcY;
+ int16 absDistX = abs(distX);
+ int16 absDistY = abs(distY);
+
+ if (absDistX > absDistY) {
+ char d;
+ if (distX > 0)
+ d = 'E';
+ else
+ d = 'W';
+
+ // Append direction to animation string
+ object->animationString2[strlen(object->animationString2) + 1] = '\0';
+ object->animationString2[strlen(object->animationString2)] = d;
+
+ object->direction = d;
+ object->field90 = absDistX;
+
+ if (distX != 0) {
+ if (distX > 0)
+ object->speedX = 1 << 16;
+ else
+ object->speedX = -1 << 16; // 0xffff0000
+
+ object->speedY = (distY << 16) / absDistX;
+ }
+ }
+ else {
+ char d;
+ if (distY > 0)
+ d = 'S';
+ else
+ d = 'N';
+
+ // Append direction to animation string
+ object->animationString2[strlen(object->animationString2) + 1] = '\0';
+ object->animationString2[strlen(object->animationString2)] = d;
+
+ object->direction = d;
+ object->field90 = absDistY;
+
+ if (distY != 0) {
+ if (distY > 0)
+ object->speedY = 1 << 16;
+ else
+ object->speedY = -1 << 16; // 0xffff0000
+
+ object->speedX = (distX << 16) / absDistY;
+ }
+ }
+}
+
SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filename, uint16 scale) {
SharedPtr<Bitmap> bitmapToReturn;
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index 52157f4a0c..68a9d51218 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -99,7 +99,8 @@ struct TrekEvent {
enum Commands {
COMMAND_TICK = 0,
- COMMAND_CLICKED_ON_OBJECT
+ COMMAND_CLICKED_ON_OBJECT = 1,
+ COMMAND_12 = 12
};
struct Command {
@@ -134,6 +135,8 @@ private:
uint16 getObjectScaleAtPosition(int16 y);
void runAwayMissionCycle();
+ bool isPositionSolid(int16 x, int16 y);
+
public:
Room *getRoom();
@@ -153,13 +156,15 @@ public:
// Objects
void initObjects();
int loadObjectAnim(int objectIndex, const Common::String &animName, int16 x, int16 y, uint16 arg8);
- bool objectWalkToPosition(int objectIndex, Common::Point src, Common::Point dest);
+ bool objectWalkToPosition(int objectIndex, const Common::String &animFile, int16 srcX, int16 srcY, int16 destX, int16 destY);
void updateObjectAnimations();
void removeObjectFromScreen(int objectIndex);
void objectFunc1();
- void drawObjectToScreen(Object *object, const Common::String &animName, uint16 field5e, uint16 field60, uint16 arg8, bool addSprite);
+ void drawObjectToScreen(Object *object, const Common::String &animName, int16 x, int16 y, uint16 scale, bool addSprite);
void releaseAnim(Object *object);
void initStandAnim(int objectIndex);
+ void updateObjectPositionWhileWalking(Object *object, int16 x, int16 y);
+ void chooseObjectDirectionForWalking(Object *object, int16 srcX, int16 srcY, int16 destX, int16 destY);
SharedPtr<Bitmap> loadAnimationFrame(const Common::String &filename, uint16 arg2);
Common::String getCrewmanAnimFilename(int objectIndex, const Common::String &basename);