STARTREK: Basic walking

This commit is contained in:
Matthew Stewart 2018-05-14 13:26:47 -04:00 committed by Eugene Sandulenko
parent 0187c795d5
commit 65d24b0451
5 changed files with 215 additions and 28 deletions

View File

@ -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));
}
}

View File

@ -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];

View File

@ -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];

View File

@ -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;

View File

@ -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);