Specimen · bouncing-balls.ptl
Bouncing Balls
Gravity, elastic walls, and persistent state. Click the canvas to fling more.
compiling petal…
this sketch is interactive — click the canvas and use the mouse / arrow keys to play.
Source
1// Bouncing Balls — click to add more balls.2// Demonstrates state, frame timing, mouse input, and the drawing API.3 4state balls = []5 6let sw = float(screen_width())7let sh = float(screen_height())8let delta = dt()9 10// Seed with a few balls on first frame11if len(balls) == 0 then12 for i in range(0, 12) do13 let f = float(i)14 push(balls, {15 x: 50.0 + f * 60.0,16 y: 80.0 + f * 20.0,17 vx: 80.0 + f * 15.0,18 vy: 40.0 - f * 8.0,19 r: 12.0 + f * 1.5,20 cr: 80 + (i * 23) % 175,21 cg: 120 + (i * 47) % 135,22 cb: 200 - (i * 31) % 15023 })24 end25end26 27// Add a ball on click28if mouse_pressed(1) then29 let mx = float(mouse_x())30 let my = float(mouse_y())31 push(balls, {32 x: mx, y: my,33 vx: random(-200.0, 200.0),34 vy: random(-200.0, 0.0),35 r: random(8.0, 28.0),36 cr: int(random(80.0, 255.0)),37 cg: int(random(80.0, 255.0)),38 cb: int(random(80.0, 255.0))39 })40end41 42let gravity = 600.043 44// Physics step45let new_balls = []46for b in balls do47 let nvy = b.vy + gravity * delta48 let nx = b.x + b.vx * delta49 let ny = b.y + nvy * delta50 let nvx = b.vx51 52 // Wall collisions53 let final_vx = nvx54 let final_x = nx55 if nx - b.r < 0.0 then56 final_x = b.r57 final_vx = -nvx * 0.8558 end59 if nx + b.r > sw then60 final_x = sw - b.r61 final_vx = -nvx * 0.8562 end63 64 let final_vy = nvy65 let final_y = ny66 if ny + b.r > sh then67 final_y = sh - b.r68 final_vy = -nvy * 0.8569 end70 if ny - b.r < 0.0 then71 final_y = b.r72 final_vy = -nvy * 0.8573 end74 75 push(new_balls, {76 x: final_x, y: final_y,77 vx: final_vx, vy: final_vy,78 r: b.r, cr: b.cr, cg: b.cg, cb: b.cb79 })80end81balls = new_balls82 83// === Drawing ===84clear(14, 16, 28)85 86for b in balls do87 // soft outer halo88 draw_circle(int(b.x), int(b.y), int(b.r + 3.0), b.cr / 4, b.cg / 4, b.cb / 4)89 draw_circle(int(b.x), int(b.y), int(b.r), b.cr, b.cg, b.cb)90 draw_circle(int(b.x - b.r * 0.3), int(b.y - b.r * 0.3), int(b.r * 0.35),91 min(255, b.cr + 60), min(255, b.cg + 60), min(255, b.cb + 60))92end93 94draw_text("Bouncing Balls — click to add", 16, 12, 14, 200, 200, 220)95draw_text("count: " ++ str(len(balls)), 16, 32, 12, 150, 150, 180)The whole program is the source above — there is no hidden runtime. Petal re-runs it every frame: state values persist between frames, draw calls paint to the canvas, and edits take effect live. Open it in the playground to poke at the numbers and watch the picture change.