| 1 | module main |
| 2 | |
| 3 | import datatypes |
| 4 | import gg |
| 5 | import time |
| 6 | import math |
| 7 | import rand |
| 8 | |
| 9 | const win_width = 1340 |
| 10 | const win_height = 640 |
| 11 | const timer_period = 40 * time.millisecond // defaulted at 25 fps |
| 12 | |
| 13 | const font_small = gg.TextCfg{ |
| 14 | color: gg.black |
| 15 | size: 20 |
| 16 | } |
| 17 | |
| 18 | struct App { |
| 19 | mut: |
| 20 | gg &gg.Context |
| 21 | qt datatypes.Quadtree |
| 22 | players []datatypes.AABB |
| 23 | particles []Particle |
| 24 | retrieveds []datatypes.AABB |
| 25 | nodes []datatypes.Quadtree |
| 26 | width f64 = 1340 |
| 27 | height f64 = 640 |
| 28 | } |
| 29 | |
| 30 | struct Particle { |
| 31 | mut: |
| 32 | pmt datatypes.AABB |
| 33 | speed f64 |
| 34 | angle f64 |
| 35 | } |
| 36 | |
| 37 | fn (mut p Particle) update() { |
| 38 | p.pmt.x += p.speed * math.cos(p.angle * math.pi / 180) |
| 39 | p.pmt.y += p.speed * math.sin(p.angle * math.pi / 180) |
| 40 | |
| 41 | if p.pmt.x < 0 { |
| 42 | p.pmt.x = 0 |
| 43 | p.speed = -p.speed |
| 44 | p.angle = -p.angle |
| 45 | } |
| 46 | if p.pmt.x > 1340 { |
| 47 | p.pmt.x = 1340 |
| 48 | p.speed = -p.speed |
| 49 | p.angle = -p.angle |
| 50 | } |
| 51 | if p.pmt.y < 0 { |
| 52 | p.pmt.y = 0 |
| 53 | p.speed = -p.speed |
| 54 | p.angle = 180 - p.angle |
| 55 | } |
| 56 | if p.pmt.y > 640 { |
| 57 | p.pmt.y = 640 |
| 58 | p.speed = -p.speed |
| 59 | p.angle = 180 - p.angle |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | fn (mut app App) start() { |
| 64 | app.players << datatypes.AABB{1200 * rand.f64(), 500 * rand.f64(), 20, 20} |
| 65 | app.insert_particles() |
| 66 | for mut particle in app.particles { |
| 67 | particle.speed = 10 * rand.f64() |
| 68 | particle.angle = 200 * rand.f64() |
| 69 | } |
| 70 | app.nodes << app.qt.get_nodes() |
| 71 | } |
| 72 | |
| 73 | fn (mut app App) update() { |
| 74 | app.qt.clear() |
| 75 | app.nodes = [] |
| 76 | for mut particle in app.particles { |
| 77 | particle.update() |
| 78 | app.qt.insert(particle.pmt) |
| 79 | } |
| 80 | app.find_particles() |
| 81 | app.nodes << app.qt.get_nodes() |
| 82 | } |
| 83 | |
| 84 | fn (mut app App) insert_particles() { |
| 85 | mut grid := 10.0 |
| 86 | mut gridh := app.qt.perimeter.width / grid |
| 87 | mut gridv := app.qt.perimeter.height / grid |
| 88 | num_particles := 100 |
| 89 | for _ in 0 .. num_particles { |
| 90 | mut x := rand_minmax(0, gridh) * grid |
| 91 | mut y := rand_minmax(0, gridv) * grid |
| 92 | mut random_particle := datatypes.AABB{ |
| 93 | x: x |
| 94 | y: y |
| 95 | width: rand_minmax(1, 4) * grid |
| 96 | height: rand_minmax(1, 4) * grid |
| 97 | } |
| 98 | app.particles << Particle{random_particle, 0.0, 0.0} |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | fn (mut app App) find_particles() { |
| 103 | app.retrieveds = [] |
| 104 | app.retrieveds << app.qt.retrieve(app.players[0]) |
| 105 | } |
| 106 | |
| 107 | fn main() { |
| 108 | mut app := &App{ |
| 109 | gg: unsafe { nil } |
| 110 | } |
| 111 | app.gg = gg.new_context( |
| 112 | bg_color: gg.white |
| 113 | width: win_width |
| 114 | height: win_height |
| 115 | create_window: true |
| 116 | window_title: 'Quadtree Demo' |
| 117 | frame_fn: frame |
| 118 | event_fn: on_event |
| 119 | user_data: app |
| 120 | ) |
| 121 | app.qt = app.qt.create(0, 0, 1340, 640, 8, 4, 0) |
| 122 | app.start() |
| 123 | spawn app.run() |
| 124 | app.gg.run() |
| 125 | } |
| 126 | |
| 127 | fn (mut app App) on_mouse_move(mouse_x f32, mouse_y f32) { |
| 128 | for mut player in app.players { |
| 129 | player.x = (mouse_x / gg.window_size_real_pixels().width) * 1340 |
| 130 | player.y = (mouse_y / gg.window_size_real_pixels().height) * 640 |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | fn on_event(mut e gg.Event, mut app App) { |
| 135 | match e.typ { |
| 136 | .mouse_move { app.on_mouse_move(e.mouse_x, e.mouse_y) } |
| 137 | else {} |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | fn (mut app App) run() { |
| 142 | for { |
| 143 | app.update() |
| 144 | time.sleep(timer_period) |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | fn frame(app &App) { |
| 149 | app.gg.begin() |
| 150 | app.draw() |
| 151 | app.gg.end() |
| 152 | } |
| 153 | |
| 154 | fn (app &App) display() { |
| 155 | for player in app.players { |
| 156 | app.gg.draw_rect_filled(f32(player.x), f32(player.y), f32(player.width), |
| 157 | f32(player.height), gg.black) |
| 158 | } |
| 159 | for particle in app.particles { |
| 160 | app.gg.draw_rect_empty(f32(particle.pmt.x), f32(particle.pmt.y), f32(particle.pmt.width), |
| 161 | f32(particle.pmt.height), gg.blue) |
| 162 | } |
| 163 | for node in app.nodes { |
| 164 | app.gg.draw_rect_empty(f32(node.perimeter.x), f32(node.perimeter.y), |
| 165 | f32(node.perimeter.width), f32(node.perimeter.height), gg.red) |
| 166 | } |
| 167 | for retrieved in app.retrieveds { |
| 168 | app.gg.draw_rect_filled(f32(retrieved.x + 1), f32(retrieved.y + 1), |
| 169 | f32(retrieved.width - 2), f32(retrieved.height - 2), gg.green) |
| 170 | } |
| 171 | app.gg.draw_text(1200, 25, 'Nodes: ${app.nodes.len}', font_small) |
| 172 | app.gg.draw_text(1200, 50, 'Particles: ${app.particles.len}', font_small) |
| 173 | } |
| 174 | |
| 175 | fn (app &App) draw() { |
| 176 | app.display() |
| 177 | } |
| 178 | |
| 179 | fn rand_minmax(min f64, max f64) f64 { |
| 180 | mut val := min + (rand.f64() * (max - min)) |
| 181 | return val |
| 182 | } |
| 183 | |