Building Playable Godot 4 and WebGL Games That Survive Revision
Why single-file AI games break on the second edit, and how decoupling scene trees, swept-AABB collision controllers, and barycentric terrain samplers keeps creative projects editable.
Most AI game demos fail on two fronts: either the character controller clips through sloped terrain and tunnels through walls on the first run, or the second prompt ("add a companion firefly and a suspension bridge over the pond") overwrites the working movement code and breaks the scene. On fox.baltor.ai and parkour.baltor.ai, Baltor structures playable WebGL2 and Godot 4 projects around modular scene components and verified physics primitives so that unchanged subsystems remain locked across revisions.
Why naive discrete collision checks fail
When an unassisted model writes a 3D platformer or woodland exploration game, it almost always checks collision after moving the character (position.addScaledVector(velocity, dt)). If the player jumps toward a thin wall or lands from a high ledge during a 28 ms frame, the bounding box steps completely across the obstacle boundary in a single tick.
Baltor's movement component (physics.controller.swept_aabb.v1) uses continuous slab-method Time-of-Impact (TOI) queries with three-iteration slide projection:
// Continuous Swept-AABB Collision & Slide Solver
export function moveAndSlideSweptAABB(box, velocity, colliders, dt) {
let remainingDt = Math.min(dt, 0.0333);
let vel = { ...velocity };
let grounded = false;
for (let iter = 0; iter < 3 && remainingDt > 1e-5; iter++) {
let earliestToi = 1.0;
let hitNormal = null;
for (const obstacle of colliders) {
const hit = intersectMovingAABB(box, vel, obstacle, remainingDt);
if (hit && hit.toi < earliestToi) {
earliestToi = hit.toi;
hitNormal = hit.normal;
}
}
const safeAdvance = Math.max(0.0, earliestToi - 1e-4) * remainingDt;
box.x += vel.x * safeAdvance;
box.y += vel.y * safeAdvance;
box.z += vel.z * safeAdvance;
if (!hitNormal) break;
if (hitNormal.y > 0.7) grounded = true;
const vn = vel.x * hitNormal.x + vel.y * hitNormal.y + vel.z * hitNormal.z;
if (vn < 0) {
vel.x -= vn * hitNormal.x;
vel.y -= vn * hitNormal.y;
vel.z -= vn * hitNormal.z;
}
remainingDt *= (1.0 - earliestToi);
}
return { position: box, velocity: vel, grounded };
}
Barycentric terrain sampling and quadruped gait alignment
In Foxglade: The Living Wood (fox.baltor.ai), the red fox traverses rolling hills, a catenary wooden bridge, and shoreline rocks. Sampling terrain height at the character origin alone leaves the front paws floating in mid-air on downhill slopes and buried inside the mesh on uphill climbs.
The Baltor terrain adapter queries exact barycentric triangle heights (u * y0 + v * y1 + w * y2) at four independent paw raycast sockets (FL, FR, HL, HR), pitches the pelvis and chest bones along the filtered terrain normal, and blends a 17-joint RTMPose rotary-gallop keyframe cycle (fox.baltor.ai/motion-study.html). When a user later revises the lighting or adds a quest marker, the rig, terrain sampler, and swept-AABB controller remain untouched in their component slots.
| Navigation | Post Title | Direct Links |
|---|---|---|
| Previous Post | Eliminating Non-Manifold LLM Meshes in Blender bpy and Three.js r170+ | HTML · Markdown |
| Next Post | 60 FPS Motion Graphics: Why Spring Physics and DFT Epicycles Beat CSS Keyframes | HTML · Markdown |
| Blog Index & Feeds | Return to Baltor Engineering Blog Index (8 Posts) | index.json · feed.xml |