Preliminary implementation of lots of code related to player movement

svn-id: r50882
This commit is contained in:
Paul Gilbert 2010-07-14 11:55:15 +00:00
parent f456b7cfa2
commit f796fd6cf3
5 changed files with 383 additions and 12 deletions

View File

@ -35,20 +35,27 @@ const int MadsPlayer::_directionListIndexes[32] = {
MadsPlayer::MadsPlayer() {
_playerPos = Common::Point(160, 78);
_direction = 0;
_newDirection = 0;
_ticksAmount = 3;
_forceRefresh = true;
_stepEnabled = true;
_ticksAmount = 3;
_priorTimer = 0;
_visible = true;
_priorVisible = false;
_visible3 = false;
_yScale = 0;
_moving = false;
_spriteListStart = 0;
_spriteListIdx = 0;
//TODO:unknown vars
_special = 0;
_next = 0;
_unk4 = false;
_spritesChanged = true;
_direction = 0;
_newDirection = 0;
_priorTimer = 0;
_priorVisible = false;
_visible3 = false;
_spriteListIdx = 0;
_currentScale = 0;
strcpy(_spritesPrefix, "");
for (int idx = 0; idx < 8; ++idx)
@ -59,6 +66,8 @@ MadsPlayer::MadsPlayer() {
_frameCount = 0;
_frameListIndex = 0;
_actionIndex = 0;
_routeCount = 0;
resetActionList();
}
@ -168,7 +177,7 @@ void MadsPlayer::update() {
_madsVm->scene()->_spriteSlots[slotIndex] = slot;
}
// TODO: Meaning of word_844c0 block
// TODO: Meaning of _v844c0 block
}
}
@ -325,6 +334,34 @@ void MadsPlayer::nextFrame() {
}
}
void MadsPlayer::setDest(int destX, int destY, int facing) {
resetActionList();
setTicksAmount();
_moving = true;
_destFacing = facing;
_madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 2,
_playerPos, _madsVm->scene()->_depthSurface);
_madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 1,
Common::Point(destX, destY), _madsVm->scene()->_depthSurface);
bool v = _madsVm->scene()->getDepthHighBit(Common::Point(destX, destY));
setupRoute(v);
_next = 0;
if (_routeCount > 0) {
Common::Point srcPos = _playerPos;
for (int routeCtr = _routeCount - 1; (routeCtr >= 0) && (_next == 0); --routeCtr) {
int idx = _routeIndexes[routeCtr];
const Common::Point &pt = _madsVm->scene()->getSceneResources()._nodes[idx].pt;
_next = scanPath(_madsVm->scene()->_depthSurface, srcPos, pt);
srcPos = pt;
}
}
}
int MadsPlayer::getScale(int yp) {
MadsSceneResources &r = _madsVm->scene()->getSceneResources();
@ -411,7 +448,98 @@ void MadsPlayer::idle() {
}
void MadsPlayer::move() {
// TODO: Handle player movement
bool routeFlag = false;
if (_moving) {
int idx = _routeCount;
while (!_v844C0 && (_destPos.x == _playerPos.x) && (_destPos.y == _playerPos.y)) {
if (idx != 0) {
--idx;
SceneNode &node = _madsVm->scene()->getSceneResources()._nodes[_routeIndexes[idx]];
_destPos = node.pt;
routeFlag = true;
} else if (_v844BE == idx) {
// End of walking path
_routeCount = 0;
_moving = false;
turnToDestFacing();
routeFlag = true;
idx = _routeCount;
} else {
_v844C0 = _v844BE;
_v844BC = true;
_v844BE = 0;
_stepEnabled = true;
routeFlag = false;
}
if (!_moving)
break;
}
_routeCount = idx;
}
if (routeFlag && _moving)
startMovement();
if (_newDirection != _direction)
dirChanged();
else if (!_moving)
updateFrame();
int var1 = _unk1;
if (_unk4 && (_hypotenuse > 0)) {
int v1 = -(_currentScale - 100) * (_posDiff.x - 1) / _hypotenuse + _currentScale;
var1 = MAX(1, 10000 / (v1 * _currentScale * var1));
}
if (!_moving || (_direction != _newDirection))
return;
Common::Point newPos = _playerPos;
if (_v8452E < var1) {
do {
if (_v8452C < _posDiff.x)
_v8452C += _posDiff.y;
if (_v8452C >= _posDiff.x) {
if ((_posChange.y <= 0) || (_v844C0 != 0))
newPos.y += _yDirection;
--_posChange.y;
_v8452C -= _posDiff.x;
}
if (_v8452C < _posDiff.x) {
if ((_posChange.x <= 0) || (_v844C0 != 0))
newPos.x += _xDirection;
--_posChange.x;
}
if ((_v844BC == 0) && (_v844C0 == 0) && (_v844BE == 0)) {
routeFlag = _madsVm->scene()->getDepthHighBit(newPos);
if (_special == 0)
_special = _madsVm->scene()->getDepthHighBits(newPos);
}
_v8452E += _v84530;
} while ((_v8452E < var1) && !routeFlag && ((_posChange.x > 0) || (_posChange.y > 0)));
}
if (routeFlag)
moveComplete();
else {
if (!_v844C0) {
// If the move is complete, make sure the position is exactly on the given destination
if (_posChange.x == 0)
newPos.x = _destPos.x;
if (_posChange.y == 0)
newPos.y = _destPos.y;
}
_playerPos = newPos;
}
}
void MadsPlayer::dirChanged() {
@ -451,4 +579,175 @@ void MadsPlayer::dirChanged() {
_priorTimer += 1;
}
void MadsPlayer::moveComplete() {
reset();
//todo: Unknown flag
}
void MadsPlayer::reset() {
_destPos = _playerPos;
_destFacing = 5;
_newDirection = _direction;
_moving = false;
_v844BC = false;
_v844C0 = false;
_v844BE = 0;
_next = 0;
_routeCount = 0;
}
/**
* Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first
* pixel high nibble encountered with a non-zero value
*/
int MadsPlayer::scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos) {
// For compressed depth surfaces, always return 0
if (_madsVm->scene()->getSceneResources()._depthStyle != 2)
return 0;
int yDiff = destPos.y - srcPos.y;
int yAmount = MADS_SURFACE_WIDTH;
if (yDiff < 0) {
yDiff = -yDiff;
yAmount = -yAmount;
}
int xDiff = destPos.x - srcPos.y;
int xDirection = 1;
int xAmount = 0;
if (xDiff < 0) {
xDiff = -xDiff;
xDirection = -xDirection;
xAmount = MIN(yDiff, xDiff);
}
++xDiff;
++yDiff;
const byte *srcP = depthSurface->getBasePtr(srcPos.x, srcPos.y);
int index = xAmount;
// Outer horizontal movement loop
for (int yIndex = 0; yIndex < yDiff; ++yIndex) {
index += yDiff;
int v = (*srcP && 0x7F) >> 4;
if (v)
return v;
// Inner loop for handling vertical movement
while (index >= xDiff) {
index -= xDiff;
int v = (*srcP && 0x7F) >> 4;
if (v)
return v;
srcP += yAmount;
}
srcP += xDirection;
}
return 0;
}
/**
* Starts a player moving to a given destination
*/
void MadsPlayer::startMovement() {
int xDiff = _destPos.x - _playerPos.x;
int yDiff = _destPos.y - _playerPos.y;
int srcScale = getScale(_playerPos.y);
int destScale = getScale(_destPos.y);
// Sets the X direction
if (xDiff > 0)
_xDirection = 1;
else if (xDiff < 0)
_xDirection = -1;
else
_xDirection = 0;
// Sets the Y direction
if (yDiff > 0)
_yDirection = 1;
else if (yDiff < 0)
_yDirection = -1;
else
_yDirection = 0;
xDiff = ABS(xDiff);
yDiff = ABS(yDiff);
int scaleDiff = ABS(srcScale - destScale);
int xAmt100 = xDiff * 100;
int yAmt100 = yDiff * 100;
int xAmt33 = xDiff * 33;
int scaleAmount = (_unk4 ? scaleDiff * 3 : 0) + 100 * yDiff / 100;
int scaleAmount100 = scaleAmount * 100;
// Figure out direction that will need to be moved in
int majorDir;
if (xDiff == 0)
majorDir = 1;
else if (yDiff == 0)
majorDir = 3;
else {
if ((scaleAmount >= xDiff) && ((xAmt33 / scaleAmount) >= 141))
majorDir = 3;
else if (yDiff <= xDiff)
majorDir = 2;
else if ((scaleAmount100 / xDiff) >= 141)
majorDir = 1;
else
majorDir = 2;
}
switch (majorDir) {
case 1:
_newDirection = (_yDirection <= 0) ? 8 : 2;
break;
case 2: {
_newDirection = ((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0);
break;
}
case 3:
_newDirection = (_xDirection <= 0) ? 4 : 6;
break;
default:
break;
}
_hypotenuse = SqrtF16(xAmt100 * xAmt100 + yAmt100 * yAmt100);
_posDiff.x = xDiff + 1;
_posDiff.y = yDiff + 1;
_posChange.x = xDiff;
_posChange.y = yDiff;
scaleAmount = MAX(xDiff, yDiff);
_v84530 = (scaleAmount == 0) ? 0 : _hypotenuse / scaleAmount;
if (_playerPos.x > _destPos.x)
_v8452C = MAX(_posChange.x, _posChange.y);
else
_v8452C = 0;
_hypotenuse /= 100;
_v8452E = -_v84530;
}
void MadsPlayer::turnToDestFacing() {
if (_destFacing != 5)
_newDirection = _destFacing;
}
void MadsPlayer::setupRoute(bool bitFlag) {
// TODO: Properly Implement route setup
_routeIndexes[0] = _madsVm->scene()->getSceneResources()._nodes.size() - 1;
_routeCount = 1;
}
} // End of namespace M4

View File

@ -31,6 +31,7 @@
namespace M4 {
#define PLAYER_SEQ_INDEX -2
#define MAX_ROUTE_NODES 22
class MadsPlayer {
private:
@ -42,12 +43,18 @@ private:
void idle();
void move();
void dirChanged();
void reset();
int scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos);
void startMovement();
public:
char _spritesPrefix[16];
int _spriteSetCount;
bool _spriteSetsPresent[8];
Common::Point _playerPos;
Common::Point _destPos;
Common::Point _posChange;
Common::Point _posDiff;
int _hypotenuse;
uint32 _priorTimer;
uint _ticksAmount;
int16 _direction, _newDirection;
@ -70,6 +77,21 @@ public:
int _actionList2[12];
int _unk2;
int _unk3;
int _xDirection, _yDirection;
int _destFacing;
int _special;
int _next;
int _routeCount;
int _routeOffset;
int _tempRoute[MAX_ROUTE_NODES];
int _routeIndexes[MAX_ROUTE_NODES];
bool _unk4;
bool _v844BC;
int _v844BE;
bool _v844C0;
int _v8452E;
int _v8452C;
int _v84530;
static const int _directionListIndexes[32];
public:
@ -81,6 +103,10 @@ public:
void setupFrame();
void step();
void nextFrame();
void setDest(int destX, int destY, int facing);
void turnToDestFacing();
void setupRoute(bool bitFlag);
void moveComplete();
};
} // End of namespace M4

