v2 / examples / gg / fire.v
149 lines · 139 sloc · 3.09 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1// Use `v -d show_fps run examples/gg/fire.v` to show a fire effect with an FPS counter.
2import gg
3import rand
4
5const win_width = 800
6const win_height = 600
7const width = 100
8const height = 140
9const scale = 4
10const palette = [
11 gg.rgb(0x07, 0x07, 0x07),
12 gg.rgb(0x1f, 0x07, 0x07),
13 gg.rgb(0x2f, 0x0f, 0x07),
14 gg.rgb(0x47, 0x0f, 0x07),
15 gg.rgb(0x57, 0x17, 0x07),
16 gg.rgb(0x67, 0x1f, 0x07),
17 gg.rgb(0x77, 0x1f, 0x07),
18 gg.rgb(0x8f, 0x27, 0x07),
19 gg.rgb(0x9f, 0x2f, 0x07),
20 gg.rgb(0xaf, 0x3f, 0x07),
21 gg.rgb(0xbf, 0x47, 0x07),
22 gg.rgb(0xc7, 0x47, 0x07),
23 gg.rgb(0xdf, 0x4f, 0x07),
24 gg.rgb(0xdf, 0x57, 0x07),
25 gg.rgb(0xdf, 0x57, 0x07),
26 gg.rgb(0xd7, 0x5f, 0x07),
27 gg.rgb(0xd7, 0x5f, 0x07),
28 gg.rgb(0xd7, 0x67, 0x0f),
29 gg.rgb(0xcf, 0x6f, 0x0f),
30 gg.rgb(0xcf, 0x77, 0x0f),
31 gg.rgb(0xcf, 0x7f, 0x0f),
32 gg.rgb(0xcf, 0x87, 0x17),
33 gg.rgb(0xc7, 0x87, 0x17),
34 gg.rgb(0xc7, 0x8f, 0x17),
35 gg.rgb(0xc7, 0x97, 0x1f),
36 gg.rgb(0xbf, 0x9f, 0x1f),
37 gg.rgb(0xbf, 0x9f, 0x1f),
38 gg.rgb(0xbf, 0xa7, 0x27),
39 gg.rgb(0xbf, 0xa7, 0x27),
40 gg.rgb(0xbf, 0xaf, 0x2f),
41 gg.rgb(0xb7, 0xaf, 0x2f),
42 gg.rgb(0xb7, 0xb7, 0x2f),
43 gg.rgb(0xb7, 0xb7, 0x37),
44 gg.rgb(0xcf, 0xcf, 0x6f),
45 gg.rgb(0xdf, 0xdf, 0x9f),
46 gg.rgb(0xef, 0xef, 0xc7),
47 gg.rgb(0xff, 0xff, 0xff),
48]!
49
50struct App {
51mut:
52 gg &gg.Context = unsafe { nil }
53 buf [][]int
54 dying bool
55 tiles int
56}
57
58fn main() {
59 mut app := &App{
60 buf: [][]int{len: height - 1, init: []int{len: width}}
61 }
62 app.buf << []int{len: width, init: 36} // white fire base
63
64 app.gg = gg.new_context(
65 event_fn: event
66 frame_fn: frame
67 init_fn: retile
68 window_title: 'Fire Animation'
69 user_data: app
70 bg_color: palette[0]
71 width: win_width
72 height: win_height
73 )
74 app.gg.run()
75}
76
77fn retile(mut app App) {
78 size := app.gg.window_size()
79 app.tiles = size.width / (width * scale) + 1
80}
81
82fn (mut app App) draw() {
83 size := app.gg.window_size()
84 for t in 0 .. app.tiles {
85 app.gg.begin()
86 for y, row in app.buf {
87 for x, i in row {
88 app.gg.draw_square_filled(t * width * scale + x * scale,
89
90 (size.height - height * scale) + y * scale, scale, palette[i])
91 }
92 }
93 app.gg.end(
94 how: if t == 0 { .clear } else { .passthru }
95 )
96 // one pass per tile to avoid sgl vertex limit
97 }
98}
99
100@[direct_array_access]
101fn (mut app App) tick() {
102 for x in 0 .. width {
103 for y in 1 .. height {
104 if app.buf[y][x] > 0 {
105 r := rand.intn(4) or { panic('failed to generate random number') }
106 xn := ((x - r + 1) % width + width) % width
107 app.buf[y - 1][xn] = app.buf[y][x] - r % 2
108 } else {
109 app.buf[y - 1][x] = 0
110 }
111 }
112 }
113 if app.dying {
114 for x in 0 .. width {
115 y := height - 1
116 app.buf[y][x] -= rand.intn(4) or { panic('failed to generate random number') }
117 if app.buf[y][x] < 0 {
118 app.buf[y][x] = 0
119 }
120 }
121 }
122}
123
124fn event(event &gg.Event, mut app App) {
125 match event.typ {
126 .key_up {
127 match event.key_code {
128 .space {
129 if app.dying {
130 app.dying = false
131 app.buf[height - 1] = []int{len: width, init: 36}
132 } else {
133 app.dying = true
134 }
135 }
136 else {}
137 }
138 }
139 .resized {
140 retile(mut app)
141 }
142 else {}
143 }
144}
145
146fn frame(mut app App) {
147 app.draw()
148 app.tick()
149}
150