RosettaCodeData/Task/Matrix-digital-rain/Julia/matrix-digital-rain.julia
2023-07-01 13:44:08 -04:00

81 lines
2.6 KiB
Text

using Gtk, Colors, Cairo
import Base.iterate, Base.IteratorSize, Base.IteratorEltype
const caps = [c for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
startfall() = rand() < 0.2
endfall() = rand() < 0.2
startblank() = rand() < 0.1
endblank() = rand() < 0.05
bechangingchar() = rand() < 0.03
struct RainChars chars::Vector{Char} end
Base.IteratorSize(s::RainChars) = Base.IsInfinite()
Base.IteratorEltype(s::RainChars) = Char
function Base.iterate(rain::RainChars, state = (true, false, 0))
c = '\0'
isfalling, isblank, blankcount = state
if isfalling # falling, so feed the column
if isblank
c = ' '
((blankcount += 1) > 12) && (isblank = endblank())
else
c = bechangingchar() ? '~' : rand(rain.chars)
isblank, blankcount = startblank(), 0
end
endfall() && (isfalling = false)
else
isfalling = startfall()
end
return c, (isfalling, isblank, blankcount)
end
function digitalrain()
mapwidth, mapheight, fontpointsize = 800, 450, 14
windowmaxx = div(mapwidth, Int(round(fontpointsize * 0.9)))
windowmaxy = div(mapheight, fontpointsize)
basebuffer = fill(' ', windowmaxy, windowmaxx)
bkcolor, rcolor, xcolor = colorant"black", colorant"green", colorant"limegreen"
columngenerators = [Iterators.Stateful(RainChars(caps)) for _ in 1:windowmaxx]
win = GtkWindow("Digital Rain Effect", mapwidth, mapheight) |>
(GtkFrame() |> (can = GtkCanvas()))
set_gtk_property!(can, :expand, true)
draw(can) do widget
ctx = Gtk.getgc(can)
select_font_face(ctx, "Leonardo\'s mirrorwriting", Cairo.FONT_SLANT_NORMAL,
Cairo.FONT_WEIGHT_BOLD)
set_font_size(ctx, fontpointsize)
set_source(ctx, bkcolor)
rectangle(ctx, 0, 0, mapwidth, mapheight)
fill(ctx)
set_source(ctx, rcolor)
for i in 1:size(basebuffer)[1], j in 1:size(basebuffer)[2]
move_to(ctx, j * fontpointsize * 0.9, i * fontpointsize)
c = basebuffer[i, j]
if c == '~'
set_source(ctx, xcolor)
show_text(ctx, String([rand(caps)]))
set_source(ctx, rcolor)
else
show_text(ctx, String([c]))
end
end
end
while true
for col in 1:windowmaxx
c = popfirst!(columngenerators[col])
if c != '\0'
basebuffer[2:end, col] .= basebuffer[1:end-1, col]
basebuffer[1, col] = c
end
end
draw(can)
Gtk.showall(win)
sleep(0.05)
end
end
digitalrain()