| 1 | // Copyright(C) 2019 Lars Pontoppidan. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license file distributed with this software package |
| 3 | module particle |
| 4 | |
| 5 | import math.vec |
| 6 | import rand |
| 7 | import sokol.sgl |
| 8 | |
| 9 | pub struct SystemConfig { |
| 10 | pub: |
| 11 | pool int |
| 12 | } |
| 13 | |
| 14 | pub struct System { |
| 15 | pub: |
| 16 | width int |
| 17 | height int |
| 18 | mut: |
| 19 | pool []&Particle |
| 20 | bin []&Particle |
| 21 | } |
| 22 | |
| 23 | pub fn (mut s System) init(sc SystemConfig) { |
| 24 | unsafe { s.pool.flags.set(.noslices | .noshrink) } |
| 25 | unsafe { s.bin.flags.set(.noslices | .noshrink) } |
| 26 | for i := 0; i < sc.pool; i++ { |
| 27 | p := new(vec.Vec2[f64]{f32(s.width) * 0.5, f32(s.height) * 0.5}) |
| 28 | s.bin << p |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | pub fn (mut s System) update(dt f64) { |
| 33 | mut p := &Particle(unsafe { nil }) |
| 34 | mut moved := 0 |
| 35 | for i := 0; i < s.pool.len; i++ { |
| 36 | p = s.pool[i] |
| 37 | p.update(dt) |
| 38 | if p.is_dead() { |
| 39 | s.bin << p |
| 40 | s.pool.delete(i) |
| 41 | moved++ |
| 42 | } |
| 43 | } |
| 44 | if moved != 0 { |
| 45 | $if trace_moves_spool_to_sbin ? { |
| 46 | eprintln('${moved:4} particles s.pool -> s.bin') |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | pub fn (s System) draw() { |
| 52 | sgl.begin_quads() |
| 53 | for p in s.pool { |
| 54 | p.draw() |
| 55 | } |
| 56 | sgl.end() |
| 57 | } |
| 58 | |
| 59 | pub fn (mut s System) reset() { |
| 60 | for i in 0 .. s.pool.len { |
| 61 | mut p := s.pool[i] |
| 62 | p.reset() |
| 63 | p.life_time = 0 |
| 64 | } |
| 65 | for i in 0 .. s.bin.len { |
| 66 | mut p := s.pool[i] |
| 67 | p.reset() |
| 68 | p.life_time = 0 |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | pub fn (mut s System) explode(x f32, y f32) { |
| 73 | mut reserve := 500 |
| 74 | center := vec.Vec2[f64]{x, y} |
| 75 | mut p := &Particle(unsafe { nil }) |
| 76 | mut moved := 0 |
| 77 | for i := 0; i < s.bin.len && reserve > 0; i++ { |
| 78 | p = s.bin[i] |
| 79 | p.reset() |
| 80 | p.location.from(center) |
| 81 | p.acceleration = vec.Vec2[f64]{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5, 0.5) or { |
| 82 | -0.5 |
| 83 | }} |
| 84 | p.velocity = vec.Vec2[f64]{rand.f32_in_range(-0.5, 0.5) or { -0.5 }, rand.f32_in_range(-0.5, 0.5) or { |
| 85 | -0.5 |
| 86 | }} |
| 87 | p.life_time = rand.f64_in_range(500, 2000) or { 500 } |
| 88 | s.pool << p |
| 89 | s.bin.delete(i) |
| 90 | moved++ |
| 91 | reserve-- |
| 92 | } |
| 93 | if moved != 0 { |
| 94 | $if trace_moves_sbin_to_spool ? { |
| 95 | eprintln('${moved:4} particles s.bin -> s.pool') |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | pub fn (mut s System) free() { |
| 101 | for p in s.pool { |
| 102 | if unsafe { p == 0 } { |
| 103 | print(ptr_str(p) + ' ouch') |
| 104 | continue |
| 105 | } |
| 106 | unsafe { free(p) } |
| 107 | } |
| 108 | s.pool.clear() |
| 109 | for p in s.bin { |
| 110 | if unsafe { p == 0 } { |
| 111 | print(ptr_str(p) + ' ouch') |
| 112 | continue |
| 113 | } |
| 114 | unsafe { |
| 115 | // println('Freeing from bin') |
| 116 | free(p) |
| 117 | } |
| 118 | } |
| 119 | s.bin.clear() |
| 120 | } |
| 121 | |