EBLAN_ENGINE/include/engine_physics.inc
Игорь Федосеев 527d92411d chore: integrate main before stage 2
Preserve stage-1 stability fixes alongside v5 lighting, IPC v2, weapons and studio updates. Fix barrel AOE pointer corruption and extend modal gameplay gating.

Verify 137 editor checks, 191 ASM checks, lighting bake and preview parity. Document stage-2 scope without implementing it.
2026-10-31 22:10:07 +03:00

252 lines
5.6 KiB
PHP

; ==============================================================================
; EBLAN ENGINE - Player Movement, Physics & Collision Handling
; ==============================================================================
.code
; Shared gameplay gate. Returns EAX != 0 when simulation must be frozen.
; UpdatePlayer owns the per-tick latch; renderer never changes this decision.
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
; ------------------------------------------------------------------------------
; UpdatePlayer: Updates rotation, computes movement vector & handles collisions
; ------------------------------------------------------------------------------
UpdatePlayer PROC uses ebx ecx edx esi edi
LOCAL moveX:DWORD, moveY:DWORD
LOCAL speed:DWORD
LOCAL nextX:DWORD, nextY:DWORD
LOCAL checkGridX:DWORD, checkGridY:DWORD
mov gameplayTickBlocked, 1
cmp isGamePaused, 0
jne update_player_done
cmp gameDialogActive, 0
jne update_player_done
cmp isPlayerDead, 0
jne update_player_done
; Freeze player movement and inputs during level transitions
cmp fadeState, 0
jne update_player_done
cmp cutscenePending, 0
je scene_manual_start
call StartCutscene
scene_manual_start:
cmp keyCutscene, 0
je scene_check_active
cmp isCutsceneActive, 0
jne scene_check_active
call StartCutscene
scene_check_active:
cmp isCutsceneActive, 0
je normal_player_update
cmp keySkipScene, 0
je scene_update_tick
call StopCutscene
ret
scene_update_tick:
call UpdateCutscene
ret
normal_player_update:
mov gameplayTickBlocked, 0
mov moveX, 0
mov moveY, 0
; 1. Handle Camera Rotation
cmp keyTurnLeft, 0
je check_turn_right
mov eax, playerAngle
sub eax, playerTurnSpeed
and eax, ANGLE_MASK
mov playerAngle, eax
check_turn_right:
cmp keyTurnRight, 0
je check_action
mov eax, playerAngle
add eax, playerTurnSpeed
and eax, ANGLE_MASK
mov playerAngle, eax
check_action:
cmp keyAction, 0
je check_movement
call InteractDoor
cmp fadeState, 0
jne update_player_done
cmp gameplayTickBlocked, 0
jne update_player_done
; 2. Determine Movement Speed
check_movement:
mov eax, playerMoveSpeed ; Base speed: raw units/frame
cmp keyRun, 0
je @F
mov eax, playerRunSpeed ; Sprint speed
@@:
mov speed, eax
; 3. Forward / Backward Vector
cmp keyForward, 0
je check_backward
mov eax, playerAngle
and eax, ANGLE_MASK
; dx += cos(angle) * speed
mov ebx, [tableCos + eax*4]
imul ebx, speed
sar ebx, 16
add moveX, ebx
; dy += sin(angle) * speed
mov ecx, [tableSin + eax*4]
imul ecx, speed
sar ecx, 16
add moveY, ecx
check_backward:
cmp keyBackward, 0
je check_strafe_left
mov eax, playerAngle
and eax, ANGLE_MASK
mov ebx, [tableCos + eax*4]
imul ebx, speed
sar ebx, 16
sub moveX, ebx
mov ecx, [tableSin + eax*4]
imul ecx, speed
sar ecx, 16
sub moveY, ecx
; 4. Strafe Left / Right Vector (Angle +/- 90 degrees)
check_strafe_left:
cmp keyStrafeLeft, 0
je check_strafe_right
; Left vector is (angle - 128)
mov eax, playerAngle
sub eax, ANGLE_90
and eax, ANGLE_MASK
mov ebx, [tableCos + eax*4]
imul ebx, speed
sar ebx, 16
add moveX, ebx
mov ecx, [tableSin + eax*4]
imul ecx, speed
sar ecx, 16
add moveY, ecx
check_strafe_right:
cmp keyStrafeRight, 0
je apply_physics
; Right vector is (angle + 128)
mov eax, playerAngle
add eax, ANGLE_90
and eax, ANGLE_MASK
mov ebx, [tableCos + eax*4]
imul ebx, speed
sar ebx, 16
add moveX, ebx
mov ecx, [tableSin + eax*4]
imul ecx, speed
sar ecx, 16
add moveY, ecx
; 5. Apply Movement with Wall-Sliding Collision Detection
apply_physics:
mov eax, moveX
or eax, moveY
jz update_player_done ; No movement input
; --- Test X Movement ---
mov eax, playerX
add eax, moveX
mov nextX, eax
; Buffer check (collision body radius)
mov ebx, nextX
cmp moveX, 0
jge @F
mov eax, playerRadius
sub ebx, eax ; Moving left: check left edge
jmp check_x_col
@@:
mov eax, playerRadius
add ebx, eax ; Moving right: check right edge
check_x_col:
sar ebx, 6 ; divide by CELL_SIZE (64)
mov checkGridX, ebx
mov ecx, playerY
sar ecx, 6
mov checkGridY, ecx
invoke GetMapCell, checkGridX, checkGridY
cmp eax, CELL_PORTAL
je allow_portal_x
invoke IsSolidCell, eax
test eax, eax
jnz skip_x_move ; Collision on X: slide along wall!
allow_portal_x:
mov eax, nextX
mov playerX, eax
skip_x_move:
; --- Test Y Movement ---
mov eax, playerY
add eax, moveY
mov nextY, eax
mov ecx, nextY
cmp moveY, 0
jge @F
mov eax, playerRadius
sub ecx, eax
jmp check_y_col
@@:
mov eax, playerRadius
add ecx, eax
check_y_col:
sar ecx, 6
mov checkGridY, ecx
mov ebx, playerX
sar ebx, 6
mov checkGridX, ebx
invoke GetMapCell, checkGridX, checkGridY
cmp eax, CELL_PORTAL
je allow_portal_y
invoke IsSolidCell, eax
test eax, eax
jnz update_player_done ; Collision on Y
allow_portal_y:
mov eax, nextY
mov playerY, eax
update_player_done:
call IsGameplayBlocked
test eax, eax
jnz @F
call CheckPortalTriggers
@@:
ret
UpdatePlayer ENDP