// Use `v -d show_fps run examples/gg/fire.v` to show a fire effect with an FPS counter. import gg import rand const win_width = 800 const win_height = 600 const width = 100 const height = 140 const scale = 4 const palette = [ gg.rgb(0x07, 0x07, 0x07), gg.rgb(0x1f, 0x07, 0x07), gg.rgb(0x2f, 0x0f, 0x07), gg.rgb(0x47, 0x0f, 0x07), gg.rgb(0x57, 0x17, 0x07), gg.rgb(0x67, 0x1f, 0x07), gg.rgb(0x77, 0x1f, 0x07), gg.rgb(0x8f, 0x27, 0x07), gg.rgb(0x9f, 0x2f, 0x07), gg.rgb(0xaf, 0x3f, 0x07), gg.rgb(0xbf, 0x47, 0x07), gg.rgb(0xc7, 0x47, 0x07), gg.rgb(0xdf, 0x4f, 0x07), gg.rgb(0xdf, 0x57, 0x07), gg.rgb(0xdf, 0x57, 0x07), gg.rgb(0xd7, 0x5f, 0x07), gg.rgb(0xd7, 0x5f, 0x07), gg.rgb(0xd7, 0x67, 0x0f), gg.rgb(0xcf, 0x6f, 0x0f), gg.rgb(0xcf, 0x77, 0x0f), gg.rgb(0xcf, 0x7f, 0x0f), gg.rgb(0xcf, 0x87, 0x17), gg.rgb(0xc7, 0x87, 0x17), gg.rgb(0xc7, 0x8f, 0x17), gg.rgb(0xc7, 0x97, 0x1f), gg.rgb(0xbf, 0x9f, 0x1f), gg.rgb(0xbf, 0x9f, 0x1f), gg.rgb(0xbf, 0xa7, 0x27), gg.rgb(0xbf, 0xa7, 0x27), gg.rgb(0xbf, 0xaf, 0x2f), gg.rgb(0xb7, 0xaf, 0x2f), gg.rgb(0xb7, 0xb7, 0x2f), gg.rgb(0xb7, 0xb7, 0x37), gg.rgb(0xcf, 0xcf, 0x6f), gg.rgb(0xdf, 0xdf, 0x9f), gg.rgb(0xef, 0xef, 0xc7), gg.rgb(0xff, 0xff, 0xff), ]! struct App { mut: gg &gg.Context = unsafe { nil } buf [][]int dying bool tiles int } fn main() { mut app := &App{ buf: [][]int{len: height - 1, init: []int{len: width}} } app.buf << []int{len: width, init: 36} // white fire base app.gg = gg.new_context( event_fn: event frame_fn: frame init_fn: retile window_title: 'Fire Animation' user_data: app bg_color: palette[0] width: win_width height: win_height ) app.gg.run() } fn retile(mut app App) { size := app.gg.window_size() app.tiles = size.width / (width * scale) + 1 } fn (mut app App) draw() { size := app.gg.window_size() for t in 0 .. app.tiles { app.gg.begin() for y, row in app.buf { for x, i in row { app.gg.draw_square_filled(t * width * scale + x * scale, (size.height - height * scale) + y * scale, scale, palette[i]) } } app.gg.end( how: if t == 0 { .clear } else { .passthru } ) // one pass per tile to avoid sgl vertex limit } } @[direct_array_access] fn (mut app App) tick() { for x in 0 .. width { for y in 1 .. height { if app.buf[y][x] > 0 { r := rand.intn(4) or { panic('failed to generate random number') } xn := ((x - r + 1) % width + width) % width app.buf[y - 1][xn] = app.buf[y][x] - r % 2 } else { app.buf[y - 1][x] = 0 } } } if app.dying { for x in 0 .. width { y := height - 1 app.buf[y][x] -= rand.intn(4) or { panic('failed to generate random number') } if app.buf[y][x] < 0 { app.buf[y][x] = 0 } } } } fn event(event &gg.Event, mut app App) { match event.typ { .key_up { match event.key_code { .space { if app.dying { app.dying = false app.buf[height - 1] = []int{len: width, init: 36} } else { app.dying = true } } else {} } } .resized { retile(mut app) } else {} } } fn frame(mut app App) { app.draw() app.tick() }