Polygon wheel

natiny.render.poly takes a centre, a side count, a radius and a rotation in degrees - which makes it the triangle, the hexagon and, given enough sides, the circle.

Rotation is a parameter like any other: give each shape its own rate and a still ring becomes a mechanism. The satellites gain a side each going round.


    
main.lua
local natiny = require("natiny")

local BG = natiny.color.from_hex("#151E2C")
local OBJECT = natiny.color.from_hex("#A9B3C5")
local OBJECT_FAINT = natiny.color.from_hex("#A9B3C540")
local ACCENT_SOFT = natiny.color.from_hex("#F8F9FDE6")

local SATELLITE_COLORS = {
    natiny.color.from_hex("#F8F9FDE6"),
    natiny.color.from_hex("#EDEFF5E6"),
    natiny.color.from_hex("#E1E5EDE6"),
    natiny.color.from_hex("#D6DBE5E6"),
    natiny.color.from_hex("#CBD1DDE6"),
    natiny.color.from_hex("#C0C7D5E6"),
    natiny.color.from_hex("#B4BDCDE6"),
    natiny.color.from_hex("#A9B3C5E6"),
}

local CORE_COLORS = {
    natiny.color.from_hex("#F8F9FDBF"),
    natiny.color.from_hex("#F8F9FDA8"),
    natiny.color.from_hex("#F8F9FD91"),
    natiny.color.from_hex("#F8F9FD7A"),
    natiny.color.from_hex("#F8F9FD63"),
    natiny.color.from_hex("#F8F9FD4D"),
}

local function color(c)
    natiny.render.set_color(c)
end

natiny.backend.init()

local win = natiny.window.create("Polygon wheel", 900, 600)
natiny.window.set_scale_mode(win, natiny.window.SCALE_MODE_STRETCH)

local cx, cy = 450, 300
local t = 0.0

natiny.backend.loop(function(dt)
    natiny.window.bind(win, function()
        t = t + dt

        natiny.render.clear(BG)

        -- ── The frame: twelve sides, turning slowly ─────────────────
        color(OBJECT)
        natiny.render.poly_outline(cx, cy, 12, 262, t * 6, 3)

        -- ── Eight satellites, one more side each ────────────────────
        for i = 0, 7 do
            local a  = t * 0.35 + i * (math.pi * 2 / 8)
            local px = cx + math.cos(a) * 190
            local py = cy + math.sin(a) * 190

            local sides  = 3 + i
            local radius = 26 + 8 * math.sin(t * 2.0 + i)

            color(SATELLITE_COLORS[i + 1])
            natiny.render.poly(px, py, sides, radius, t * (40 + i * 14))

            -- a looser outline turning the other way, one ring out
            color(OBJECT_FAINT)
            natiny.render.poly_outline(px, py, sides, radius + 6,
                                     -t * (30 + i * 10), 3)
        end

        -- ── The middle: six outlines nested, alternate ones reversed ─
        -- Brightest at the core and fading outward, so the stack reads as
        -- one object rather than six rings that happen to share a centre.
        for i = 0, 5 do
            local dir = (i % 2 == 0) and 1 or -1
            color(CORE_COLORS[i + 1])
            natiny.render.poly_outline(cx, cy, 3 + i, 34 + i * 16,
                                     dir * t * (26 + i * 9), 3)
        end

        color(ACCENT_SOFT)
        natiny.render.poly(cx, cy, 6, 13, -t * 30)
    end)
end)

natiny.backend.shutdown()