← ROBERTHQ.COM ROBLOX · AGE 12–14
█ ARCHIVED RECORD █

where it
started.

before the iOS apps and the agents, there was roblox. i taught myself to build there, from age 12 to 14 - a live data dashboard, a shipped horror game, terrain art, and a water simulation i couldn't put down. this is the origin story, in order.

FILEroblox-era · age 12-14
SUBJECTrobert vassallo (@weeeeeeeeeels)
AGE12 → 14
OUTPUTdashboards · games · terrain · sims
STATUSwhere the building habit began
2020 · CH.1 · AGE 12

the very first thing: a live COVID tracker.

not a game - a dashboard. it hit a public COVID-19 API every load and pushed each country's case numbers onto television screens inside the world. age 12, no idea what an API even was. that was the spark that started everything.

In-world Roblox TV screens showing live COVID country case data
in-world dashboards, fed by a live API · 2020
local http   = game:GetService("HttpService")
local apiurl = "https://api.covid19api.com/summary"
local data   = { ["X-Access-Token"] = "••••••••" } -- redacted

local countries = http:JSONDecode(http:GetAsync(apiurl, false, data))

ImpEvent.OnServerEvent:Connect(function(player, citySent)
    for _, v in pairs(countries.Countries) do
        if string.lower(citySent) == string.lower(v.Country) then
            dashboardShow(v) -- push totals to the in-world TVs
            break
        end
    end
end)
covidtracker/script.lua - my first ever HTTP request.
CH.2 · FIRST FULL GAME

“only way out” - 561 visits, cutscenes and all.

my first complete game. a horror-escape with flashlight mechanics, custom lighting, a nuke ending, and fully scripted camera cutscenes. 561 players ran it start to finish. below: the full 4:55 walkthrough, then stills from the cutscenes.

FULL WALKTHROUGH · 4× SPEED
Flashlight horror gameplay
the chase
'Great job on escaping' cutscene
you escaped…
Campfire picnic cutscene
the calm
Night scene with red house
…or did you
-- scripted camera cutscenes via TweenService
function tween(from, to, hold, duration)
    camera.CameraType = Enum.CameraType.Scriptable
    camera.CFrame = from.CFrame
    TweenService:Create(camera,
        TweenInfo.new(duration, Enum.EasingStyle.Sine, Enum.EasingDirection.Out),
        { CFrame = to.CFrame }):Play()
    wait(hold)
    camera.CameraType = Enum.CameraType.Custom
end

tween(cams.Camera1, cams.Camera2, 10, 10) -- glide between cinematic cameras
onlywayout/cutscene.lua - easing the camera between fixed shots.
CH.3 · TERRAIN ART

sculpting worlds in Gaea.

i moved from scripting to making worlds feel real - designing terrains in Gaea (QuadSpinner) with heightmaps and erosion, and taking paid commissions building environments for a studio. it was the start of an obsession with believable digital nature that led straight into the next one.

Aurora over a mountain range, Roblox terrain
aurora mountains
Avatar on a cliff at sunset overlooking generated terrain
a world you could stand in
Volcanic mountain range at sunset
volcano range
gaea / quadspinner · heightmaps · erosion · paid commissions
CH.4 · THE OBSESSION

real-time water simulation.

i don't fully know why water got me. the thought of simulating something that complex - and actually being able to swim in virtualised water - just kept pulling me back. getting it working at 13 was genuinely hard, but i was too fascinated to stop, so i kept at it.

animated Gerstner waves deform the mesh in real time. the hard part was inverting that displacement to recover a point's true height on the moving surface - so a player's buoyancy matched exactly what they saw. what you float on is what you see.

REAL DEMO · GERSTNER WAVES
-- the visible surface: a sum of Gerstner waves
function getWavePos(p, t)
    return gerstnerSingle(p, -0.14, 0.91,  40, 2,  t)     * 5
         + gerstnerSingle(p, -0.99, 0.14,  40, 2,  t)     * 5
         + gerstnerSingle(p, -0.80, 0.60,  20, 2, -t)     * 3
         + gerstnerSingle(p, -0.50, 0.808, 190, 2, t*0.4) * 19
end

-- the hard part: invert the displacement to recover a point's TRUE
-- height on the moving surface. three trace-backs converge on it.
function getCorrectedY(wavePosAt, Position, Time)
    local off  = Position - wavePosAt
    local b1   = getWavePos(off  - (getWavePos(off,  Time) + (off  - Position)), Time)
    local off2 = Position - b1
    local b2   = getWavePos(off2 - (getWavePos(off2, Time) + (off2 - Position)), Time)
    local off3 = Position - b2
    return getWavePos(off3 - (getWavePos(off3, Time) + (off3 - Position)), Time)
end
wavesimulation/WaveFunction.lua - Gerstner sum + iterative inverse sampling, age 13.

and the funniest part? i spent days convinced the math was broken, rewriting it over and over. it wasn't. every bone in the mesh was anchored, so nothing could physically move no matter what the code did. the second i un-anchored them, the whole ocean came alive. days of "debugging" undone by one checkbox.

and it wasn't a tech demo floating in a void - it carried a boat. the hull samples the wave height at each point and bobs with the swell. real buoyancy, on water i'd simulated myself.

BOAT · BUOYANCY ON THE SIM
me actually riding it, buoyancy sampled from the same wave function.

and the best part? i didn't just get to be a total geek about this, i got paid to be one. the water and the boat were a commission for a studio. i was 13.

CH.5 · THE RECEIPTS

it's all documented.

my original developer portfolio lived on the Roblox DevForum - the full run from age 12 to 14, terrain generation, scripting, and commissions. then i went off to build everything else.

DEVFORUM PORTFOLIO ↗
END OF RECORD
← BACK TO ROBERTHQ.COM