Trace shots against current map geometry instead of stale render depth. Preserve outline counters across volatile pixel calls and freeze gameplay on cinematic, transition and death ticks. Clamp packed HP before narrowing and match legacy archetype rules. Publish IDE saves atomically; failed saves block file switches and builds. Drain compiler output while hidden. Verify runtime/editor builds, 112 editor checks, 148 ASM checks and live preview parity. Record remaining stages in docs/STABILIZATION.md.
245 lines
5.5 KiB
PHP
245 lines
5.5 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
|
|
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 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:
|
|
cmp fadeState, 0
|
|
jne @F
|
|
call CheckPortalTriggers
|
|
@@:
|
|
ret
|
|
UpdatePlayer ENDP
|