**The flat plane is gone.** Terrain existed all along — heightfield collision via box3d, AO and shadow raymarching against it, a mesh path, a `game.terrain` verb — and arcade simply spawned a flat slab instead. That is the fourth capability this week that was built and never called. Turning it on was not enough, because the generator had faults that a screenshot explains faster than prose: - **Single-octave value noise.** Detail at exactly one scale reads as melted blobs. Now fBm with domain warp, which is the single highest-value knob here: warping the sample point bends contours into ridges and valleys instead of round lumps on a visible grid. - **`step` defaulted to 1.0**, quantising every smooth slope into 1-unit stairs. The old default renders as a literal contour map. Off by default. - **Noise was indexed by CELL INDEX, not world position**, so asking for a finer mesh silently generated a different landscape. Resolution should buy detail, never a new world. - **Colour came from height alone**, which paints terrain in horizontal stripes like a contour map. Now height AND slope, so rock lands on cliff faces and grass on the shelf above them. Generation moved to `libs/game/gen/terrain.rs` as a pure function. Beyond testability that was forced: arcade's demo world has no script VM, so the only generator in the tree was one it could not reach. `rim_relief` is the load-bearing idea. Terrain interesting everywhere is terrain you cannot put a town on; terrain flat enough to build on is a green table. Growing the relief outward gives a playable basin ringed by something worth looking at, and doubles as a soft boundary. It SCALES the noise rather than adding a radial ramp — the ramp version has no noise in it and renders as a smooth machined ring between two flat plains, which I built first and threw away after looking at it. Two things the tests taught me rather than confirmed: - Normalising fBm by the sum of octave amplitudes — the textbook form — makes five octaves come out FLATTER than one, because summing decorrelated fields concentrates them about the mean. Normalising against the field's own extents makes `amp` mean literal relief at any octave count. - The octave test measures CURVATURE, not slope. At gain 0.5 / lacunarity 2 every octave contributes equally to slope — that is what self-similar means — so a slope-based test reports no difference while the terrain visibly gains detail. My first version of that test was wrong, not the code. Statics get one conform pass after composition; movers already clamp to the terrain every tick in `step.rs`, so the player, villagers and car find the ground themselves. **Cars now touch the road.** Kenney authors vehicles origin-at-the-contact- patch — tyres exactly on y=0, with each wheel node lifted by its own radius — and every vehicle in every kit measures min.y == 0, verified across all 4442 GLBs in the library. We were dropping the model by `half.y` instead, a rule that is right for a walker (a Mover's box bottom really is its feet) and wrong for a raycast vehicle, whose suspension probes from the chassis origin. The float was suspension travel plus wheel radius, 0.341 units, predicted in closed form and matched by simulation to 1e-5. The same line also shifted in world Y after rotation, so the mesh slid out from under a leaning chassis. Both now derive from measured bounds along the body's own down axis — no constant anywhere. Note the convention is real but NOT universal: track and road pieces go to min.y = -1.0, so it must be read, never assumed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
24 lines
1 KiB
TOML
24 lines
1 KiB
TOML
[package]
|
|
name = "makepad-game-blocks"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "High-level game building blocks (cars, characters, planes, brains, race kit) for Makepad Arcade"
|
|
license = "MIT OR Apache-2.0"
|
|
|
|
[dependencies]
|
|
makepad-game-math = { path = "../math" }
|
|
makepad-game-sim = { path = "../sim" }
|
|
makepad-game-audio = { path = "../audio" }
|
|
makepad-math = { path = "../../math", version = "1.0.0" }
|
|
makepad-box3d = { path = "../../box3d" }
|
|
|
|
[dev-dependencies]
|
|
# Tests only: proving a walker can enter a REAL generated room is the point of
|
|
# the interior work, and a synthetic box would prove nothing about it. The
|
|
# crate itself stays independent of geometry generation — blocks are behaviour.
|
|
makepad-game-gen = { path = "../gen" }
|
|
# Tests only, same reason: "the car's body does not float above the road" is a
|
|
# claim about a REAL Kenney GLB's vertices placed on a REAL settled chassis.
|
|
# Split across two crates it is two half-tests that both pass while the car
|
|
# hovers, which is exactly what happened.
|
|
makepad-game-render = { path = "../render" }
|