format ELF64 initial_width = 800 initial_height = 450 FLAG_MSAA_4X_HINT = 32 struc splat x { dd x, x, x, x } struc Vec2 x,y { dd x, y, 0.0, 0.0 } struc Ball x, y, r { .pos Vec2 x, y .vel splat 0.0 .rad splat r } public _start extrn SetConfigFlags extrn InitWindow extrn SetTargetFPS extrn WindowShouldClose extrn GetMouseWheelMove extrn IsMouseButtonDown extrn GetMousePosition extrn GetScreenWidth extrn GetScreenHeight extrn BeginDrawing extrn EndDrawing extrn ClearBackground extrn DrawCircleV extrn _exit section '.text' executable _start: ; enable anti-aliasing mov edi, FLAG_MSAA_4X_HINT call SetConfigFlags ; initialise window mov edi, initial_width mov esi, initial_height mov rdx, title call InitWindow ; 60 fps mov edi, 60 call SetTargetFPS jmp loop_entr main_loop: ; change ball size call GetMouseWheelMove shufps xmm0, xmm0, 0x0 addps xmm0, [ball.rad] maxps xmm0, [minimum_radius] movlps [ball.rad], xmm0 ; check if lmb is pressed xor edi, edi call IsMouseButtonDown test eax, eax jz no_click ; accelerate ball towards mouse call GetMousePosition subps xmm0, [ball.pos] mulps xmm0, [mouse_seek_speed] jmp move_and_draw no_click: ; get width/height call GetScreenWidth mov ebx, eax call GetScreenHeight ; convert width/height to packed single precision floats cvtsi2ss xmm0, ebx cvtsi2ss xmm1, eax movlhps xmm0, xmm1 shufps xmm0, xmm0, 0x8 ; load ball position and radius movlps xmm1, [ball.pos] movlps xmm2, [ball.rad] ; calculate upper boundaries subps xmm0, xmm2 ; stash boundaries for later movaps xmm3, xmm2 movaps xmm4, xmm0 ; dirty, rotten, low-down, no-good hack cmpnleps xmm2, xmm1 ; out of left/top bounds mask cmpltps xmm0, xmm1 ; out of right/bottom bounds mask orps xmm0, xmm2 ; or the masks andps xmm0, [restitution_minus_one] ; mask & restitution coefficient minus one addps xmm0, [ones] ; add ones to create bounce vector (0.0 -> 1.0, restitution - 1.0 -> restitution) maxps xmm1, xmm3 minps xmm1, xmm4 ; keep position in bounds ; scale velocity by bounce vector mulps xmm0, [ball.vel] ; apply air resistance and gravity mulps xmm0, [air_resistance_coef] addps xmm0, [grav_accel] ; store position movlps [ball.pos], xmm1 move_and_draw: ; store velocity movlps [ball.vel], xmm0 ; move ball addps xmm0, [ball.pos] movlps [ball.pos], xmm0 ; draw frame call BeginDrawing ; black background xor edi, edi call ClearBackground ; sphere movlps xmm0, [ball.pos] movss xmm1, [ball.rad] mov rdi, 0xFF2C7500 ; green call DrawCircleV call EndDrawing loop_entr: call WindowShouldClose test eax, eax jz main_loop xor edi, edi call _exit section '.data' writable align 16 mouse_seek_speed splat 0.5 minimum_radius splat 2.5 air_resistance_coef splat 0.99 restitution_minus_one splat -1.8 ones splat 1.0 grav_accel Vec2 0.0, 0.69 ball Ball 400.0, 250.0, 25.0 title db 'ball simulator',0