View File

@ -48,6 +48,17 @@ static const int SCROLLER_DELAY = 200;
//--------------------------------------------------------------------------
void SceneNode::load(Common::SeekableReadStream *stream) {
// Get the next data block
uint8 obj[0x30];
stream->read(obj, 0x30);
pt.x = READ_LE_UINT16(&obj[0]);
pt.y = READ_LE_UINT16(&obj[2]);
}
//--------------------------------------------------------------------------
MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResources), MadsView(this) {
_vm = vm;
_activeAnimation = NULL;
@ -265,6 +276,10 @@ void MadsScene::leftClick(int x, int y) {
statusText[0] = toupper(statusText[0]); // capitalize first letter
setStatusText(statusText);
}
// **DEBUG** - being used for movement testing
_madsVm->_player.moveComplete();
_madsVm->_player.setDest(x, y, 2);
}
void MadsScene::rightClick(int x, int y) {
@ -503,6 +518,22 @@ void MadsScene::loadAnimation(const Common::String &animName, int abortTimers) {
_activeAnimation = anim;
}
bool MadsScene::getDepthHighBit(const Common::Point &pt) {
const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
if (_sceneResources._depthStyle == 2)
return ((*p << 4) & 0x80) != 0;
return (*p & 0x80) != 0;
}
bool MadsScene::getDepthHighBits(const Common::Point &pt) {
if (_sceneResources._depthStyle == 2)
return 0;
const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
return (*p & 0x70) >> 4;
}
/*--------------------------------------------------------------------------*/
MadsAction::MadsAction() {
@ -733,9 +764,9 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
// Load in any scene objects
for (int i = 0; i < objectCount; ++i) {
MadsObject rec;
SceneNode rec;
rec.load(stream);
_objects.push_back(rec);
_nodes.push_back(rec);
}
for (int i = 0; i < 20 - objectCount; ++i)
stream->skip(48);
@ -810,6 +841,9 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
delete depthSurface;
}
void MadsSceneResources::setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface) {
// TODO
}
/*--------------------------------------------------------------------------*/

View File

@ -37,6 +37,13 @@ class MadsInterfaceView;
#define DEPTH_BANDS_SIZE 15
class SceneNode {
public:
Common::Point pt;
void load(Common::SeekableReadStream *stream);
};
class MadsSceneResources: public SceneResources {
public:
int _sceneId;
@ -44,7 +51,7 @@ public:
int _depthStyle;
int _width;
int _height;
Common::Array<MadsObject> _objects;
Common::Array<SceneNode> _nodes;
Common::Array<Common::String> _setNames;
int _yBandsStart, _yBandsEnd;
int _maxScale, _minScale;
@ -55,6 +62,7 @@ public:
void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface);
int bandsRange() const { return _yBandsEnd - _yBandsStart; }
int scaleRange() const { return _maxScale - _minScale; }
void setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface);
};
enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
@ -138,6 +146,8 @@ public:
MadsSceneResources &getSceneResources() { return _sceneResources; }
MadsAction &getAction() { return _action; }
void setStatusText(const char *text) {}//***DEPRECATED***
bool getDepthHighBit(const Common::Point &pt);
bool getDepthHighBits(const Common::Point &pt);
};
#define CHEAT_SEQUENCE_MAX 8

View File

@ -93,6 +93,8 @@ private:
bool isLineWalkable(int x0, int y0, int x1, int y1);
};
long SqrtF16(long n);
} // End of namespace M4
#endif