mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
SCUMM: (SCUMM3) - pixel-perfect walking
This is a follow-up commit to 8cbcde0c
(bug
https://bugs.scummvm.org/ticket/12666). While that commit improved the situation, in particular the behavior described in the bug ticket, it still wasn't anything like pixel-perfect.
The agents would walk in a weird half circle due to being showered with walkActorToActor calls from the script.
I have now implemented the original walk code and also compared the first part of the INDY3 scene described in the ticket frame by frame with the DOSBox debugger to check whether it is truly pixel-perfect.
This commit is contained in:
parent
8e0092c5d2
commit
f039bdb083
@ -151,6 +151,8 @@ void Actor::initActor(int mode) {
|
||||
_flip = false;
|
||||
_speedx = 8;
|
||||
_speedy = 2;
|
||||
_v3stepX = 0;
|
||||
_v3stepThreshold = 0;
|
||||
_frame = 0;
|
||||
_walkbox = 0;
|
||||
_animProgress = 0;
|
||||
@ -483,42 +485,52 @@ int Actor::calcMovementFactor(const Common::Point& next) {
|
||||
|
||||
diffX = next.x - _pos.x;
|
||||
diffY = next.y - _pos.y;
|
||||
deltaYFactor = _speedy << 16;
|
||||
|
||||
// These two lines fix bug #1052 (INDY3: Hitler facing wrong directions in the Berlin scene).
|
||||
// I can't see anything like this in the original SCUMM1/2 code, so I limit this to SCUMM3.
|
||||
if (_vm->_game.version == 3 && !(_moving & MF_LAST_LEG) && (int)_speedx > ABS(diffX) && (int)_speedy > ABS(diffY))
|
||||
return 0;
|
||||
if (_vm->_game.version == 3) {
|
||||
// These two lines fix bug #1052 (INDY3: Hitler facing wrong directions in the Berlin scene).
|
||||
// I can't see anything like this in the original SCUMM1/2 code, so I limit this to SCUMM3.
|
||||
if (!(_moving & MF_LAST_LEG) && (int)_speedx > ABS(diffX) && (int)_speedy > ABS(diffY))
|
||||
return 0;
|
||||
|
||||
if (diffY < 0)
|
||||
deltaYFactor = -deltaYFactor;
|
||||
|
||||
deltaXFactor = deltaYFactor * diffX;
|
||||
if (diffY != 0) {
|
||||
deltaXFactor /= diffY;
|
||||
_v3stepX = ((ABS(diffY) / (int)_speedy) >> 1) > (ABS(diffX) / (int)_speedx) ? _speedy + 1 : _speedx;
|
||||
_v3stepThreshold = MAX(ABS(diffY) / _speedy, ABS(diffX) / _v3stepX);
|
||||
deltaXFactor = diffX < 0 ? -_v3stepX : _v3stepX;
|
||||
deltaYFactor = diffY < 0 ? -_speedy : _speedy;
|
||||
_walkdata.xfrac = _walkdata.v3XAdd = diffX / deltaXFactor;
|
||||
_walkdata.yfrac = _walkdata.v3YAdd = diffY / deltaYFactor;
|
||||
} else {
|
||||
deltaYFactor = 0;
|
||||
}
|
||||
deltaYFactor = _speedy << 16;
|
||||
if (diffY < 0)
|
||||
deltaYFactor = -deltaYFactor;
|
||||
|
||||
if ((uint) ABS(deltaXFactor) > (_speedx << 16)) {
|
||||
deltaXFactor = _speedx << 16;
|
||||
if (diffX < 0)
|
||||
deltaXFactor = -deltaXFactor;
|
||||
|
||||
deltaYFactor = deltaXFactor * diffY;
|
||||
if (diffX != 0) {
|
||||
deltaYFactor /= diffX;
|
||||
deltaXFactor = deltaYFactor * diffX;
|
||||
if (diffY != 0) {
|
||||
deltaXFactor /= diffY;
|
||||
} else {
|
||||
deltaXFactor = 0;
|
||||
deltaYFactor = 0;
|
||||
}
|
||||
|
||||
if ((uint)ABS(deltaXFactor) > (_speedx << 16)) {
|
||||
deltaXFactor = _speedx << 16;
|
||||
if (diffX < 0)
|
||||
deltaXFactor = -deltaXFactor;
|
||||
|
||||
deltaYFactor = deltaXFactor * diffY;
|
||||
if (diffX != 0) {
|
||||
deltaYFactor /= diffX;
|
||||
} else {
|
||||
deltaXFactor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_walkdata.xfrac = 0;
|
||||
_walkdata.yfrac = 0;
|
||||
}
|
||||
|
||||
_walkdata.cur = _pos;
|
||||
_walkdata.next = next;
|
||||
_walkdata.deltaXFactor = deltaXFactor;
|
||||
_walkdata.deltaYFactor = deltaYFactor;
|
||||
_walkdata.xfrac = 0;
|
||||
_walkdata.yfrac = 0;
|
||||
|
||||
if (_vm->_game.version <= 3)
|
||||
// The x/y distance ratio which determines whether to face up/down instead of left/right is different for SCUMM1/2 and SCUMM3.
|
||||
@ -548,7 +560,7 @@ int Actor::actorWalkStep() {
|
||||
}
|
||||
|
||||
if (_vm->_game.version == 3) {
|
||||
if (_walkdata.next.x - (int)_speedx <= _pos.x && _walkdata.next.x + (int)_speedx >= _pos.x)
|
||||
if (_walkdata.next.x - (int)_v3stepX <= _pos.x && _walkdata.next.x + (int)_v3stepX >= _pos.x)
|
||||
_pos.x = _walkdata.next.x;
|
||||
if (_walkdata.next.y - (int)_speedy <= _pos.y && _walkdata.next.y + (int)_speedy >= _pos.y)
|
||||
_pos.y = _walkdata.next.y;
|
||||
@ -578,6 +590,15 @@ int Actor::actorWalkStep() {
|
||||
else
|
||||
_pos.y -= 1;
|
||||
}
|
||||
} else if (_vm->_game.version == 3) {
|
||||
if ((_walkdata.xfrac += _walkdata.v3XAdd) > _v3stepThreshold) {
|
||||
_pos.x += _walkdata.deltaXFactor;
|
||||
_walkdata.xfrac -= _v3stepThreshold;
|
||||
}
|
||||
if ((_walkdata.yfrac += _walkdata.v3YAdd) >= _v3stepThreshold) {
|
||||
_pos.y += _walkdata.deltaYFactor;
|
||||
_walkdata.yfrac -= _v3stepThreshold;
|
||||
}
|
||||
} else {
|
||||
tmpX = (_pos.x * (1 << 16)) + _walkdata.xfrac + (_walkdata.deltaXFactor / 256) * _scalex;
|
||||
_walkdata.xfrac = (uint16)tmpX;
|
||||
|
@ -151,6 +151,7 @@ protected:
|
||||
Common::Point point3;
|
||||
int32 deltaXFactor, deltaYFactor;
|
||||
uint16 xfrac, yfrac;
|
||||
uint16 v3XAdd, v3YAdd;
|
||||
|
||||
void reset() {
|
||||
dest.x = dest.y = 0;
|
||||
@ -164,6 +165,8 @@ protected:
|
||||
deltaYFactor = 0;
|
||||
xfrac = 0;
|
||||
yfrac = 0;
|
||||
v3XAdd = 0;
|
||||
v3YAdd = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -173,6 +176,7 @@ protected:
|
||||
uint16 _facing;
|
||||
uint16 _targetFacing;
|
||||
uint _speedx, _speedy;
|
||||
uint _v3stepX, _v3stepThreshold;
|
||||
byte _animProgress, _animSpeed;
|
||||
bool _costumeNeedsInit;
|
||||
ActorWalkData _walkdata;
|
||||
|
Loading…
Reference in New Issue
Block a user