mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-29 14:42:26 +00:00
Preliminary implementation of lots of code related to player movement
svn-id: r50882
This commit is contained in:
parent
f456b7cfa2
commit
f796fd6cf3
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -93,6 +93,8 @@ private:
|
||||
bool isLineWalkable(int x0, int y0, int x1, int y1);
|
||||
};
|
||||
|
||||
long SqrtF16(long n);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user