KAZIK/src_graphics/dice_animation.inc
Игорь Федосеев ca62db53e9 feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests
- Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects
- First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective
- City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation
- World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests
- Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
2026-10-16 12:37:40 +03:00

584 lines
13 KiB
PHP

; Moving cube geometry shares the existing 320x240 logical game canvas.
include src_graphics/dice_anchors.inc
.data
cubeCorners3D dd -32768,-32768,-32768, 32768,-32768,-32768
dd 32768,32768,-32768, -32768,32768,-32768
dd -32768,-32768,32768, 32768,-32768,32768
dd 32768,32768,32768, -32768,32768,32768
cubeFaces3D db 0,1,2,3, 4,7,6,5, 0,3,7,4
db 1,5,6,2, 0,4,5,1, 3,2,6,7
cubeTop3D dd 3,1,1,1,1,3
cubeRight3D dd 2,3,2,2,3,2
cubeColors3D dd 00FAF1DFh,00C9C1B0h,00D1C5AEh
dd 00DFD3BDh,00FFF9EAh,00B5AA98h
cubePips3D dd 32768,32768, 16384,16384, 49152,49152
dd 49152,16384, 16384,49152, 16384,32768, 49152,32768
cubeX3D dd 0
cubeY3D dd 0
cubeScale3D dd 36
cubeSinX3D dd 0
cubeCosX3D dd 65536
cubeSinY3D dd 0
cubeCosY3D dd 65536
cubeSinZ3D dd 0
cubeCosZ3D dd 65536
cubeVertices3D dd 16 dup(0)
cubeFaceValues3D dd 6 dup(0)
cubeQuad3D dd 8 dup(0)
cubeContactShadow3D dd 0
.code
; Fill clockwise triangles. Edges are incremented per pixel, avoiding divisions.
DrawTriangle3D PROC uses ebx esi edi x1:DWORD,y1:DWORD,x2:DWORD,y2:DWORD,x3:DWORD,y3:DWORD,tint:DWORD
local lowX:DWORD,highX:DWORD,lowY:DWORD,highY:DWORD
local dx0:DWORD,dy0:DWORD,dx1:DWORD,dy1:DWORD,dx2:DWORD,dy2:DWORD
local row0:DWORD,row1:DWORD,row2:DWORD,e0:DWORD,e1:DWORD,e2:DWORD
local py:DWORD,px:DWORD
mov eax, x2
sub eax, x1
mov dx0, eax
mov edx, y2
sub edx, y1
mov dy0, edx
mov ebx, x3
sub ebx, x1
imul ebx, edx
mov ecx, y3
sub ecx, y1
imul eax, ecx
sub eax, ebx
cmp eax, 0
jle triangle_done
mov eax, x3
sub eax, x2
mov dx1, eax
mov eax, y3
sub eax, y2
mov dy1, eax
mov eax, x1
sub eax, x3
mov dx2, eax
mov eax, y1
sub eax, y3
mov dy2, eax
mov eax, x1
mov ebx, eax
cmp eax, x2
jle @F
mov eax, x2
@@:
cmp eax, x3
jle @F
mov eax, x3
@@:
cmp eax, 0
jge @F
xor eax, eax
@@:
mov lowX, eax
cmp ebx, x2
jge @F
mov ebx, x2
@@:
cmp ebx, x3
jge @F
mov ebx, x3
@@:
cmp ebx, 319
jle @F
mov ebx, 319
@@:
mov highX, ebx
mov eax, y1
mov ebx, eax
cmp eax, y2
jle @F
mov eax, y2
@@:
cmp eax, y3
jle @F
mov eax, y3
@@:
cmp eax, 0
jge @F
xor eax, eax
@@:
mov lowY, eax
cmp ebx, y2
jge @F
mov ebx, y2
@@:
cmp ebx, y3
jge @F
mov ebx, y3
@@:
cmp ebx, 239
jle @F
mov ebx, 239
@@:
mov highY, ebx
mov eax, lowY
sub eax, y1
imul eax, dx0
mov edx, lowX
sub edx, x1
imul edx, dy0
sub eax, edx
mov row0, eax
mov eax, lowY
sub eax, y2
imul eax, dx1
mov edx, lowX
sub edx, x2
imul edx, dy1
sub eax, edx
mov row1, eax
mov eax, lowY
sub eax, y3
imul eax, dx2
mov edx, lowX
sub edx, x3
imul edx, dy2
sub eax, edx
mov row2, eax
mov eax, lowY
mov py, eax
triangle_row:
mov eax, py
cmp eax, highY
jg triangle_done
mov eax, row0
mov e0, eax
mov eax, row1
mov e1, eax
mov eax, row2
mov e2, eax
mov eax, lowX
mov px, eax
triangle_pixel:
mov eax, px
cmp eax, highX
jg triangle_next_row
mov eax, e0
or eax, e1
or eax, e2
js triangle_next_pixel
mov edi, py
imul edi, SCREEN_W * 2
mov eax, px
shl eax, 1
add edi, eax
mov eax, tint
mov screenBuffer[edi*4], eax
mov screenBuffer[edi*4+4], eax
mov screenBuffer[edi*4+SCREEN_W*4], eax
mov screenBuffer[edi*4+SCREEN_W*4+4], eax
triangle_next_pixel:
mov eax, dy0
sub e0, eax
mov eax, dy1
sub e1, eax
mov eax, dy2
sub e2, eax
inc px
jmp triangle_pixel
triangle_next_row:
mov eax, dx0
add row0, eax
mov eax, dx1
add row1, eax
mov eax, dx2
add row2, eax
inc py
jmp triangle_row
triangle_done:
ret
DrawTriangle3D ENDP
; Local 16.16 coordinates -> yaw, pitch, roll -> screen coordinates.
ProjectCubePoint3D PROC uses ebx esi edi nx:DWORD,ny:DWORD,nz:DWORD
local rx:DWORD,ry:DWORD,rz:DWORD
mov eax, nx
imul cubeCosY3D
shrd eax, edx, 16
mov ebx, eax
mov eax, nz
imul cubeSinY3D
shrd eax, edx, 16
add eax, ebx
mov rx, eax
mov eax, nz
imul cubeCosY3D
shrd eax, edx, 16
mov ebx, eax
mov eax, nx
imul cubeSinY3D
shrd eax, edx, 16
sub ebx, eax
mov rz, ebx
mov eax, ny
imul cubeCosX3D
shrd eax, edx, 16
mov ebx, eax
mov eax, rz
imul cubeSinX3D
shrd eax, edx, 16
sub ebx, eax
mov ry, ebx
mov eax, rx
imul cubeCosZ3D
shrd eax, edx, 16
mov ebx, eax
mov eax, ry
imul cubeSinZ3D
shrd eax, edx, 16
sub ebx, eax
imul ebx, cubeScale3D
sar ebx, 16
add ebx, cubeX3D
mov eax, rx
imul cubeSinZ3D
shrd eax, edx, 16
mov esi, eax
mov eax, ry
imul cubeCosZ3D
shrd eax, edx, 16
add eax, esi
imul eax, cubeScale3D
sar eax, 16
add eax, cubeY3D
mov edx, eax
mov eax, ebx
ret
ProjectCubePoint3D ENDP
DrawCubePip3D PROC uses ebx esi u:DWORD,v:DWORD,pipRadius:DWORD
mov eax, cubeQuad3D[8]
sub eax, cubeQuad3D
imul u
shrd eax, edx, 16
mov ebx, eax
mov eax, cubeQuad3D[24]
sub eax, cubeQuad3D
imul v
shrd eax, edx, 16
add ebx, eax
add ebx, cubeQuad3D
mov eax, cubeQuad3D[12]
sub eax, cubeQuad3D[4]
imul u
shrd eax, edx, 16
mov esi, eax
mov eax, cubeQuad3D[28]
sub eax, cubeQuad3D[4]
imul v
shrd eax, edx, 16
add esi, eax
add esi, cubeQuad3D[4]
invoke DrawCircle, ebx, esi, pipRadius, 00A31D25h
ret
DrawCubePip3D ENDP
DrawTumblingDie3D PROC uses ebx esi edi centerX:DWORD,centerY:DWORD,pitch:DWORD,yaw:DWORD,roll:DWORD,value:DWORD
local face:DWORD,pip:DWORD,pipRadius:DWORD,area:DWORD
mov eax, centerX
mov cubeX3D, eax
mov eax, centerY
mov cubeY3D, eax
mov eax, pitch
and eax, 511
mov edx, tableSin[eax*4]
mov cubeSinX3D, edx
mov edx, tableCos[eax*4]
mov cubeCosX3D, edx
mov eax, yaw
and eax, 511
mov edx, tableSin[eax*4]
mov cubeSinY3D, edx
mov edx, tableCos[eax*4]
mov cubeCosY3D, edx
mov eax, roll
and eax, 511
mov edx, tableSin[eax*4]
mov cubeSinZ3D, edx
mov edx, tableCos[eax*4]
mov cubeCosZ3D, edx
mov eax, value
mov cubeFaceValues3D[16], eax
mov edx, 7
sub edx, eax
mov cubeFaceValues3D[20], edx
dec eax
mov edx, cubeRight3D[eax*4]
mov cubeFaceValues3D[12], edx
mov ecx, 7
sub ecx, edx
mov cubeFaceValues3D[8], ecx
mov edx, cubeTop3D[eax*4]
mov cubeFaceValues3D, edx
mov ecx, 7
sub ecx, edx
mov cubeFaceValues3D[4], ecx
xor esi, esi
cube_project_loop:
imul edi, esi, 12
invoke ProjectCubePoint3D, cubeCorners3D[edi], cubeCorners3D[edi+4], cubeCorners3D[edi+8]
mov cubeVertices3D[esi*8], eax
mov cubeVertices3D[esi*8+4], edx
inc esi
cmp esi, 8
jb cube_project_loop
; A resting cube touches the cloth along its projected bottom face.
; Reverse the underside winding; the normal face pass culls it.
cmp cubeContactShadow3D,0
je cube_no_contact_shadow
mov eax,cubeVertices3D[28]
inc eax
mov ebx,cubeVertices3D[60]
inc ebx
mov edi,cubeVertices3D[52]
inc edi
invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[56],ebx,cubeVertices3D[48],edi,00153122h
mov eax,cubeVertices3D[28]
inc eax
mov ebx,cubeVertices3D[52]
inc ebx
mov edi,cubeVertices3D[20]
inc edi
invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[48],ebx,cubeVertices3D[16],edi,00153122h
cube_no_contact_shadow:
mov face, 0
cube_face_loop:
mov esi, face
xor edi, edi
cube_load_quad:
movzx eax, cubeFaces3D[esi*4+edi]
mov ebx, cubeVertices3D[eax*8]
mov cubeQuad3D[edi*8], ebx
mov ebx, cubeVertices3D[eax*8+4]
mov cubeQuad3D[edi*8+4], ebx
inc edi
cmp edi, 4
jb cube_load_quad
mov eax, cubeQuad3D[8]
sub eax, cubeQuad3D
mov edx, cubeQuad3D[28]
sub edx, cubeQuad3D[4]
imul eax, edx
mov ebx, cubeQuad3D[24]
sub ebx, cubeQuad3D
mov edx, cubeQuad3D[12]
sub edx, cubeQuad3D[4]
imul ebx, edx
sub eax, ebx
mov area, eax
cmp eax, 0
jle cube_next_face
mov ebx, cubeColors3D[esi*4]
invoke DrawTriangle3D, cubeQuad3D, cubeQuad3D[4], cubeQuad3D[8], cubeQuad3D[12], cubeQuad3D[16], cubeQuad3D[20], ebx
invoke DrawTriangle3D, cubeQuad3D, cubeQuad3D[4], cubeQuad3D[16], cubeQuad3D[20], cubeQuad3D[24], cubeQuad3D[28], ebx
cmp area, 70
jl cube_next_face
mov pipRadius, 1
cmp area, 450
jl @F
mov pipRadius, 2
@@:
mov ebx, cubeFaceValues3D[esi*4]
test ebx, 1
jz cube_corner_pips
invoke DrawCubePip3D, 32768, 32768, pipRadius
cube_corner_pips:
cmp ebx, 2
jl cube_next_face
invoke DrawCubePip3D, 16384, 16384, pipRadius
invoke DrawCubePip3D, 49152, 49152, pipRadius
cmp ebx, 4
jl cube_next_face
invoke DrawCubePip3D, 49152, 16384, pipRadius
invoke DrawCubePip3D, 16384, 49152, pipRadius
cmp ebx, 6
jl cube_next_face
invoke DrawCubePip3D, 16384, 32768, pipRadius
invoke DrawCubePip3D, 49152, 32768, pipRadius
cube_next_face:
inc face
cmp face, 6
jb cube_face_loop
ret
DrawTumblingDie3D ENDP
RenderDiceThrow3D PROC uses ebx esi edi
local t:DWORD,ground:DWORD,lift:DWORD,pitch:DWORD,yaw:DWORD,roll:DWORD
local cx1:DWORD,cx2:DWORD,cy:DWORD,cy2:DWORD,oldScale:DWORD,shadowAlpha:DWORD
; Held dice are painted into the cupped palm: no second pair over skin.
cmp diceArtReady3D,1
jne throw_begin
cmp dice3d_state,0
je throw_done
cmp dice3d_state,1
jne throw_begin
cmp dice3d_timer,240
jb throw_done
throw_begin:
mov eax,cubeScale3D
mov oldScale,eax
mov t,0
cmp dice3d_state,2
jne @F
mov t,1600
@@:
cmp dice3d_state, 1
jne throw_pose
mov eax, dice3d_timer
sub eax,240
jns @F
xor eax,eax
@@:
cmp eax,1360
jbe @F
mov eax,1360
@@:
imul eax,1600
xor edx,edx
mov ecx,1360
div ecx
mov t, eax
throw_pose:
mov cubeScale3D,12
mov eax,t
imul eax, DICE_RELEASE_Y1-146
xor edx, edx
mov ecx, 1600
div ecx
mov ebx, DICE_RELEASE_Y1
sub ebx, eax
mov ground, ebx
mov lift, 0
mov eax, t
cmp eax, 500
jae throw_bounce2
mov edx, 500
sub edx, eax
imul eax, edx
imul eax, 160
xor edx, edx
mov ecx, 250000
div ecx
mov lift, eax
jmp throw_position
throw_bounce2:
cmp eax, 950
jae throw_bounce3
sub eax, 500
mov edx, 450
sub edx, eax
imul eax, edx
imul eax, 56
xor edx, edx
mov ecx, 202500
div ecx
mov lift, eax
jmp throw_position
throw_bounce3:
cmp eax, 1300
jae throw_position
sub eax, 950
mov edx, 350
sub edx, eax
imul eax, edx
imul eax, 24
xor edx, edx
mov ecx, 122500
div ecx
mov lift, eax
throw_position:
mov eax, ground
sub eax, lift
mov cy, eax
mov eax, t
imul eax, DICE_RELEASE_X1-134
xor edx, edx
mov ecx, 1600
div ecx
mov ebx, DICE_RELEASE_X1
sub ebx, eax
mov cx1, ebx
mov eax,t
imul eax,DICE_RELEASE_X2-186
xor edx,edx
mov ecx,1600
div ecx
mov ebx,DICE_RELEASE_X2
sub ebx,eax
mov cx2,ebx
mov eax, 1600
sub eax, t
imul eax,eax
imul eax,1024
xor edx, edx
mov ecx,2560000
div ecx
mov esi,1024
sub esi,eax
mov roll,esi
mov eax,esi
add eax,70
mov pitch,eax
mov eax,esi
shr eax,1
add eax,44
mov yaw,eax
mov cubeContactShadow3D,0
cmp t,1600
jne @F
mov cubeContactShadow3D,1
@@:
mov eax,t
imul eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2
xor edx,edx
mov ecx,1600
div ecx
add eax,cy
sub eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2
mov cy2,eax
cmp dice3d_state,0
je throw_cubes
cmp dice3d_state,1
jne throw_shadows
cmp dice3d_timer,240
jb throw_cubes
throw_shadows:
cmp diceShadowPass3D,0
je throw_cubes
mov eax,85
sub eax,lift
mov shadowAlpha,eax
mov eax,cx1
shl eax,1
mov edx,cubeScale3D
shr edx,2
add edx,ground
shl edx,1
invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha
mov eax,cx2
shl eax,1
mov edx,cubeScale3D
shr edx,2
add edx,ground
shl edx,1
invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha
throw_cubes:
cmp diceShadowPass3D,0
jne throw_restore
invoke DrawTumblingDie3D, cx1, cy, pitch, yaw, roll, dice3d_val1
mov eax,roll
neg eax
invoke DrawTumblingDie3D, cx2, cy2, pitch, yaw, eax, dice3d_val2
throw_restore:
mov eax,oldScale
mov cubeScale3D,eax
mov cubeContactShadow3D,0
throw_done:
ret
RenderDiceThrow3D ENDP