Обалденное вращение
This commit is contained in:
@@ -13,6 +13,13 @@ TWO_PI: dd 6.2831852
|
|||||||
NEG_ONE_CONST: dd -1.0
|
NEG_ONE_CONST: dd -1.0
|
||||||
ONE_CONST: dd 1.0
|
ONE_CONST: dd 1.0
|
||||||
ZERO_CONST: dd 0.0
|
ZERO_CONST: dd 0.0
|
||||||
|
ABS_MASK: dd 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff
|
||||||
|
ANG_COLLIDE_COEF: dd 0.55
|
||||||
|
ANG_BOOST_FACTOR: dd 0.02
|
||||||
|
ANG_MAX: dd 0.04
|
||||||
|
ANG_SWITCH_FACTOR: dd 0.1
|
||||||
|
ANG_MAX_DELTA: dd 0.5
|
||||||
|
ANG_FRICTION: dd 0.95
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
@@ -55,6 +62,11 @@ figure_animation_step:
|
|||||||
addss xmm0, [rdi + WDI_FIGURE + FIG_ANGLE]
|
addss xmm0, [rdi + WDI_FIGURE + FIG_ANGLE]
|
||||||
movss [rdi + WDI_FIGURE + FIG_ANGLE], xmm0
|
movss [rdi + WDI_FIGURE + FIG_ANGLE], xmm0
|
||||||
|
|
||||||
|
; Apply angular friction to slow down rotation over time
|
||||||
|
movss xmm0, [rdi + WDI_FIGURE + FIG_ANG_VEL]
|
||||||
|
mulss xmm0, [rel ANG_FRICTION]
|
||||||
|
movss [rdi + WDI_FIGURE + FIG_ANG_VEL], xmm0
|
||||||
|
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -139,6 +151,232 @@ figure_handle_collision:
|
|||||||
test r14, r14
|
test r14, r14
|
||||||
jz .no_collision
|
jz .no_collision
|
||||||
|
|
||||||
|
; -----------------------
|
||||||
|
; Обновить угловую скорость при коллизии
|
||||||
|
; Формула: delta = |relevant_velocity| * speed * ANG_COLLIDE_COEF
|
||||||
|
; Знак delta зависит от границы и направления движения.
|
||||||
|
; Если итоговое направление совпадает с текущим - даём небольшой буст.
|
||||||
|
; -----------------------
|
||||||
|
|
||||||
|
; Сохраняем старую угловую скорость и обнуляем суммарный эффект
|
||||||
|
movss xmm6, [r12 + WDI_FIGURE + FIG_ANG_VEL] ; old ang vel
|
||||||
|
xorps xmm7, xmm7 ; total delta
|
||||||
|
|
||||||
|
; LEFT (bit 0): use vertical motion (vel_y)
|
||||||
|
test r14, 0x1
|
||||||
|
jz .skip_left_ang
|
||||||
|
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY + 4] ; vel_y
|
||||||
|
movss xmm1, xmm0
|
||||||
|
; Broadcast ABS_MASK (0x7fffffff) into xmm2 and AND to get abs
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2 ; abs(vel_y)
|
||||||
|
mulss xmm1, [r12 + WDI_FIGURE + FIG_SPEED]
|
||||||
|
mulss xmm1, [rel ANG_COLLIDE_COEF]
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
jb .left_up_ang ; vel_y < 0 -> moving UP
|
||||||
|
; moving DOWN -> clockwise (+)
|
||||||
|
addss xmm7, xmm1
|
||||||
|
jmp .skip_left_ang
|
||||||
|
.left_up_ang:
|
||||||
|
; moving UP -> anticlockwise (-)
|
||||||
|
movss xmm2, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm2
|
||||||
|
addss xmm7, xmm1
|
||||||
|
.skip_left_ang:
|
||||||
|
|
||||||
|
; RIGHT (bit 2): use vertical motion (vel_y)
|
||||||
|
test r14, 0x4
|
||||||
|
jz .skip_right_ang
|
||||||
|
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY + 4] ; vel_y
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2
|
||||||
|
mulss xmm1, [r12 + WDI_FIGURE + FIG_SPEED]
|
||||||
|
mulss xmm1, [rel ANG_COLLIDE_COEF]
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
jb .right_up_ang ; vel_y < 0 -> moving UP
|
||||||
|
; moving DOWN -> anticlockwise (-)
|
||||||
|
movss xmm2, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm2
|
||||||
|
addss xmm7, xmm1
|
||||||
|
jmp .skip_right_ang
|
||||||
|
.right_up_ang:
|
||||||
|
; moving UP -> clockwise (+)
|
||||||
|
addss xmm7, xmm1
|
||||||
|
.skip_right_ang:
|
||||||
|
|
||||||
|
; TOP (bit 1): use horizontal motion (vel_x)
|
||||||
|
test r14, 0x2
|
||||||
|
jz .skip_top_ang
|
||||||
|
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY] ; vel_x
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2
|
||||||
|
mulss xmm1, [r12 + WDI_FIGURE + FIG_SPEED]
|
||||||
|
mulss xmm1, [rel ANG_COLLIDE_COEF]
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
ja .top_right_ang ; vel_x > 0 -> moving RIGHT
|
||||||
|
; moving LEFT -> clockwise (+)
|
||||||
|
addss xmm7, xmm1
|
||||||
|
jmp .skip_top_ang
|
||||||
|
.top_right_ang:
|
||||||
|
; moving RIGHT -> anticlockwise (-)
|
||||||
|
movss xmm2, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm2
|
||||||
|
addss xmm7, xmm1
|
||||||
|
.skip_top_ang:
|
||||||
|
|
||||||
|
; BOTTOM (bit 3): use horizontal motion (vel_x)
|
||||||
|
test r14, 0x8
|
||||||
|
jz .skip_bottom_ang
|
||||||
|
movss xmm0, [r12 + WDI_FIGURE + FIG_VELOCITY] ; vel_x
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2
|
||||||
|
mulss xmm1, [r12 + WDI_FIGURE + FIG_SPEED]
|
||||||
|
mulss xmm1, [rel ANG_COLLIDE_COEF]
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
ja .bottom_right_ang ; vel_x > 0 -> moving RIGHT
|
||||||
|
; moving LEFT -> anticlockwise (-)
|
||||||
|
movss xmm2, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm2
|
||||||
|
addss xmm7, xmm1
|
||||||
|
jmp .skip_bottom_ang
|
||||||
|
.bottom_right_ang:
|
||||||
|
; moving RIGHT -> clockwise (+)
|
||||||
|
addss xmm7, xmm1
|
||||||
|
.skip_bottom_ang:
|
||||||
|
|
||||||
|
; Если суммарный эффект нулевой - ничего не делаем
|
||||||
|
ucomiss xmm7, [rel ZERO_CONST]
|
||||||
|
je .ang_no_change
|
||||||
|
|
||||||
|
; Invert direction rules to match drawing coordinate system
|
||||||
|
; (User requested flip — so we reverse sign of computed delta)
|
||||||
|
movss xmm0, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm7, xmm0
|
||||||
|
|
||||||
|
; Decide: same direction or switch sign
|
||||||
|
ucomiss xmm6, [rel ZERO_CONST]
|
||||||
|
jb .old_neg_dir
|
||||||
|
; old >= 0
|
||||||
|
ucomiss xmm7, [rel ZERO_CONST]
|
||||||
|
jae .same_dir
|
||||||
|
jmp .switch_dir
|
||||||
|
.old_neg_dir:
|
||||||
|
; old < 0
|
||||||
|
ucomiss xmm7, [rel ZERO_CONST]
|
||||||
|
jb .same_dir
|
||||||
|
jmp .switch_dir
|
||||||
|
|
||||||
|
; If same direction -> boost and add
|
||||||
|
.same_dir:
|
||||||
|
mulss xmm7, [rel ANG_BOOST_FACTOR]
|
||||||
|
; Clamp delta magnitude to ANG_MAX_DELTA
|
||||||
|
movss xmm0, xmm7
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2 ; xmm1 = abs(delta)
|
||||||
|
movss xmm3, [rel ANG_MAX_DELTA]
|
||||||
|
ucomiss xmm1, xmm3
|
||||||
|
ja .cap_delta_same
|
||||||
|
jmp .after_cap_same
|
||||||
|
.cap_delta_same:
|
||||||
|
; Set abs(delta) = ANG_MAX_DELTA, preserve sign
|
||||||
|
movss xmm1, [rel ANG_MAX_DELTA]
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
jae .cap_delta_same_pos
|
||||||
|
movss xmm4, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm4
|
||||||
|
.cap_delta_same_pos:
|
||||||
|
movss xmm7, xmm1
|
||||||
|
.after_cap_same:
|
||||||
|
addss xmm6, xmm7
|
||||||
|
jmp .finish_dir_logic
|
||||||
|
|
||||||
|
; Switch sign -> compute new magnitude using old magnitude and delta
|
||||||
|
.switch_dir:
|
||||||
|
; xmm6 = old, xmm7 = delta
|
||||||
|
; abs_old = abs(xmm6)
|
||||||
|
movss xmm0, xmm6
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2 ; xmm1 = abs_old
|
||||||
|
|
||||||
|
; abs_delta = abs(xmm7)
|
||||||
|
movss xmm3, xmm7
|
||||||
|
movss xmm4, xmm3
|
||||||
|
andps xmm4, xmm2 ; xmm4 = abs_delta
|
||||||
|
; Clamp abs_delta
|
||||||
|
movss xmm5, [rel ANG_MAX_DELTA]
|
||||||
|
ucomiss xmm4, xmm5
|
||||||
|
ja .cap_delta_switch
|
||||||
|
jmp .delta_not_capped
|
||||||
|
.cap_delta_switch:
|
||||||
|
movss xmm4, xmm5
|
||||||
|
.delta_not_capped:
|
||||||
|
|
||||||
|
; abs_old *= ANG_SWITCH_FACTOR
|
||||||
|
movss xmm5, [rel ANG_SWITCH_FACTOR]
|
||||||
|
mulss xmm1, xmm5
|
||||||
|
|
||||||
|
; new_mag = abs_old + abs_delta
|
||||||
|
addss xmm1, xmm4
|
||||||
|
|
||||||
|
; apply sign of delta (xmm7)
|
||||||
|
ucomiss xmm7, [rel ZERO_CONST]
|
||||||
|
jae .switch_positive
|
||||||
|
; negative
|
||||||
|
movss xmm5, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm1, xmm5
|
||||||
|
movss xmm6, xmm1
|
||||||
|
jmp .finish_dir_logic
|
||||||
|
.switch_positive:
|
||||||
|
movss xmm6, xmm1
|
||||||
|
|
||||||
|
.finish_dir_logic:
|
||||||
|
; Clamp angular velocity: |xmm6| <= ANG_MAX
|
||||||
|
movss xmm0, xmm6
|
||||||
|
movss xmm1, xmm0
|
||||||
|
mov eax, dword [rel ABS_MASK]
|
||||||
|
movd xmm2, eax
|
||||||
|
pshufd xmm2, xmm2, 0x0
|
||||||
|
andps xmm1, xmm2 ; xmm1 = abs(xmm0)
|
||||||
|
movss xmm2, [rel ANG_MAX]
|
||||||
|
ucomiss xmm1, xmm2
|
||||||
|
ja .ang_clamp_needed
|
||||||
|
movss [r12 + WDI_FIGURE + FIG_ANG_VEL], xmm6
|
||||||
|
jmp .ang_no_change2
|
||||||
|
.ang_clamp_needed:
|
||||||
|
; If xmm0 >= 0 -> set +ANG_MAX else set -ANG_MAX
|
||||||
|
ucomiss xmm0, [rel ZERO_CONST]
|
||||||
|
jae .ang_positive_clamp
|
||||||
|
; negative
|
||||||
|
movss xmm3, [rel ANG_MAX]
|
||||||
|
movss xmm4, [rel NEG_ONE_CONST]
|
||||||
|
mulss xmm3, xmm4
|
||||||
|
movss xmm6, xmm3
|
||||||
|
movss [r12 + WDI_FIGURE + FIG_ANG_VEL], xmm6
|
||||||
|
jmp .ang_no_change2
|
||||||
|
.ang_positive_clamp:
|
||||||
|
movss xmm3, [rel ANG_MAX]
|
||||||
|
movss xmm6, xmm3
|
||||||
|
movss [r12 + WDI_FIGURE + FIG_ANG_VEL], xmm6
|
||||||
|
.ang_no_change2:
|
||||||
|
.ang_no_change:
|
||||||
|
|
||||||
; Обработка коллизий: инвертировать velocity только если движемся к границе
|
; Обработка коллизий: инвертировать velocity только если движемся к границе
|
||||||
|
|
||||||
; Проверка left (bit 0): инвертировать velocity.x только если vel.x < 0
|
; Проверка left (bit 0): инвертировать velocity.x только если vel.x < 0
|
||||||
|
|||||||
Reference in New Issue
Block a user