Implement 3D positional audio across floors and popup volume HUD for Jukebox
This commit is contained in:
parent
d4436674b4
commit
75d594ec79
6 changed files with 505 additions and 2 deletions
Binary file not shown.
|
|
@ -5346,6 +5346,7 @@ check_walk_mode:
|
|||
call UpdateCamera3D
|
||||
call CheckInteractions
|
||||
call HandlePlayerInput
|
||||
call HandleJukeboxKeys3D
|
||||
call UpdateInteriorTravel3D
|
||||
call UpdateInteriorEye3D
|
||||
call UpdateCamera3D
|
||||
|
|
@ -5433,6 +5434,7 @@ check_darts_done:
|
|||
cmp engineMode, MODE_STAIRS
|
||||
jne @F
|
||||
call HandleStairs3D
|
||||
call HandleJukeboxKeys3D
|
||||
call RenderStairs3D
|
||||
jmp present_frame
|
||||
@@:
|
||||
|
|
@ -5594,7 +5596,9 @@ pause_low_spec_saved:
|
|||
call SaveProgress3D
|
||||
jmp engine_shutdown
|
||||
present_frame:
|
||||
call UpdateJukeboxAudio3D
|
||||
call RenderTowerInGameBadge
|
||||
call RenderJukeboxVolumeHUD
|
||||
mov eax, engineMode
|
||||
cmp eax, lastPersistMode3D
|
||||
je @F
|
||||
|
|
|
|||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
|
|
@ -121,9 +121,12 @@ PlayJukeboxTrack3D PROC uses ebx trackIndex:DWORD
|
|||
invoke mciSendStringA, OFFSET jboxPlayCmd, 0, 0, 0
|
||||
mov jboxCurrentTrack, ebx
|
||||
mov jboxIsPlaying, 1
|
||||
mov jboxEffectiveVolume, -1
|
||||
call UpdateJukeboxAudio3D
|
||||
ret
|
||||
jbox_play_stop_selected:
|
||||
mov jboxCurrentTrack, -1
|
||||
call UpdateJukeboxAudio3D
|
||||
ret
|
||||
PlayJukeboxTrack3D ENDP
|
||||
|
||||
|
|
@ -132,6 +135,7 @@ StopJukeboxTrack3D PROC
|
|||
invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0
|
||||
mov jboxIsPlaying, 0
|
||||
mov jboxCurrentTrack, -1
|
||||
call UpdateJukeboxAudio3D
|
||||
ret
|
||||
StopJukeboxTrack3D ENDP
|
||||
|
||||
|
|
@ -411,3 +415,471 @@ jbox_row_next:
|
|||
|
||||
ret
|
||||
RenderJackbox3D ENDP
|
||||
|
||||
; ==============================================================================
|
||||
; 3D SOUND PROPAGATION & MULTI-FLOOR ATTENUATION
|
||||
; ==============================================================================
|
||||
|
||||
CalculateJukeboxFalloff PROC uses ebx esi edi
|
||||
local dxDist:DWORD, dyDist:DWORD, distSq:DWORD, distVal:DWORD
|
||||
local factor:DWORD
|
||||
|
||||
; If music is not playing, factor = 0
|
||||
cmp jboxIsPlaying, 1
|
||||
jne falloff_silent
|
||||
cmp jboxCurrentTrack, -1
|
||||
je falloff_silent
|
||||
cmp jboxCurrentTrack, 2
|
||||
jae falloff_silent
|
||||
|
||||
; Check if on stairs (MODE_STAIRS)
|
||||
cmp engineMode, MODE_STAIRS
|
||||
je falloff_stairs
|
||||
|
||||
; Check floor level
|
||||
mov eax, hallLevel3D
|
||||
cmp eax, 0
|
||||
je falloff_ground
|
||||
cmp eax, 1
|
||||
je falloff_bunker
|
||||
cmp eax, 2
|
||||
je falloff_upper
|
||||
cmp eax, 3
|
||||
je falloff_fortune
|
||||
jmp falloff_silent
|
||||
|
||||
falloff_ground:
|
||||
; Level 0 (Ground Hall) - standard quadratic 2D distance falloff from Jackbox
|
||||
; Jackbox: JACKBOX_X = 30.6m, JACKBOX_Y = 23.5m
|
||||
mov eax, playerX
|
||||
sub eax, JACKBOX_X
|
||||
test eax, eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
shr eax, 16 ; integer meters
|
||||
mov dxDist, eax
|
||||
|
||||
mov eax, playerY
|
||||
sub eax, JACKBOX_Y
|
||||
test eax, eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
shr eax, 16 ; integer meters
|
||||
mov dyDist, eax
|
||||
|
||||
; distSq = dx*dx + dy*dy
|
||||
mov eax, dxDist
|
||||
imul eax, eax
|
||||
mov ebx, dyDist
|
||||
imul ebx, ebx
|
||||
add eax, ebx
|
||||
mov distSq, eax
|
||||
|
||||
; distVal = sqrt(distSq)
|
||||
fild distSq
|
||||
fsqrt
|
||||
fistp distVal
|
||||
|
||||
; Acoustic curve:
|
||||
; dist <= 2m -> factor = 1000
|
||||
; dist >= 35m -> factor = 0
|
||||
; in between: rem = 35 - dist; factor = 1000 * rem * rem / 1089
|
||||
mov eax, distVal
|
||||
cmp eax, 2
|
||||
jbe falloff_full
|
||||
cmp eax, 35
|
||||
jae falloff_silent
|
||||
|
||||
mov ecx, 35
|
||||
sub ecx, eax ; ecx = 35 - distVal (in 1..32)
|
||||
imul eax, ecx, 1000
|
||||
imul eax, ecx ; eax = 1000 * rem * rem
|
||||
xor edx, edx
|
||||
mov ebx, 1089 ; 33 * 33
|
||||
div ebx
|
||||
mov factor, eax
|
||||
jmp falloff_done
|
||||
|
||||
falloff_full:
|
||||
mov factor, 1000
|
||||
jmp falloff_done
|
||||
|
||||
falloff_upper:
|
||||
; Level 2 (Upper Lounge) - sound travels up the open stairs (stairwell at X=16, Y=21 on upper map)
|
||||
; Base attenuation through floor + distance from stairwell opening
|
||||
mov eax, playerX
|
||||
sub eax, 16*FP_1
|
||||
test eax, eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
shr eax, 16
|
||||
mov dxDist, eax
|
||||
|
||||
mov eax, playerY
|
||||
sub eax, 21*FP_1
|
||||
test eax, eax
|
||||
jns @F
|
||||
neg eax
|
||||
@@:
|
||||
shr eax, 16
|
||||
mov dyDist, eax
|
||||
|
||||
mov eax, dxDist
|
||||
imul eax, eax
|
||||
mov ebx, dyDist
|
||||
imul ebx, ebx
|
||||
add eax, ebx
|
||||
mov distSq, eax
|
||||
|
||||
fild distSq
|
||||
fsqrt
|
||||
fistp distVal
|
||||
|
||||
; At stair opening: factor = 420 (muffled from below)
|
||||
; Drops by 18 per meter, min 90
|
||||
mov eax, distVal
|
||||
imul eax, 18
|
||||
mov ecx, 420
|
||||
sub ecx, eax
|
||||
cmp ecx, 90
|
||||
jge @F
|
||||
mov ecx, 90
|
||||
@@:
|
||||
mov factor, ecx
|
||||
jmp falloff_done
|
||||
|
||||
falloff_bunker:
|
||||
; Level 1 (Bunker) - underground, heavily muffled concrete absorption (~160)
|
||||
mov factor, 160
|
||||
jmp falloff_done
|
||||
|
||||
falloff_fortune:
|
||||
; Level 3 (Fortune Room) - secret room on opposite side of casino (~90)
|
||||
mov factor, 90
|
||||
jmp falloff_done
|
||||
|
||||
falloff_stairs:
|
||||
; On stairs between floors
|
||||
mov eax, stairRoute3D
|
||||
cmp eax, 2
|
||||
je falloff_stairs_upper
|
||||
cmp eax, 1
|
||||
je falloff_stairs_bunker
|
||||
mov factor, 150
|
||||
jmp falloff_done
|
||||
|
||||
falloff_stairs_upper:
|
||||
; Route 2 (Upper stairs)
|
||||
; playerX goes from ~3 (bottom, beside jukebox) to ~16 (top, upper floor)
|
||||
; At bottom: 850. At top: 420.
|
||||
mov eax, playerX
|
||||
shr eax, 16 ; integer X (3..16)
|
||||
cmp eax, 3
|
||||
jge @F
|
||||
mov eax, 3
|
||||
@@:
|
||||
cmp eax, 16
|
||||
jle @F
|
||||
mov eax, 16
|
||||
@@:
|
||||
; Interpolate: factor = 850 - (eax - 3) * (850 - 420) / 13
|
||||
sub eax, 3
|
||||
imul eax, 430
|
||||
xor edx, edx
|
||||
mov ebx, 13
|
||||
div ebx
|
||||
mov ecx, 850
|
||||
sub ecx, eax
|
||||
mov factor, ecx
|
||||
jmp falloff_done
|
||||
|
||||
falloff_stairs_bunker:
|
||||
; Route 1 (Basement stairs)
|
||||
; Smooth blend between 350 (top) and 160 (bottom)
|
||||
mov factor, 250
|
||||
jmp falloff_done
|
||||
|
||||
falloff_silent:
|
||||
mov factor, 0
|
||||
|
||||
falloff_done:
|
||||
mov eax, factor
|
||||
ret
|
||||
CalculateJukeboxFalloff ENDP
|
||||
|
||||
UpdateJukeboxAudio3D PROC uses ebx esi edi
|
||||
local falloff:DWORD, targetVol:DWORD
|
||||
|
||||
; Check if music is playing
|
||||
cmp jboxIsPlaying, 1
|
||||
jne jbox_audio_mute
|
||||
|
||||
; If user volume is 0 -> mute
|
||||
mov eax, jboxUserVolume
|
||||
test eax, eax
|
||||
jz jbox_audio_mute
|
||||
|
||||
; Calculate 3D attenuation factor (0..1000)
|
||||
call CalculateJukeboxFalloff
|
||||
mov falloff, eax
|
||||
test eax, eax
|
||||
jz jbox_audio_mute
|
||||
|
||||
; targetVol = (jboxUserVolume * 100) * falloff / 1000
|
||||
; jboxUserVolume is 0..10 (0..1000 base)
|
||||
mov eax, jboxUserVolume
|
||||
imul eax, 100
|
||||
imul eax, falloff
|
||||
xor edx, edx
|
||||
mov ebx, 1000
|
||||
div ebx
|
||||
mov targetVol, eax
|
||||
jmp jbox_apply_vol
|
||||
|
||||
jbox_audio_mute:
|
||||
mov targetVol, 0
|
||||
|
||||
jbox_apply_vol:
|
||||
; If targetVol matches last applied volume, skip redundant MCI call
|
||||
mov eax, targetVol
|
||||
cmp eax, jboxEffectiveVolume
|
||||
je jbox_audio_done
|
||||
|
||||
mov jboxEffectiveVolume, eax
|
||||
|
||||
; Format: "setaudio jboxmusic volume to <targetVol>"
|
||||
; Copy prefix to jboxVolCmdBuf
|
||||
lea esi, jboxVolCmdPrefix
|
||||
lea edi, jboxVolCmdBuf
|
||||
jbox_vol_copy:
|
||||
lodsb
|
||||
stosb
|
||||
test al, al
|
||||
jnz jbox_vol_copy
|
||||
dec edi ; point at null terminator
|
||||
|
||||
; Append decimal number targetVol
|
||||
invoke FormatNumber, targetVol, edi
|
||||
|
||||
; Send to MCI
|
||||
invoke mciSendStringA, OFFSET jboxVolCmdBuf, 0, 0, 0
|
||||
|
||||
jbox_audio_done:
|
||||
ret
|
||||
UpdateJukeboxAudio3D ENDP
|
||||
|
||||
; ==============================================================================
|
||||
; VOLUME CONTROL KEYS & POP-UP SLIDING HUD BAR
|
||||
; ==============================================================================
|
||||
|
||||
HandleJukeboxKeys3D PROC
|
||||
; '+' key: VK_OEM_PLUS (0BBh) or VK_ADD (6Bh - numpad +)
|
||||
invoke Pressed3D, 0BBh
|
||||
test eax, eax
|
||||
jnz jbox_do_plus
|
||||
invoke Pressed3D, 6Bh
|
||||
test eax, eax
|
||||
jz jbox_check_minus
|
||||
jbox_do_plus:
|
||||
cmp jboxUserVolume, 10
|
||||
jae @F
|
||||
inc jboxUserVolume
|
||||
@@:
|
||||
mov jboxHudTimer, 90 ; Show HUD for ~1.5s
|
||||
call UpdateJukeboxAudio3D
|
||||
ret
|
||||
|
||||
jbox_check_minus:
|
||||
; '-' key: VK_OEM_MINUS (0BDh) or VK_SUBTRACT (6Dh - numpad -)
|
||||
invoke Pressed3D, 0BDh
|
||||
test eax, eax
|
||||
jnz jbox_do_minus
|
||||
invoke Pressed3D, 6Dh
|
||||
test eax, eax
|
||||
jz jbox_keys_done
|
||||
jbox_do_minus:
|
||||
cmp jboxUserVolume, 0
|
||||
jbe @F
|
||||
dec jboxUserVolume
|
||||
@@:
|
||||
mov jboxHudTimer, 90 ; Show HUD for ~1.5s
|
||||
call UpdateJukeboxAudio3D
|
||||
|
||||
jbox_keys_done:
|
||||
ret
|
||||
HandleJukeboxKeys3D ENDP
|
||||
|
||||
RenderJukeboxVolumeHUD PROC uses ebx esi edi
|
||||
local winX:DWORD, winY:DWORD, barX:DWORD, barY:DWORD, barW:DWORD, barH:DWORD
|
||||
local numBuf[16]:BYTE
|
||||
|
||||
; 1. Update Timer and Animation Position
|
||||
cmp jboxHudTimer, 0
|
||||
je hud_sliding_down
|
||||
|
||||
; Active: decrement timer
|
||||
dec jboxHudTimer
|
||||
; Slide UP towards target Y = 206
|
||||
cmp jboxHudY, 206
|
||||
jbe hud_at_target
|
||||
sub jboxHudY, 4
|
||||
cmp jboxHudY, 206
|
||||
jae hud_at_target
|
||||
mov jboxHudY, 206
|
||||
hud_at_target:
|
||||
jmp hud_draw
|
||||
|
||||
hud_sliding_down:
|
||||
; Timer expired: slide DOWN towards 240 (offscreen)
|
||||
cmp jboxHudY, 240
|
||||
jae hud_hidden
|
||||
add jboxHudY, 3
|
||||
cmp jboxHudY, 240
|
||||
jbe hud_draw
|
||||
mov jboxHudY, 240
|
||||
hud_hidden:
|
||||
ret
|
||||
|
||||
hud_draw:
|
||||
mov eax, jboxHudY
|
||||
mov winY, eax
|
||||
mov winX, 72 ; Centered in 320: width 176
|
||||
|
||||
; 2. Background and Frame
|
||||
; Outer dark shadow (178 x 30)
|
||||
mov eax, winX
|
||||
dec eax
|
||||
mov ecx, winY
|
||||
dec ecx
|
||||
invoke DrawBox, eax, ecx, 178, 30, 0008100Ch
|
||||
|
||||
; Outer bezel (176 x 28)
|
||||
invoke DrawBox, winX, winY, 176, 28, 001C2E24h
|
||||
|
||||
; Inner panel body (174 x 26)
|
||||
mov eax, winX
|
||||
inc eax
|
||||
mov ecx, winY
|
||||
inc ecx
|
||||
invoke DrawBox, eax, ecx, 174, 26, 00101A14h
|
||||
|
||||
; Brass top trim accent (174 x 1)
|
||||
mov eax, winX
|
||||
inc eax
|
||||
mov ecx, winY
|
||||
inc ecx
|
||||
invoke DrawBox, eax, ecx, 174, 1, 008A6B34h
|
||||
|
||||
; 3. Title text: "MUZ. AVTOMAT: " + percentage
|
||||
mov eax, winX
|
||||
add eax, 10
|
||||
mov ecx, winY
|
||||
add ecx, 4
|
||||
invoke DrawString8x8, eax, ecx, OFFSET jboxHudTitle, 0050FF90h
|
||||
|
||||
; Draw percentage or "VYKL"
|
||||
mov eax, winX
|
||||
add eax, 126
|
||||
mov ecx, winY
|
||||
add ecx, 4
|
||||
cmp jboxUserVolume, 0
|
||||
jne hud_draw_pct_num
|
||||
invoke DrawString8x8, eax, ecx, OFFSET jboxHudMute, 008CB8A5h
|
||||
jmp hud_draw_trough
|
||||
|
||||
hud_draw_pct_num:
|
||||
push eax
|
||||
push ecx
|
||||
mov edx, jboxUserVolume
|
||||
imul edx, 10
|
||||
lea edi, numBuf
|
||||
invoke FormatNumber, edx, edi
|
||||
hud_find_term:
|
||||
cmp byte ptr [edi], 0
|
||||
je hud_append_pct
|
||||
inc edi
|
||||
jmp hud_find_term
|
||||
hud_append_pct:
|
||||
mov byte ptr [edi], '%'
|
||||
mov byte ptr [edi+1], 0
|
||||
pop ecx
|
||||
pop eax
|
||||
lea edx, numBuf
|
||||
invoke DrawString8x8, eax, ecx, edx, 00F0E6C3h
|
||||
|
||||
hud_draw_trough:
|
||||
; Progress trough at barX = winX + 24, barY = winY + 15, barW = 128, barH = 7
|
||||
mov eax, winX
|
||||
add eax, 24
|
||||
mov barX, eax
|
||||
mov ecx, winY
|
||||
add ecx, 15
|
||||
mov barY, ecx
|
||||
mov barW, 128
|
||||
mov barH, 7
|
||||
|
||||
; Trough border
|
||||
mov eax, barX
|
||||
dec eax
|
||||
mov ecx, barY
|
||||
dec ecx
|
||||
invoke DrawBox, eax, ecx, 130, 9, 00223828h
|
||||
invoke DrawBox, barX, barY, 128, 7, 000C1610h
|
||||
|
||||
; Draw 10 blocks: i = 0..9
|
||||
xor esi, esi
|
||||
hud_blocks_loop:
|
||||
mov eax, barX
|
||||
add eax, 4
|
||||
mov edx, esi
|
||||
imul edx, 12
|
||||
add eax, edx ; blockX = barX + 4 + i*12
|
||||
|
||||
mov ecx, barY
|
||||
inc ecx ; blockY = barY + 1
|
||||
|
||||
cmp esi, jboxUserVolume
|
||||
jae hud_block_empty
|
||||
|
||||
; Filled block color gradient
|
||||
cmp esi, 7
|
||||
jb hud_col_green
|
||||
cmp esi, 9
|
||||
jb hud_col_gold
|
||||
mov edx, 00465AFFh ; Red/orange accent for 100%
|
||||
jmp hud_draw_block_rect
|
||||
hud_col_green:
|
||||
mov edx, 0050FF90h ; Phosphor green
|
||||
jmp hud_draw_block_rect
|
||||
hud_col_gold:
|
||||
mov edx, 00FFD700h ; Golden amber
|
||||
jmp hud_draw_block_rect
|
||||
|
||||
hud_block_empty:
|
||||
mov edx, 0018261Eh ; Dim background
|
||||
|
||||
hud_draw_block_rect:
|
||||
invoke DrawBox, eax, ecx, 10, 5, edx
|
||||
|
||||
inc esi
|
||||
cmp esi, 10
|
||||
jb hud_blocks_loop
|
||||
|
||||
; Draw '-' and '+' labels
|
||||
mov eax, winX
|
||||
add eax, 8
|
||||
mov ecx, winY
|
||||
add ecx, 15
|
||||
invoke DrawString8x8, eax, ecx, OFFSET jboxHudMinus, 008CB8A5h
|
||||
|
||||
mov eax, winX
|
||||
add eax, 158
|
||||
mov ecx, winY
|
||||
add ecx, 15
|
||||
invoke DrawString8x8, eax, ecx, OFFSET jboxHudPlus, 008CB8A5h
|
||||
|
||||
ret
|
||||
RenderJukeboxVolumeHUD ENDP
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ StopJukeboxTrack3D PROTO
|
|||
BeginJackbox3D PROTO
|
||||
HandleJackbox3D PROTO
|
||||
RenderJackbox3D PROTO
|
||||
CalculateJukeboxFalloff PROTO
|
||||
UpdateJukeboxAudio3D PROTO
|
||||
HandleJukeboxKeys3D PROTO
|
||||
RenderJukeboxVolumeHUD PROTO
|
||||
|
||||
.data
|
||||
jackboxWorldArt3D AnimPack3D <>
|
||||
|
|
@ -37,9 +41,25 @@ jboxCurrentTrack dd -1
|
|||
jboxSelectedTrack dd 0
|
||||
jboxIsPlaying dd 0
|
||||
|
||||
; Volume control & 3D sound state
|
||||
jboxUserVolume dd 8
|
||||
jboxEffectiveVolume dd -1
|
||||
jboxHudTimer dd 0
|
||||
jboxHudY dd 240
|
||||
|
||||
jboxCloseCmd db "close jboxmusic",0
|
||||
jboxStopCmd db "stop jboxmusic",0
|
||||
jboxPlayCmd db "play jboxmusic repeat",0
|
||||
jboxVolCmdPrefix db "setaudio jboxmusic volume to ",0
|
||||
jboxVolCmdBuf db 64 dup(0)
|
||||
|
||||
; Popup HUD labels in CP1251:
|
||||
; "MUZ. AVTOMAT: "
|
||||
jboxHudTitle db 204,211,199,46,32,192,194,210,206,204,192,210,58,32,0
|
||||
; "VYKL"
|
||||
jboxHudMute db 194,251,234,235,0
|
||||
jboxHudMinus db "-",0
|
||||
jboxHudPlus db "+",0
|
||||
|
||||
jboxOpen0 db 'open "assets\music\jackbox\BYBOLDEN. - Art Deco.mp3" type mpegvideo alias jboxmusic',0
|
||||
jboxOpen1 db 'open "assets\music\jackbox\BYBOLDEN. - Soft Hours.mp3" type mpegvideo alias jboxmusic',0
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ def test_code_structure():
|
|||
"LoadJackboxArt3D", "FreeJackboxArt3D", "ResolveJackboxSurface3D",
|
||||
"DrawJackboxCabinet3D", "RenderJackboxCabinet3D", "JackboxCanWalk3D",
|
||||
"PlayJukeboxTrack3D", "StopJukeboxTrack3D", "BeginJackbox3D",
|
||||
"HandleJackbox3D", "RenderJackbox3D"
|
||||
"HandleJackbox3D", "RenderJackbox3D",
|
||||
"CalculateJukeboxFalloff", "UpdateJukeboxAudio3D",
|
||||
"HandleJukeboxKeys3D", "RenderJukeboxVolumeHUD"
|
||||
]
|
||||
for p in procs:
|
||||
assert f"{p} PROC" in code_inc, f"Missing proc: {p}"
|
||||
|
|
@ -86,6 +88,11 @@ def test_code_structure():
|
|||
assert "MODE_JACKBOX" in casino_inc
|
||||
assert "HandleJackbox3D" in casino_inc
|
||||
assert "RenderJackbox3D" in casino_inc
|
||||
assert "call HandleJukeboxKeys3D" in casino_inc
|
||||
assert "call UpdateJukeboxAudio3D" in casino_inc
|
||||
assert "call RenderJukeboxVolumeHUD" in casino_inc
|
||||
assert "jboxUserVolume dd" in data_inc
|
||||
assert "setaudio jboxmusic volume to" in data_inc
|
||||
|
||||
assert "call LoadJackboxArt3D" in world_inc
|
||||
assert "call FreeJackboxArt3D" in world_inc
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue