Typewriter
Reveals UTF-8 text one code point at a time while preloading its glyphs and sizing the panel from the complete wrapped message. Press Space to restart or hold it to reveal the text faster.
local natiny = require("natiny")
natiny.backend.init()
local win = natiny.window.create("Typewriter", 900, 600)
natiny.window.set_scale_mode(win, natiny.window.SCALE_MODE_STRETCH)
local res = natiny.resource.load("data/common/fonts/roboto.ttf")
local font = natiny.font.create(res, 26)
local small = natiny.font.create(res, 18)
local MESSAGE = "Missing glyphs are baked when first drawn. preload does this during " ..
"loading, so the pause stays hidden."
natiny.font.preload(font, MESSAGE)
natiny.font.set_line_spacing(font, 1.15)
local BG = { 21 / 255, 30 / 255, 44 / 255 } -- #151E2C
local OBJECT = { 169 / 255, 179 / 255, 197 / 255 } -- #A9B3C5
local ACCENT = { 248 / 255, 249 / 255, 253 / 255 } -- #F8F9FD
local LIGHT_TEXT = { 243 / 255, 245 / 255, 250 / 255 } -- #F3F5FA
local DARK_TEXT = { 17 / 255, 24 / 255, 39 / 255 } -- #111827
local X, Y, W = 120, 140, 660
local TOTAL = utf8.len(MESSAGE)
local shown, blink = 0, 0
natiny.backend.loop(function(dt)
natiny.window.bind(win, function()
shown = math.min(TOTAL, shown + dt * 26)
blink = blink + dt
local cut = utf8.offset(MESSAGE, math.floor(shown) + 1) or (#MESSAGE + 1)
local visible = MESSAGE:sub(1, cut - 1)
local caret = (blink % 1.0 < 0.55) and "_" or " "
local _, full_h = natiny.font.measure_wrapped(font, MESSAGE, W)
natiny.render.clear(BG[1], BG[2], BG[3], 1)
natiny.render.set_color(OBJECT[1], OBJECT[2], OBJECT[3], 1)
natiny.render.rectangle(X - 24, Y - 24, W + 48, full_h + 48)
natiny.render.set_color(DARK_TEXT[1], DARK_TEXT[2], DARK_TEXT[3], 1)
natiny.render.text_box(font, X, Y, W, full_h, visible .. caret)
natiny.render.set_color(OBJECT[1], OBJECT[2], OBJECT[3], 1)
natiny.render.rectangle(X, Y + full_h + 44, W, 4)
natiny.render.set_color(ACCENT[1], ACCENT[2], ACCENT[3], 1)
natiny.render.rectangle(X, Y + full_h + 44, W * shown / TOTAL, 4)
natiny.render.set_color(LIGHT_TEXT[1], LIGHT_TEXT[2], LIGHT_TEXT[3], 1)
natiny.render.text(small, X, Y + full_h + 60,
string.format("%d / %d code points", math.floor(shown), TOTAL))
end)
end)
natiny.backend.shutdown()