STARTREK: Implement fixed-point decimal class

This commit is contained in:
Matthew Stewart 2018-07-18 23:53:21 -04:00 committed by Eugene Sandulenko
parent a024a3fd45
commit ac9cd1f00a
11 changed files with 417 additions and 111 deletions

View File

@ -105,9 +105,9 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex)
actorFunc1();
initActors();
double num = _room->getVar0c() - _room->getVar0a();
double den = _room->getVar06() - _room->getVar08() + 1;
_playerActorScale = (int32)(num * 256 / den);
Fixed16 num = _room->getMaxScale() - _room->getMinScale();
int16 den = _room->getMaxY() - _room->getMinY() + 1;
_playerActorScale = Fixed32(num) / den;
// TODO: RDF vars 1e/1f and 20/21; relates to BAN files?
@ -446,21 +446,21 @@ void StarTrekEngine::unloadRoom() {
* further up (away) the object is, the smaller it is.
*/
int StarTrekEngine::loadActorAnimWithRoomScaling(int actorIndex, const Common::String &animName, int16 x, int16 y) {
uint16 scale = getActorScaleAtPosition(y);
Fixed16 scale = getActorScaleAtPosition(y);
return loadActorAnim(actorIndex, animName, x, y, scale);
}
uint16 StarTrekEngine::getActorScaleAtPosition(int16 y) {
int16 var06 = _room->getVar06();
int16 var08 = _room->getVar08();
int16 var0a = _room->getVar0a();
Fixed16 StarTrekEngine::getActorScaleAtPosition(int16 y) {
int16 maxY = _room->getMaxY();
int16 minY = _room->getMinY();
Fixed16 minScale = _room->getMinScale();
if (var06 < y)
y = var06;
if (var08 > y)
y = var08;
if (y > maxY)
y = maxY;
if (y < minY)
y = minY;
return ((_playerActorScale * (y - var08)) >> 8) + var0a;
return Fixed16(_playerActorScale * (y - minY)) + minScale;
}
SharedPtr<Room> StarTrekEngine::getRoom() {

View File

@ -23,6 +23,7 @@
#define STARTREK_COMMON_H
#include "common/scummsys.h"
#include "common/textconsole.h"
namespace Common {
struct Rect;
@ -41,12 +42,6 @@ Common::Rect getRectEncompassing(Common::Rect r1, Common::Rect r2);
void serializeRect(Common::Rect rect, Common::Serializer &ser);
// Fixed-point (16.16) number
typedef int32 Fixed32;
// Fixed-point (8.8) number
typedef int16 Fixed16;
}
#endif

152
engines/startrek/fixedint.h Normal file
View File

@ -0,0 +1,152 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef STARTREK_FIXEDINT_H
#define STARTREK_FIXEDINT_H
#include "common/serializer.h"
#include "startrek/common.h"
namespace StarTrek {
/**
* Signed fixed-point number.
*/
template<typename T, uint totalBits, uint decimalBits>
class TFixedInt : Common::Serializable {
const static int max = (1 << (totalBits - decimalBits - 1)) - 1;
const static int min = -max - 1;
T val;
public:
static TFixedInt fromRaw(T raw) {
TFixedInt ret;
ret.val = raw;
return ret;
}
TFixedInt() : val(0) {}
TFixedInt(double d) {
assert(d >= min && d <= max); // FIXME: downgrade this to a warning?
val = (T)(d * (1 << decimalBits));
}
/**
* Constructor from other fixed-point formats.
*/
template<typename T2, uint otherTB, uint otherDB>
TFixedInt<T, totalBits, decimalBits>(const TFixedInt<T2, otherTB, otherDB> &fi) {
int diff = otherDB - decimalBits;
if (otherDB >= decimalBits)
val = fi.raw() >> diff;
else
val = fi.raw() << (-diff);
}
T raw() const {
return val;
}
int16 toInt() const {
return val >> decimalBits;
}
double toDouble() const {
return ((double)val) / (1 << decimalBits);
}
/**
* Multiplication with an int, with the result being an int.
*/
int32 multToInt(int32 i) {
return ((val * i) << (totalBits - decimalBits)) >> totalBits;
}
/**
* Multiplication with an int, with the result being the same type.
*/
TFixedInt operator*(int32 i) const {
return fromRaw(val * i);
}
/**
* Division with an int, with the result being the same type.
*/
TFixedInt operator/(int32 i) const {
return fromRaw(val / i);
}
TFixedInt operator+(const TFixedInt &f) const {
return fromRaw(val + f.val);
}
TFixedInt operator-(const TFixedInt &f) const {
return fromRaw(val - f.val);
}
void operator+=(const TFixedInt &f) {
val += f.val;
}
void operator-=(const TFixedInt &f) {
val -= f.val;
}
bool operator==(double d) const {
return toDouble() == d;
}
bool operator!=(double d) const {
return toDouble() != d;
}
bool operator<(double d) const {
return toDouble() < d;
}
bool operator<=(double d) const {
return toDouble() <= d;
}
void saveLoadWithSerializer(Common::Serializer &ser) {
if (totalBits == 16)
ser.syncAsSint16LE(val);
else if (totalBits == 32)
ser.syncAsSint32LE(val);
else
error("Unsupported bit size for TFixedInt");
}
};
template<typename T, uint totalBits, uint decimalBits>
int32 operator*(const int16 lhs, const TFixedInt<T, totalBits, decimalBits> &rhs) {
return rhs * lhs;
}
// Fixed-point (2.14) number (between -1 and 1)
typedef TFixedInt<int16, 16, 14> Fixed14;
// Fixed-point (8.8) number
typedef TFixedInt<int16, 16, 8> Fixed16;
// Fixed-point (16.16) number
typedef TFixedInt<int32, 32, 16> Fixed32;
}
#endif

View File

@ -24,6 +24,7 @@
#define STARTREK_OBJECT_H
#include "startrek/common.h"
#include "startrek/fixedint.h"
#include "startrek/items.h"
#include "startrek/sprite.h"

View File

@ -210,7 +210,7 @@ void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y,
if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END)
_vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y);
else
_vm->loadActorAnim(actorIndex, anim, x, y, 256);
_vm->loadActorAnim(actorIndex, anim, x, y, 1.0);
if (finishedAnimActionParam != 0) {
actor->triggerActionWhenAnimFinished = true;
@ -231,7 +231,7 @@ void Room::loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y,
if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END)
_vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y);
else
_vm->loadActorAnim(actorIndex, anim, x, y, 256);
_vm->loadActorAnim(actorIndex, anim, x, y, 1.0);
if (funcPtr != nullptr) {
actor->triggerActionWhenAnimFinished = true;

View File

@ -27,6 +27,7 @@
#include "common/ptr.h"
#include "common/str.h"
#include "startrek/fixedint.h"
#include "startrek/startrek.h"
#include "startrek/text.h"
@ -60,11 +61,13 @@ public:
// Helper stuff for RDF access
uint16 readRdfWord(int offset);
// Scale-related stuff (rename these later)
uint16 getVar06() { return readRdfWord(0x06); }
uint16 getVar08() { return readRdfWord(0x08); }
uint16 getVar0a() { return readRdfWord(0x0a); }
uint16 getVar0c() { return readRdfWord(0x0c); }
// Scale-related stuff; at the "min Y" position or below, the crewmembers have
// "minimum" scale; that value rises to the "max scale" value by the time they reach
// the "max Y" value.
uint16 getMaxY() { return readRdfWord(0x06); }
uint16 getMinY() { return readRdfWord(0x08); }
Fixed16 getMinScale() { return Fixed16::fromRaw(readRdfWord(0x0a)); }
Fixed16 getMaxScale() { return Fixed16::fromRaw(readRdfWord(0x0c)); }
// words 0x0e and 0x10 in RDF file are pointers to start and end of event code.
// That code is instead rewritten on a per-room basis.

View File

@ -256,7 +256,7 @@ bool StarTrekEngine::saveOrLoadGameData(Common::SeekableReadStream *in, Common::
a->sprite.saveLoadWithSerializer(ser);
ser.syncBytes((byte *)a->bitmapFilename, 10);
ser.syncAsUint16LE(a->scale);
a->scale.saveLoadWithSerializer(ser);
// Can't save "animFile" (will be reloaded)
ser.syncAsUint16LE(a->numAnimFrames);
ser.syncAsUint16LE(a->animFrame);
@ -274,10 +274,10 @@ bool StarTrekEngine::saveOrLoadGameData(Common::SeekableReadStream *in, Common::
ser.syncAsUint16LE(a->field76);
ser.syncAsSint16LE(a->iwSrcPosition);
ser.syncAsSint16LE(a->iwDestPosition);
ser.syncAsSint32LE(a->granularPosX);
ser.syncAsSint32LE(a->granularPosY);
ser.syncAsSint32LE(a->speedX);
ser.syncAsSint32LE(a->speedY);
a->granularPosX.saveLoadWithSerializer(ser);
a->granularPosY.saveLoadWithSerializer(ser);
a->speedX.saveLoadWithSerializer(ser);
a->speedY.saveLoadWithSerializer(ser);
ser.syncAsSint16LE(a->dest.x);
ser.syncAsSint16LE(a->dest.y);
ser.syncAsUint16LE(a->field90);

View File

@ -26,8 +26,8 @@
namespace StarTrek {
void StarTrekEngine::initStarfieldPosition() {
memset(&_starfieldPosition, 0, sizeof(_starfieldPosition));
// TODO: matrix initialization
_starfieldPosition = Point3(0, 0, 0);
_someMatrix = initMatrix();
}
void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8) {
@ -45,13 +45,35 @@ void StarTrekEngine::initStarfield(int16 x, int16 y, int16 width, int16 height,
_starfieldPointDivisor = 150;
}
void StarTrekEngine::addR3(R3 *r3) {
for (int i = 0; i < NUM_SPACE_OBJECTS; i++) {
if (_r3List[i] == nullptr) {
_r3List[i] = r3;
return;
}
}
error("addR3: out of shapes.");
}
void StarTrekEngine::delR3(R3 *r3) {
for (int i = 0; i < NUM_SPACE_OBJECTS; i++) {
if (_r3List[i] == r3) {
_r3List[i] = nullptr;
r3->field1e = 0;
return;
}
}
error("delR3: shape not found.");
}
void StarTrekEngine::clearStarfieldPixels() {
_gfx->fillBackgroundRect(_starfieldRect, 0);
}
void StarTrekEngine::drawStarfield() {
// TODO: make these class variables
Point3W starPositionWeightings[] = {{0x4000, 0, 0}, {0, 0x4000, 0}, {0, 0, 0x4000}};
float flt_50898 = 50.0; // ?
int16 var28 = ((_starfieldXVar2 * 3) >> 1);
@ -72,12 +94,12 @@ void StarTrekEngine::drawStarfield() {
int16 var4 = getRandomWord() / var28 - xvar;
int16 var6 = getRandomWord() / var2a - yvar;
Point3 point = constructPoint3ForStarfield(var4, var6, var8);
star->pos = applyPointWeightings(starPositionWeightings, point) + _starfieldPosition;
star->pos = matrixMult(_starPositionMatrix, point) + _starfieldPosition;
star->active = true;
}
Point3 p = star->pos - _starfieldPosition;
Point3 point2 = applyPointWeightings2(p, starPositionWeightings);
Point3 point2 = matrixMult(p, _starPositionMatrix);
if (point2.z > flt_50898 && point2.z < 0x3fff
&& abs(point2.x) < point2.z && abs(point2.y) < point2.z) {
@ -111,7 +133,7 @@ void StarTrekEngine::drawStarfield() {
void StarTrekEngine::updateStarfieldAndShips(bool arg0) {
_starfieldSprite.bitmapChanged = true;
// sub_24b74(...);
_starPositionMatrix = _someMatrix.invert();
clearStarfieldPixels();
drawStarfield();
@ -127,28 +149,32 @@ Point3 StarTrekEngine::constructPoint3ForStarfield(int16 x, int16 y, int16 z) {
return point;
}
Point3 StarTrekEngine::applyPointWeightings(Point3W *weight, const Point3 &point) {
Point3 StarTrekEngine::matrixMult(const Matrix &weight, const Point3 &point) {
int32 ret[3];
for (int i = 0; i < 3; i++) {
ret[i] = weight[i].x * (point.x & 0xffff) + weight[i].y * (point.y & 0xffff) + weight[i].z * (point.z & 0xffff);
ret[i] <<= 2;
ret[i] = weight[i][0].multToInt(point.x & 0xffff) + weight[i][1].multToInt(point.y & 0xffff) + weight[i][2].multToInt(point.z & 0xffff);
}
Point3 p;
p.x = ret[0] >> 16;
p.y = ret[1] >> 16;
p.z = ret[2] >> 16;
p.x = ret[0];
p.y = ret[1];
p.z = ret[2];
return p;
}
Point3 StarTrekEngine::applyPointWeightings2(const Point3 &point, Point3W *weight) {
Point3 StarTrekEngine::matrixMult(const Point3 &point, const Matrix &weight) {
Point3 p = Point3();
p.x = (weight[0].x * (point.x & 0xffff) + weight[1].x * (point.y & 0xffff) + weight[2].x * (point.z & 0xffff)) << 2;
p.y = (weight[0].y * (point.x & 0xffff) + weight[1].y * (point.y & 0xffff) + weight[2].y * (point.z & 0xffff)) << 2;
p.z = (weight[0].z * (point.x & 0xffff) + weight[1].z * (point.y & 0xffff) + weight[2].z * (point.z & 0xffff)) << 2;
p.x >>= 16;
p.y >>= 16;
p.z >>= 16;
p.x = (weight[0][0].multToInt(point.x & 0xffff) + weight[1][0].multToInt(point.y & 0xffff) + weight[2][0].multToInt(point.z & 0xffff));
p.y = (weight[0][1].multToInt(point.x & 0xffff) + weight[1][1].multToInt(point.y & 0xffff) + weight[2][1].multToInt(point.z & 0xffff));
p.z = (weight[0][2].multToInt(point.x & 0xffff) + weight[1][2].multToInt(point.y & 0xffff) + weight[2][2].multToInt(point.z & 0xffff));
return p;
}
Matrix StarTrekEngine::initMatrix() {
Matrix mat;
mat[0][0] = 1;
mat[1][1] = 1;
mat[2][2] = 1;
return mat;
}
}

View File

@ -1,32 +1,113 @@
// Pseudo-3D structs
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
struct Point3 {
int32 x;
int32 y;
int32 z;
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
Point3 operator+(const Point3 &p) const {
Point3 p2;
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef STARTREK_SPACE_H
#define STARTREK_SPACE_H
#include "fixedint.h"
namespace StarTrek {
class FileStream;
template<typename T>
struct TPoint {
T x;
T y;
T z;
TPoint() : x(0), y(0), z(0) {}
TPoint(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {}
TPoint<T> operator+(const TPoint<T> &p) const {
TPoint<T> p2;
p2.x = x + p.x;
p2.y = y + p.y;
p2.z = z + p.z;
return p2;
}
Point3 operator-(const Point3 &p) const {
Point3 p2;
TPoint<T> operator-(const TPoint<T> &p) const {
TPoint<T> p2;
p2.x = x - p.x;
p2.y = y - p.y;
p2.z = z - p.z;
return p2;
}
T &operator[](int i) {
if (i == 0)
return x;
else if (i == 1)
return y;
else if (i == 2)
return z;
assert(false);
}
T operator[](int i) const {
if (i == 0)
return x;
else if (i == 1)
return y;
else if (i == 2)
return z;
assert(false);
}
};
struct Point3W {
int16 x;
int16 y;
int16 z;
typedef TPoint<int32> Point3;
typedef TPoint<Fixed14> Point3W;
template<typename T>
struct TMatrix {
private:
T m[3];
public:
TMatrix() {}
TMatrix(const TMatrix<T> &mat) {
m[0] = mat.m[0];
m[1] = mat.m[1];
m[2] = mat.m[2];
}
T &operator[](int i) {
return m[i];
};
T operator[](int i) const {
return m[i];
};
TMatrix<T> invert() {
TMatrix<T> ret;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
ret[i][j] = m[j][i];
}
}
return ret;
}
};
typedef TMatrix<Point3W> Matrix;
struct Star {
bool active;
Point3 pos;
@ -37,6 +118,10 @@ struct Star {
struct R3 {
Point3 pos; // 0x0
int16 field1e; // 0x1e
int16 field20; // 0x20
int16 field22; // 0x22
int16 field24; // 0x24
SharedPtr<FileStream> shpFile; // 0x68
};
// Maximum number of stars visible at once in the starfields
@ -44,3 +129,7 @@ struct R3 {
// Maximum number of R3 objects in space at once
#define NUM_SPACE_OBJECTS 0x30
}
#endif

View File

@ -217,6 +217,10 @@ void StarTrekEngine::playIntro() {
_starfieldSprite.bitmap = fakeStarfieldBitmap;
initStarfieldSprite(&_starfieldSprite, fakeStarfieldBitmap, _starfieldRect);
//delR3(&_enterpriseR3); // TODO: uncomment
R3 planetR3 = R3();
// TODO: remainder of starfield initialization
_gfx->clearScreenAndPriBuffer();
@ -312,8 +316,26 @@ void StarTrekEngine::playIntro() {
loadSubtitleSprite(1, &subtitleSprite);
break;
case 42:
case 42: // Enterprise moves toward camera
loadSubtitleSprite(-1, &subtitleSprite);
addR3(&_enterpriseR3);
_enterpriseR3.field1e = 2;
initIntroR3ObjectToMove(&_enterpriseR3, 330, 5000, 0, 0, 18);
break;
case 60: // Enterprise moves away from camera
initIntroR3ObjectToMove(&_enterpriseR3, 0, 0, 30, 5000, 6);
break;
case 66: // Cut to scene with planet
loadSubtitleSprite(2, &subtitleSprite);
planetR3.field22 = 2000;
planetR3.field24 = 10000 / _starfieldPointDivisor;
planetR3.shpFile = loadFile("planet.shp");
initIntroR3ObjectToMove(&planetR3, 6, 10000, 6, 10000, 0);
addR3(&planetR3);
initIntroR3ObjectToMove(&_enterpriseR3, -15, 250, 15, 500, 18);
starfieldZoomSpeed = 0;
break;
case 378:
@ -344,6 +366,11 @@ void StarTrekEngine::playIntro() {
// TODO: the rest
}
void StarTrekEngine::initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks) {
srcAngle = (srcAngle << 9) / 180;
destAngle = (destAngle << 9) / 180;
}
void StarTrekEngine::loadSubtitleSprite(int index, Sprite *sprite) {
if (_showSubtitles) {
if (index == -1)
@ -379,25 +406,25 @@ void StarTrekEngine::runTransportSequence(const Common::String &name) {
Common::String filename = getCrewmanAnimFilename(i, name);
int x = crewmanTransportPositions[i][0];
int y = crewmanTransportPositions[i][1];
loadActorAnim(i, filename, x, y, 256);
loadActorAnim(i, filename, x, y, 1.0);
_actorList[i].animationString[0] = '\0';
}
if (_missionToLoad.equalsIgnoreCase("feather") && name[4] == 'b') {
loadActorAnim(9, "qteleb", 0x61, 0x79, 0x100);
loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0);
}
else if (_missionToLoad.equalsIgnoreCase("trial")) {
if (name[4] == 'd') {
loadActorAnim(9, "qteled", 0x61, 0x79, 0x100);
loadActorAnim(9, "qteled", 0x61, 0x79, 1.0);
}
/* TODO
else if (word_51156 >= 3) {
loadActorAnim(9, "qteleb", 0x61, 0x79, 0x100);
loadActorAnim(9, "qteleb", 0x61, 0x79, 1.0);
}
*/
}
loadActorAnim(8, "transc", 0, 0, 0x100);
loadActorAnim(8, "transc", 0, 0, 1.0);
// TODO: redraw mouse and sprite_52c4e?
@ -570,7 +597,7 @@ bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &a
if (directPathExists(srcX, srcY, destX, destY)) {
chooseActorDirectionForWalking(actor, srcX, srcY, destX, destY);
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16);
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
return true;
}
else {
@ -590,7 +617,7 @@ bool StarTrekEngine::actorWalkToPosition(int actorIndex, const Common::String &a
else {
Common::Point iwSrc = _iwFile->_keyPositions[actor->iwSrcPosition];
chooseActorDirectionForWalking(actor, srcX, srcY, iwSrc.x, iwSrc.y);
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16);
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
return true;
}
}
@ -660,7 +687,7 @@ void StarTrekEngine::updateActorAnimations() {
if (actor->field90 != 0) {
Sprite *sprite = &actor->sprite;
int loops;
if (getActorScaleAtPosition((actor->granularPosY + 0x8000) >> 16) < 0xa0)
if (getActorScaleAtPosition((actor->granularPosY + 0.5).toInt()) < 0.625)
loops = 1;
else
loops = 2;
@ -668,11 +695,11 @@ void StarTrekEngine::updateActorAnimations() {
if (actor->field90 == 0)
break;
actor->field90--;
uint32 newX = actor->granularPosX + actor->speedX;
uint32 newY = actor->granularPosY + actor->speedY;
Fixed32 newX = actor->granularPosX + actor->speedX;
Fixed32 newY = actor->granularPosY + actor->speedY;
if ((actor->field90 & 3) == 0) {
sprite->bitmap.reset();
updateActorPositionWhileWalking(actor, (newX + 0x8000) >> 16, (newY + 0x8000) >> 16);
updateActorPositionWhileWalking(actor, (newX + 0.5).toInt(), (newY + 0.5).toInt());
actor->field92++;
}
@ -689,7 +716,7 @@ void StarTrekEngine::updateActorAnimations() {
}
actor->sprite.bitmap.reset();
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0x8000) >> 16, (actor->granularPosY + 0x8000) >> 16);
updateActorPositionWhileWalking(actor, (actor->granularPosX + 0.5).toInt(), (actor->granularPosY + 0.5).toInt());
initStandAnim(i);
}
else { // actor->iwSrcPosition != -1
@ -834,7 +861,7 @@ void StarTrekEngine::initStandAnim(int actorIndex) {
else // Default to facing south
animName = Common::String(actor->animationString) + 's';
uint16 scale = getActorScaleAtPosition(actor->pos.y);
Fixed16 scale = getActorScaleAtPosition(actor->pos.y);
loadActorAnim(actorIndex, animName, actor->pos.x, actor->pos.y, scale);
actor->animType = 0;
}
@ -863,8 +890,8 @@ void StarTrekEngine::updateActorPositionWhileWalking(Actor *actor, int16 x, int1
* a destination position it's walking to.
*/
void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, int16 srcY, int16 destX, int16 destY) {
actor->granularPosX = srcX << 16;
actor->granularPosY = srcY << 16;
actor->granularPosX = srcX;
actor->granularPosY = srcY;
int16 distX = destX - srcX;
int16 distY = destY - srcY;
@ -887,11 +914,11 @@ void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, in
if (distX != 0) {
if (distX > 0)
actor->speedX = 1 << 16;
actor->speedX = 1.0;
else
actor->speedX = -1 << 16; // 0xffff0000
actor->speedX = -1.0;
actor->speedY = (distY << 16) / absDistX;
actor->speedY = Fixed32(distY) / absDistX;
}
}
else {
@ -910,11 +937,11 @@ void StarTrekEngine::chooseActorDirectionForWalking(Actor *actor, int16 srcX, in
if (distY != 0) {
if (distY > 0)
actor->speedY = 1 << 16;
actor->speedY = 1.0;
else
actor->speedY = -1 << 16; // 0xffff0000
actor->speedY = -1.0;
actor->speedX = (distX << 16) / absDistY;
actor->speedX = Fixed32(distX) / absDistY;
}
}
}
@ -939,12 +966,12 @@ bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16
if (distCounter == 0)
return true;
speedY = (distY << 16) / absDistX;
speedY = Fixed32(distY) / absDistX;
if (distX > 0)
speedX = 1 << 16;
speedX = 1.0;
else
speedX = -1 << 16;
speedX = -1.0;
}
else { // absDistX <= absDistY
distCounter = absDistY;
@ -952,25 +979,25 @@ bool StarTrekEngine::directPathExists(int16 srcX, int16 srcY, int16 destX, int16
if (distCounter == 0)
return true;
speedX = (distX << 16) / absDistY;
speedX = Fixed32(distX) / absDistY;
if (distY > 0)
speedY = 1 << 16;
speedY = 1.0;
else
speedY = -1 << 16;
speedY = -1.0;
}
Fixed32 fixedX = srcX << 16;
Fixed32 fixedY = srcY << 16;
Fixed32 fixedX = srcX;
Fixed32 fixedY = srcY;
if (isPositionSolid((fixedX + 0x8000) >> 16, (fixedY + 0x8000) >> 16))
if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
return false;
while (distCounter-- > 0) {
fixedX += speedX;
fixedY += speedY;
if (isPositionSolid((fixedX + 0x8000) >> 16, (fixedY + 0x8000) >> 16))
if (isPositionSolid((fixedX + 0.5).toInt(), (fixedY + 0.5).toInt()))
return false;
}
@ -1119,7 +1146,7 @@ SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filen
bitmapToReturn = _gfx->loadBitmap(filename);
}
if (scale != 256) {
if (scale != 1.0) {
bitmapToReturn = scaleBitmap(bitmapToReturn, scale);
}
@ -1454,7 +1481,7 @@ void StarTrekEngine::updateCrewmanGetupTimers() {
}
else {
const char *dirs = "nsew";
uint16 scale = getActorScaleAtPosition(actor->sprite.pos.y);
Fixed16 scale = getActorScaleAtPosition(actor->sprite.pos.y);
d = dirs[dir];
int16 xOffset = 0, yOffset = 0;
@ -1466,8 +1493,8 @@ void StarTrekEngine::updateCrewmanGetupTimers() {
xOffset = -35;
yOffset = -12;
}
actor->sprite.pos.x += (scale * xOffset) >> 8;
actor->sprite.pos.y += (scale * yOffset) >> 8;
actor->sprite.pos.x += scale.multToInt(xOffset);
actor->sprite.pos.y += scale.multToInt(yOffset);
}
anim += (char)d;
@ -1652,12 +1679,9 @@ void StarTrekEngine::initStarfieldSprite(Sprite *sprite, SharedPtr<Bitmap> bitma
sprite->drawMode = 1;
}
/**
* A scale of 256 is the baseline.
*/
SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed16 scale) {
int scaledWidth = (bitmap->width * scale) >> 8;
int scaledHeight = (bitmap->height * scale) >> 8;
int scaledWidth = scale.multToInt(bitmap->width);
int scaledHeight = scale.multToInt(bitmap->height);
int origWidth = bitmap->width;
int origHeight = bitmap->height;
@ -1667,8 +1691,8 @@ SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed16
scaledHeight = 1;
SharedPtr<Bitmap> scaledBitmap(new Bitmap(scaledWidth, scaledHeight));
scaledBitmap->xoffset = (bitmap->xoffset * scale) >> 8;
scaledBitmap->yoffset = (bitmap->yoffset * scale) >> 8;
scaledBitmap->xoffset = scale.multToInt(bitmap->xoffset);
scaledBitmap->yoffset = scale.multToInt(bitmap->yoffset);
// sub_344a5(scaledWidth, origWidth);
@ -1678,7 +1702,7 @@ SharedPtr<Bitmap> StarTrekEngine::scaleBitmap(SharedPtr<Bitmap> bitmap, Fixed16
byte *src = bitmap->pixels;
byte *dest = scaledBitmap->pixels;
if (scale <= 256) {
if (scale <= 1.0) {
int16 var2e = 0;
uint16 var30 = scaledHeight << 1;
uint16 var32 = (scaledHeight - origHeight) << 1;

View File

@ -222,7 +222,7 @@ public:
void handleAwayMissionEvents();
void unloadRoom();
int loadActorAnimWithRoomScaling(int actorIndex, const Common::String &animName, int16 x, int16 y);
uint16 getActorScaleAtPosition(int16 y);
Fixed16 getActorScaleAtPosition(int16 y);
void addAction(const Action &action);
void addAction(byte type, byte b1, byte b2, byte b3);
bool checkItemInteractionExists(int action, int activeItem, int passiveItem, int16 arg6);
@ -240,18 +240,30 @@ public:
private:
// Intro
void playIntro();
/**
* Initializes an object to spawn at one position and move toward another position.
* @param ticks The number of ticks it should take for the object to reach the destination
*/
void initIntroR3ObjectToMove(R3 *r3, int16 srcAngle, int16 srcDepth, int16 destAngle, int16 destDepth, int16 ticks);
void loadSubtitleSprite(int index, Sprite *sprite);
// Space, pseudo-3D (space.cpp)
void initStarfieldPosition();
void initStarfield(int16 x, int16 y, int16 width, int16 height, int16 arg8);
void addR3(R3 *r3);
void delR3(R3 *r3);
void clearStarfieldPixels();
void drawStarfield();
void updateStarfieldAndShips(bool arg0);
Point3 constructPoint3ForStarfield(int16 x, int16 y, int16 z);
Point3 applyPointWeightings(Point3W *weight, const Point3 &point);
Point3 applyPointWeightings2(const Point3 &point, Point3W *weight);
Point3 matrixMult(const Matrix &weight, const Point3 &point);
Point3 matrixMult(const Point3 &point, const Matrix &weight);
/**
* Creates something like an "identity" matrix? (Value 0x4000 along the diagonal)
*/
Matrix initMatrix();
// Transporter room
void runTransportSequence(const Common::String &name);
@ -447,7 +459,7 @@ public:
Common::String _screenName; // _screenName = _missionName + _roomIndex
Common::String _mapFilename; // Similar to _screenName, but used for .map files?
SharedPtr<FileStream> _mapFile;
int32 _playerActorScale;
Fixed32 _playerActorScale;
Common::String _txtFilename;
Common::String _loadedText; // TODO: might be OK to delete this
@ -519,6 +531,10 @@ public:
int16 _starfieldXVar1, _starfieldYVar1;
int16 _starfieldXVar2, _starfieldYVar2;
Common::Rect _starfieldRect;
R3 _enterpriseR3;
R3 *_r3List[NUM_SPACE_OBJECTS];
Matrix _starPositionMatrix;
Matrix _someMatrix;
Graphics *_gfx;
Sound *_sound;