Alvaro Guzman Résumé ↓
← Work
Gamedev · LÖVE 11.5, Unity, Bevy

Game loops, from the metal up.

LÖVE is where I prototype: plain Lua against its update and draw callbacks, with no engine layered on top. Passages, the game I'm building, runs in Unity. The rest is study — a BSP renderer in C, and an SDL2 → Rust/Bevy track.

love.update(dt)
fixed step
love.draw()
canvas batched
love.physics
box2d body sim

Active and past builds

01

Passages — LitRPG-inspired third-person action RPG

In development

Combat blends FF12's Gambit system with the rule-driven party logic of .hack//GU. A dual-resource system (Vitality / Essence) governs both health and casting. The Attunement Scripts editor lets the player wire per-companion behavior trees. Abilities authored as ScriptableObjects so designers iterate without recompiling.

UnityC#gambit AIScriptableObjectdual-resource
02

From-scratch BSP renderer + Unity shooter prototype

Research

A BSP renderer written from scratch in C as a graphics deep-dive — tree construction, polygon splitting, painter's-order traversal. Separately, a 3D shooter prototype in Unity to feel the C# tooling end of the same pipeline. Both research artifacts, not productized.

CUnityBSPrendererresearch
03

Bevy + SDL2 track — SDL2 first, Bevy after

In progress

Sequential ladder, not a single project. SDL2/C++ for the fundamentals (Pong, then Breakout, then a top-down shooter), then graduate the same exercises into Rust + Bevy to feel ECS-first authoring against the same problems.

pong → breakout → top-down shooter → bevy
RustBevySDL2C++ECS
Loop skeleton

Fixed timestep, honestly.

Accumulate real time, step the world in constant slices, draw whatever is current. Deterministic under load, and the bug that only appears on fast machines goes away.

love.graphicscanvases, batches, shaders
love.physicsbox2d bodies, joints
love.audiopositional sources
love.keyboardedge + held detection
conf.luawindow + module flags
function love.load()
    world = love.physics.newWorld(0, 9.81*64)
    player = entities.spawn("player", 100, 100)
end

function love.update(dt)
    accumulator = accumulator + dt
    while accumulator >= STEP do
        world:update(STEP)
        input.poll()
        ai.tick(STEP)
        accumulator = accumulator - STEP
    end
end

function love.draw()
    camera:attach()
    tilemap:draw()
    entities:draw()
    camera:detach()
    hud:draw()
end