192 lines
4.2 KiB
PHP
192 lines
4.2 KiB
PHP
; ==============================================================================
|
|
; EBLAN ENGINE - Player Movement, Physics & Collision Handling
|
|
; ==============================================================================
|
|
|
|
.code
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; 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 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
|
|
|
|
; 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
|
|
invoke IsSolidCell, eax
|
|
test eax, eax
|
|
jnz skip_x_move ; Collision on X: slide along wall!
|
|
|
|
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
|
|
invoke IsSolidCell, eax
|
|
test eax, eax
|
|
jnz update_player_done ; Collision on Y
|
|
|
|
mov eax, nextY
|
|
mov playerY, eax
|
|
|
|
update_player_done:
|
|
ret
|
|
UpdatePlayer ENDP
|