Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,178 @@
|
||||
// Creates the digital rain effect from the movie, "The Matrix"
|
||||
module main
|
||||
|
||||
import gg
|
||||
import rand
|
||||
import time
|
||||
|
||||
const font_size = 20
|
||||
const rain_drops = '0123456789!@#$%^&*()-=+[]{}|;:<>?~bdjpqtvz'.bytes()
|
||||
|
||||
struct App {
|
||||
mut:
|
||||
ctx &gg.Context = unsafe { nil }
|
||||
rows int
|
||||
cols int
|
||||
char_width int
|
||||
char_height int
|
||||
screen_size gg.Size
|
||||
should_calc bool = true
|
||||
rain_columns []RainColumn
|
||||
delay time.Duration = time.millisecond * 100
|
||||
}
|
||||
|
||||
struct RainColumn {
|
||||
mut:
|
||||
col int // character based postion
|
||||
len int // length of the rain column in characters
|
||||
head int // y position of the rain column
|
||||
drops []u8 // no retained graphics in gg, store entire column
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut app := &App{}
|
||||
rain(mut app)
|
||||
}
|
||||
|
||||
fn rain(mut app App) {
|
||||
app.ctx = gg.new_context(
|
||||
bg_color: gg.rgb(0, 0, 0)
|
||||
width: app.screen_size.width
|
||||
height: app.screen_size.height
|
||||
user_data: app
|
||||
window_title: 'Digital Rain'
|
||||
init_fn: fn (mut app App) {
|
||||
gg.toggle_fullscreen()
|
||||
}
|
||||
event_fn: fn (event &gg.Event, mut app App) {
|
||||
vprintln('event.typ: ${event.typ} | event.char_code: ${event.char_code}')
|
||||
if event.typ == .resized {
|
||||
app.should_calc = true
|
||||
return
|
||||
}
|
||||
if event.typ == .char && event.char_code == `f` {
|
||||
gg.toggle_fullscreen()
|
||||
return
|
||||
}
|
||||
if event.typ == .key_up && event.key_code == .up {
|
||||
app.delay = app.delay + 50 * time.millisecond
|
||||
}
|
||||
if event.typ == .key_up && event.key_code == .down {
|
||||
new_delay := app.delay - 50 * time.millisecond
|
||||
app.delay = if new_delay > 0 { new_delay } else { 0 }
|
||||
}
|
||||
}
|
||||
frame_fn: frame
|
||||
)
|
||||
app.ctx.run()
|
||||
}
|
||||
|
||||
fn frame(mut app App) {
|
||||
app.ctx.begin()
|
||||
if app.should_calc {
|
||||
app.should_calc = false
|
||||
calc_sizes(mut app)
|
||||
}
|
||||
// gradually add rain columns
|
||||
if app.rain_columns.len < app.cols / 4 * 3 {
|
||||
app.rain_columns << random_rain_column(app.cols, app.rows)
|
||||
}
|
||||
// update and print all rain columns
|
||||
for mut rc in app.rain_columns {
|
||||
update_rain_column(mut rc, app.cols, app.rows)
|
||||
draw_rain_column(rc, app)
|
||||
}
|
||||
app.ctx.draw_text(app.screen_size.width / 2 - 190, app.screen_size.height - 15,
|
||||
'press `f` to toggle fullscreen, Up/Down arrows to change speed',
|
||||
color: gg.gray
|
||||
)
|
||||
app.ctx.end()
|
||||
vprintln('frame: ${app.ctx.frame} | app.cols: ${app.cols} | app.rows: ${app.rows} | app.rain_columns.len: ${app.rain_columns.len} | app.delay: ${app.delay}')
|
||||
time.sleep(app.delay)
|
||||
}
|
||||
|
||||
@[if verbose ?]
|
||||
fn vprintln(msg string) {
|
||||
println(msg)
|
||||
}
|
||||
|
||||
fn calc_sizes(mut app App) {
|
||||
app.screen_size = gg.window_size()
|
||||
app.ctx.set_text_cfg(gg.TextCfg{
|
||||
size: font_size
|
||||
color: gg.green
|
||||
mono: true
|
||||
})
|
||||
// figure out how big character is in pixels
|
||||
// Pad it or it looks too squashed
|
||||
app.char_width, app.char_height = app.ctx.text_size('M')
|
||||
app.char_width += 3
|
||||
app.char_height += 1
|
||||
// determine the size of the matrix in rows and columns
|
||||
app.cols = app.screen_size.width / app.char_width
|
||||
app.rows = app.screen_size.height / app.char_height
|
||||
vprintln('app.cols: ${app.cols} | app.rows: ${app.rows}')
|
||||
}
|
||||
|
||||
fn update_rain_column(mut rc RainColumn, width int, height int) {
|
||||
rc.head += 1
|
||||
if rc.head > height + rc.len {
|
||||
rc = random_rain_column(width, height)
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_rain_column(rc RainColumn, app App) {
|
||||
mut y := 0
|
||||
x := rc.col * app.char_width
|
||||
end := rc.head - rc.len
|
||||
for i in 0 .. app.rows - 1 {
|
||||
if i >= end && i < rc.head {
|
||||
alpha := match i - end {
|
||||
0 { u8(75) }
|
||||
1 { u8(100) }
|
||||
2 { u8(125) }
|
||||
3 { u8(150) }
|
||||
4 { u8(175) }
|
||||
5 { u8(200) }
|
||||
6 { u8(225) }
|
||||
else { u8(255) }
|
||||
}
|
||||
|
||||
at_head := i == rc.head - 1
|
||||
cfg := gg.TextCfg{
|
||||
size: font_size
|
||||
color: gg.Color{
|
||||
r: if at_head { u8(255) } else { 0 }
|
||||
g: 255
|
||||
b: if at_head { u8(255) } else { 0 }
|
||||
a: alpha
|
||||
}
|
||||
mono: true
|
||||
}
|
||||
if i < rc.drops.len {
|
||||
app.ctx.draw_text(x, y, rc.drops[i].ascii_str(), cfg)
|
||||
app.ctx.draw_text(x, y, rc.drops[(i + 10) % rc.drops.len].ascii_str(), cfg)
|
||||
} else {
|
||||
vprintln('BAD i: ${i} | rc.drops.len: ${rc.drops.len}')
|
||||
}
|
||||
}
|
||||
y += app.char_height
|
||||
}
|
||||
}
|
||||
|
||||
fn random_rain_column(max_col int, max_height int) RainColumn {
|
||||
min_len := 6
|
||||
mut rc := RainColumn{
|
||||
col: rand.int_in_range(0, max_col) or { 0 }
|
||||
len: rand.int_in_range(min_len, max_height / 4 * 3) or { min_len }
|
||||
drops: []u8{cap: max_height}
|
||||
}
|
||||
for _ in 0 .. max_height {
|
||||
rc.drops << random_rain_drop()
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
fn random_rain_drop() u8 {
|
||||
return rand.element(rain_drops) or { rain_drops[0] }
|
||||
}
|
||||
Reference in new issue
Block a user