Spinning Donut with only ASCII

local function renderDonut()
    local A, B = 0, 0 -- Rotation angles
    local width, height = 40, 20 -- Screen size in characters
    local theta_spacing = 0.07
    local phi_spacing = 0.02
    local R1, R2, K2 = 1, 2, 5
    local K1 = width * K2 * 3 / (8 * (R1 + R2))

    while true do
        local z_buffer = {}
        local output = {}

        -- Initialize buffers
        for i = 1, width * height do
            z_buffer[i] = 0
            output[i] = ' '
        end

        -- Render the donut
        for theta = 0, 2 * math.pi, theta_spacing do
            for phi = 0, 2 * math.pi, phi_spacing do
                local cosA, sinA = math.cos(A), math.sin(A)
                local cosB, sinB = math.cos(B), math.sin(B)
                local cosTheta, sinTheta = math.cos(theta), math.sin(theta)
                local cosPhi, sinPhi = math.cos(phi), math.sin(phi)

                local circleX = R2 + R1 * cosTheta
                local circleY = R1 * sinTheta

                local x = circleX * (cosB * cosPhi + sinA * sinB * sinPhi) - circleY * cosA * sinB
                local y = circleX * (sinB * cosPhi - sinA * cosB * sinPhi) + circleY * cosA * cosB
                local z = K2 + cosA * circleX * sinPhi + circleY * sinA
                local ooz = 1 / z

                local xp = math.floor(width / 2 + K1 * ooz * x)
                local yp = math.floor(height / 2 - K1 * ooz * y)

                local luminance = cosTheta * cosPhi * sinB - cosA * cosTheta * sinPhi - sinA * sinTheta + cosB * (cosA * sinTheta - cosTheta * sinPhi * sinA)

                if luminance > 0 then
                    local index = xp + yp * width
                    if index >= 1 and index <= width * height and ooz > z_buffer[index] then
                        z_buffer[index] = ooz
                        local chars = {'.', ',', '-', '~', ':', ';', '=', '!', '*', '#', '$', '@'}
                        local luminanceIndex = math.floor(luminance * 8)
                        output[index] = chars[luminanceIndex] or '.'
                    end
                end
            end
        end

        -- Print the frame
        local frame = ""
        for i = 1, width * height do
            if i % width == 0 then
                frame = frame .. "\n"
            end
            frame = frame .. output[i]
        end

        print(frame)
        task.wait(0.05) -- Control speed

        A = A + 0.04
        B = B + 0.08
    end
end

-- Start rendering in a coroutine
task.spawn(renderDonut)

ÂżWhat the Robloxment is this?

The script is a spinning ASCII donut in Roblox Studio’s Output window, based on the classic ASCII donut algorithm (“donut.c”). It uses math to simulate 3D rotation, rendering a torus (donut shape) using ASCII characters.

How It Works:

  1. Uses math to rotate the donut
  • Two rotation angles A and B continuously update.
  • theta and phi control the donut’s shape in 3D.
  1. Projects 3D points onto a 2D ASCII grid
  • Converts 3D coordinates to screen coordinates (xp, yp).
  • Uses depth buffering (z_buffer) to determine which points are in front.
  1. Chooses ASCII characters based on lighting
  • Brighter areas use characters like @ and #, while darker areas use . or -.
  1. Prints the donut frame-by-frame
  • The print() function continuously updates, creating a spinning effect in the Output.

Where to See It?

  • Run it in Roblox Studio inside a Script (ServerScriptService or StarterPlayerScripts).
  • Open the Output window (View → Output or Dev Console with F9).
  • The donut will spin continuously, updating in real-time.
  • PRECAUTION: you need to scroll down to the Dev Console to see it animate

So ,the unique bug is there a missaligned line of characters at the right of the time date so I let it here

1 Like

This is cool and all but at least learn from ChatGPT’s scripts instead of copy-pasting them

2 Likes

Ok but this is actually pretty nice i didnt know u could do that in the dev console but u cant just let chatgpt do all the work for u

He removed it lol

That’s a nice ASCII donut, ChatGPT!

ChatGPT, this is what you’re doing while I’m trying to reconfigure the same script 12 times and you keep forgetting the previous logic we worked on?

Judging by the image and the explanation, it looks really interesting!

I wonder if you can do this in GUI elements like TextLabel… It would be something pretty cool!

what’s less surprising than the fact that this was written by ChatGPT, is the fact that running this code immediately crashed my Studio.
reliable as always.