| 1 | @[has_globals] |
| 2 | module main |
| 3 | |
| 4 | import gg |
| 5 | import rand |
| 6 | |
| 7 | __global app = App{} |
| 8 | |
| 9 | struct Ball { |
| 10 | mut: |
| 11 | x f32 |
| 12 | y f32 |
| 13 | dx f32 |
| 14 | dy f32 |
| 15 | color gg.Color |
| 16 | } |
| 17 | |
| 18 | struct App { |
| 19 | mut: |
| 20 | size gg.Size = gg.Size{1024, 768} |
| 21 | balls []Ball |
| 22 | } |
| 23 | |
| 24 | fn main() { |
| 25 | init_app() |
| 26 | gg.start( |
| 27 | window_title: 'Bouncing balls' |
| 28 | width: app.size.width |
| 29 | height: app.size.height |
| 30 | frame_fn: on_frame |
| 31 | ) |
| 32 | } |
| 33 | |
| 34 | fn on_frame(ctx &gg.Context) { |
| 35 | app.size = gg.window_size() |
| 36 | if ctx.frame % 20000 == 0 { |
| 37 | init_app() |
| 38 | } |
| 39 | for mut ball in app.balls { |
| 40 | move_ball(mut ball) |
| 41 | } |
| 42 | ctx.begin() |
| 43 | for ball in app.balls { |
| 44 | ctx.draw_circle_filled(ball.x, app.size.height - ball.y, 6, ball.color) |
| 45 | } |
| 46 | ctx.draw_text(10, 20, 'Frame: ${ctx.frame:06}', color: gg.Color{255, 255, 255, 255}, size: 20) |
| 47 | ctx.end() |
| 48 | } |
| 49 | |
| 50 | fn init_app() { |
| 51 | app.balls.clear() |
| 52 | for _ in 0 .. 2500 { |
| 53 | app.balls << Ball{ |
| 54 | x: rand.f32() * app.size.width |
| 55 | y: 3 * app.size.height / 4 |
| 56 | dx: 5 * rand.f32() |
| 57 | dy: 5 * rand.f32() |
| 58 | color: gg.Color{rand.u8(), rand.u8(), rand.u8(), 255} |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | @[inline] |
| 64 | fn move_ball(mut ball Ball) { |
| 65 | ball.x += ball.dx |
| 66 | ball.y += ball.dy |
| 67 | ball.dy -= 9.81 * 0.01 |
| 68 | if ball.x <= 0 || ball.x >= app.size.width - 1 { |
| 69 | ball.dx = -ball.dx |
| 70 | apply_friction(mut ball) |
| 71 | } |
| 72 | if ball.y <= 0 || ball.y >= app.size.height - 1 { |
| 73 | ball.dy = -ball.dy |
| 74 | apply_friction(mut ball) |
| 75 | } |
| 76 | // apply some clipping: |
| 77 | ball.x = f32_max(-5, f32_min(f32(app.size.width) * 1.3, ball.x)) |
| 78 | ball.y = f32_max(-5, f32_min(f32(app.size.height) * 1.3, ball.y)) |
| 79 | ball.dx = f32_max(-50, f32_min(30, ball.dx)) |
| 80 | ball.dy = f32_max(-50, f32_min(30, ball.dy)) |
| 81 | } |
| 82 | |
| 83 | @[inline] |
| 84 | fn apply_friction(mut ball Ball) { |
| 85 | // apply some random friction on each bounce: |
| 86 | ball.dy *= (1 - rand.f32() * 0.1) |
| 87 | ball.dx *= (1 - rand.f32() * 0.01) |
| 88 | } |
| 89 | |