Difference between revisions of "Fix jump height bug when exiting water"
From Sonic Retro
(wrote guide) |
m (Text replacement - "\[\[Category:SCHG How-tos.*" to "") |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 5: | Line 5: | ||
==Fixing the bug== | ==Fixing the bug== | ||
Locate the '''Obj01_InWater''' routine. It should look like this: | Locate the '''Obj01_InWater''' routine. It should look like this: | ||
− | <asm>; loc_1A18E: | + | <syntaxhighlight lang="asm">; loc_1A18E: |
Obj01_InWater: | Obj01_InWater: | ||
move.w (Water_Level_1).w,d0 | move.w (Water_Level_1).w,d0 | ||
Line 15: | Line 15: | ||
bset #6,status(a0) ; set underwater flag | bset #6,status(a0) ; set underwater flag | ||
bne.s return_1A18C ; if already underwater, branch | bne.s return_1A18C ; if already underwater, branch | ||
− | </ | + | </syntaxhighlight> |
At the indicated line, add this: | At the indicated line, add this: | ||
− | <asm> tst.w y_vel(a0) ; check if player is moving upward (i.e. from jumping) | + | <syntaxhighlight lang="asm"> tst.w y_vel(a0) ; check if player is moving upward (i.e. from jumping) |
bmi.s return_1A18C ; if yes, skip routine | bmi.s return_1A18C ; if yes, skip routine | ||
− | </ | + | </syntaxhighlight> |
Why this fixes the bug will be explained further down. | Why this fixes the bug will be explained further down. | ||
Line 27: | Line 27: | ||
==The bug explained== | ==The bug explained== | ||
This bug is the result of the in- and out water routines interacting in a way that isn't immediately obvious. On their own, they wouldn't cause this bug at all, since their conditions are mutually exclusive. The actual trigger lies elsewhere, in Sonic's jumping routine: | This bug is the result of the in- and out water routines interacting in a way that isn't immediately obvious. On their own, they wouldn't cause this bug at all, since their conditions are mutually exclusive. The actual trigger lies elsewhere, in Sonic's jumping routine: | ||
− | <asm>; loc_1AA38: | + | <syntaxhighlight lang="asm">; loc_1AA38: |
Sonic_Jump: | Sonic_Jump: | ||
move.b (Ctrl_1_Press_Logical).w,d0 | move.b (Ctrl_1_Press_Logical).w,d0 | ||
Line 43: | Line 43: | ||
return_1AAE6: | return_1AAE6: | ||
rts | rts | ||
− | </ | + | </syntaxhighlight> |
Right at the very end, before the routine returns, Sonic's position is increased slightly, moving him down. Now it's important to know, which order these routines run in. First, Sonic's movement code is run, where it checks if the player pushed a jump button. This is when Sonic is put in a jumping state, given some upward velocity and moved slightly down. Some time after that Sonic's water checks are run. If he was already very close to the water surface he might have been pushed under water by jumping. Now observe the code at '''Obj01_InWater''': | Right at the very end, before the routine returns, Sonic's position is increased slightly, moving him down. Now it's important to know, which order these routines run in. First, Sonic's movement code is run, where it checks if the player pushed a jump button. This is when Sonic is put in a jumping state, given some upward velocity and moved slightly down. Some time after that Sonic's water checks are run. If he was already very close to the water surface he might have been pushed under water by jumping. Now observe the code at '''Obj01_InWater''': | ||
− | <asm>; loc_1A18E: | + | <syntaxhighlight lang="asm">; loc_1A18E: |
Obj01_InWater: | Obj01_InWater: | ||
move.w (Water_Level_1).w,d0 | move.w (Water_Level_1).w,d0 | ||
Line 58: | Line 58: | ||
[...] | [...] | ||
− | </ | + | </syntaxhighlight> |
Since Sonic is under water this code is run. The game simulates the water's surface tension by halving Sonic's horizontal velocity and quartering his vertical velocity. Normally, this would just cause the water surface to break Sonic's fall, but since he's actually jumping, it reduces his jump strength considerably. During the next few frames Sonic slowly moves upward until he hits the water surface again. Now this code is run: | Since Sonic is under water this code is run. The game simulates the water's surface tension by halving Sonic's horizontal velocity and quartering his vertical velocity. Normally, this would just cause the water surface to break Sonic's fall, but since he's actually jumping, it reduces his jump strength considerably. During the next few frames Sonic slowly moves upward until he hits the water surface again. Now this code is run: | ||
− | <asm>; loc_1A1FE: | + | <syntaxhighlight lang="asm">; loc_1A1FE: |
Obj01_OutWater: | Obj01_OutWater: | ||
bclr #6,status(a0) ; unset underwater flag | bclr #6,status(a0) ; unset underwater flag | ||
Line 70: | Line 70: | ||
[...] | [...] | ||
− | </ | + | </syntaxhighlight> |
The significant part is where Sonic's vertical speed is doubled. This simulates Sonic no longer being subject to the water's resistance. Keeping in mind that previously Sonic's speed was quartered and now only doubled; that leaves Sonic with only half of his intended jump height, at most. By only allowing the speed decrease when Sonic is not moving up, this bug is fixed. | The significant part is where Sonic's vertical speed is doubled. This simulates Sonic no longer being subject to the water's resistance. Keeping in mind that previously Sonic's speed was quartered and now only doubled; that leaves Sonic with only half of his intended jump height, at most. By only allowing the speed decrease when Sonic is not moving up, this bug is fixed. | ||
+ | |||
+ | {{S2Howtos}} | ||
+ | |||
+ | |{{PAGENAME}}]] |
Latest revision as of 11:11, 25 August 2018
(Original guide by MoDule)
There is a bug in Sonic's water entry and exiting routines that is present in every main series 16-bit Sonic game. When Sonic is just above the point at which he would be considered submerged and jumps his jump height will be very low. This guide will show a possible way to fix this bug and explain its cause.
Fixing the bug
Locate the Obj01_InWater routine. It should look like this:
; loc_1A18E:
Obj01_InWater:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0 ; is Sonic above the water?
bge.s Obj01_OutWater ; if yes, branch
; <--
bset #6,status(a0) ; set underwater flag
bne.s return_1A18C ; if already underwater, branch
At the indicated line, add this:
tst.w y_vel(a0) ; check if player is moving upward (i.e. from jumping)
bmi.s return_1A18C ; if yes, skip routine
Why this fixes the bug will be explained further down.
Things to keep in mind
This is a general player object bug, so it will need to be fixed for Tails and Knuckles, too, if they are present.
The bug explained
This bug is the result of the in- and out water routines interacting in a way that isn't immediately obvious. On their own, they wouldn't cause this bug at all, since their conditions are mutually exclusive. The actual trigger lies elsewhere, in Sonic's jumping routine:
; loc_1AA38:
Sonic_Jump:
move.b (Ctrl_1_Press_Logical).w,d0
andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ; is A, B or C pressed?
beq.w return_1AAE6 ; if not, return
[...]
move.b #$E,y_radius(a0)
move.b #7,x_radius(a0)
move.b #2,anim(a0) ; use "jumping" animation
bset #2,status(a0)
addq.w #5,y_pos(a0) ; <--
return_1AAE6:
rts
Right at the very end, before the routine returns, Sonic's position is increased slightly, moving him down. Now it's important to know, which order these routines run in. First, Sonic's movement code is run, where it checks if the player pushed a jump button. This is when Sonic is put in a jumping state, given some upward velocity and moved slightly down. Some time after that Sonic's water checks are run. If he was already very close to the water surface he might have been pushed under water by jumping. Now observe the code at Obj01_InWater:
; loc_1A18E:
Obj01_InWater:
move.w (Water_Level_1).w,d0
cmp.w y_pos(a0),d0 ; is Sonic above the water?
bge.s Obj01_OutWater ; if yes, branch
[...]
asr.w x_vel(a0)
asr.w y_vel(a0) ; <-- memory operands can only be shifted one bit at a time
asr.w y_vel(a0)
[...]
Since Sonic is under water this code is run. The game simulates the water's surface tension by halving Sonic's horizontal velocity and quartering his vertical velocity. Normally, this would just cause the water surface to break Sonic's fall, but since he's actually jumping, it reduces his jump strength considerably. During the next few frames Sonic slowly moves upward until he hits the water surface again. Now this code is run:
; loc_1A1FE:
Obj01_OutWater:
bclr #6,status(a0) ; unset underwater flag
beq.s return_1A18C ; if already above water, branch
[...]
asl y_vel(a0) ; <--
[...]
The significant part is where Sonic's vertical speed is doubled. This simulates Sonic no longer being subject to the water's resistance. Keeping in mind that previously Sonic's speed was quartered and now only doubled; that leaves Sonic with only half of his intended jump height, at most. By only allowing the speed decrease when Sonic is not moving up, this bug is fixed.
|Fix jump height bug when exiting water]]