EBLAN_ENGINE/include/engine_physics.inc
Игорь Федосеев aa64510def feat: stabilize fixed-tick simulation
Decouple gameplay from presentation and preserve signed movement fractions. Separate cinematic camera ownership with safe body handoff and transactional current-room restarts.

Resample input latches on focus regain, discard modal timing debt, and attach cinematic lighting to the view to match editor preview.

Verify editor 137/137 and ASM 288/288, cinematic traces, RGB bake and IPC framebuffer parity without changing project assets.
2026-10-31 22:31:20 +03:00

222 lines
4.5 KiB
PHP

; Fixed-tick player simulation. Wire coordinates remain raw world units.
.code
StartCutscene PROTO
StopCutscene PROTO
UpdateCutscene PROTO
IsGameplayBlocked PROC
mov eax, gameplayTickBlocked
or eax, isPlayerDead
or eax, isCutsceneActive
or eax, cutscenePending
or eax, fadeState
or eax, isGamePaused
or eax, gameDialogActive
ret
IsGameplayBlocked ENDP
ResetMovementFractions PROC
mov playerFractionX, 0
mov playerFractionY, 0
ret
ResetMovementFractions ENDP
; Test every overlapped cell, not only the leading edge's center. Portal cells
; block rays but deliberately remain walkable for players/camera handoff.
CanOccupyPlayer PROC uses ebx ecx edx esi edi, x:DWORD, y:DWORD
LOCAL minX:DWORD, maxX:DWORD, maxY:DWORD, row:DWORD
mov eax, x
sub eax, playerRadius
sar eax, CELL_SHIFT
mov minX, eax
mov eax, x
add eax, playerRadius
sar eax, CELL_SHIFT
mov maxX, eax
mov eax, y
sub eax, playerRadius
sar eax, CELL_SHIFT
mov row, eax
mov eax, y
add eax, playerRadius
sar eax, CELL_SHIFT
mov maxY, eax
body_row:
mov ebx, minX
body_cell:
invoke GetMapCell, ebx, row
cmp eax, CELL_PORTAL
je body_next
invoke IsSolidCell, eax
test eax, eax
jnz body_blocked
body_next:
inc ebx
cmp ebx, maxX
jle body_cell
inc row
mov eax, row
cmp eax, maxY
jle body_row
mov eax, 1
ret
body_blocked:
xor eax, eax
ret
CanOccupyPlayer ENDP
UpdatePlayer PROC uses ebx ecx edx esi edi
LOCAL forward:SDWORD, strafe:SDWORD, speed:DWORD
LOCAL moveX:SDWORD, moveY:SDWORD, steps:DWORD
mov gameplayTickBlocked, 1
cmp isGamePaused, 0
jne player_done
cmp gameDialogActive, 0
jne player_done
cmp isPlayerDead, 0
jne player_done
cmp fadeState, 0
jne player_done
cmp cutscenePending, 0
je @F
call StartCutscene
@@:
cmp keyCutscene, 0
je @F
cmp isCutsceneActive, 0
jne @F
call StartCutscene
@@:
cmp isCutsceneActive, 0
je player_active
cmp keySkipScene, 0
je player_scene
call StopCutscene
ret
player_scene:
call UpdateCutscene
ret
player_active:
mov gameplayTickBlocked, 0
movzx eax, keyTurnRight
movzx ebx, keyTurnLeft
sub eax, ebx
imul eax, playerTurnSpeed
add eax, playerAngle
and eax, ANGLE_MASK
mov playerAngle, eax
cmp keyAction, 0
je @F
call InteractDoor
call IsGameplayBlocked
test eax, eax
jnz player_done
@@:
movzx eax, keyForward
movzx ebx, keyBackward
sub eax, ebx
mov forward, eax
movzx eax, keyStrafeRight
movzx ebx, keyStrafeLeft
sub eax, ebx
mov strafe, eax
or eax, forward
jz player_done
mov eax, playerMoveSpeed
cmp keyRun, 0
je @F
mov eax, playerRunSpeed
@@:
shl eax, 16
cmp forward, 0
je speed_ready
cmp strafe, 0
je speed_ready
; 1/sqrt(2), 16.16. Product may exceed 32 bits.
mov ebx, 46341
imul ebx
shrd eax, edx, 16
speed_ready:
mov speed, eax
mov ecx, playerAngle
mov eax, [tableCos+ecx*4]
imul eax, forward
mov ebx, [tableSin+ecx*4]
imul ebx, strafe
sub eax, ebx
imul speed
mov ebx, FIXED_ONE
idiv ebx
add eax, playerFractionX
cdq
mov ebx, FIXED_ONE
idiv ebx
mov moveX, eax
mov playerFractionX, edx
mov eax, [tableSin+ecx*4]
imul eax, forward
mov ebx, [tableCos+ecx*4]
imul ebx, strafe
add eax, ebx
imul speed
mov ebx, FIXED_ONE
idiv ebx
add eax, playerFractionY
cdq
mov ebx, FIXED_ONE
idiv ebx
mov moveY, eax
mov playerFractionY, edx
; Unit substeps prevent tunneling even when scripts increase speed.
mov steps, 0
player_step:
mov eax, moveX
or eax, moveY
jz player_done
inc steps
cmp steps, 64
ja player_done
cmp moveX, 0
je step_y
mov esi, 1
jg @F
mov esi, -1
@@:
mov ebx, playerX
add ebx, esi
invoke CanOccupyPlayer, ebx, playerY
test eax, eax
jz blocked_x
mov playerX, ebx
sub moveX, esi
jmp step_y
blocked_x:
mov moveX, 0
mov playerFractionX, 0
step_y:
cmp moveY, 0
je player_step
mov esi, 1
jg @F
mov esi, -1
@@:
mov ebx, playerY
add ebx, esi
invoke CanOccupyPlayer, playerX, ebx
test eax, eax
jz blocked_y
mov playerY, ebx
sub moveY, esi
jmp player_step
blocked_y:
mov moveY, 0
mov playerFractionY, 0
jmp player_step
player_done:
call IsGameplayBlocked
test eax, eax
jnz @F
call CheckPortalTriggers
@@:
ret
UpdatePlayer ENDP