Blockbuster 767
Commits
Every published commit of this world, on every branch, newest first.
8e9b87fcceshots and clips of the game as it plays now: the wind-up launcher, a called landmark, flight through the towers, the tally and the star card1bd17c5cd1fix: the title card is the first thing a player sees again, the room stops holding dust that is not there, and the Kid's verdict stays on the end card
The boot never reached the title. is answered both by the
presentation slice, which lands the title card, and by the camera director,
which started the opening flythrough, and whichever the bus reached last
decided what the player looked at — so a fresh session went straight into the
flythrough and on to the launcher, and BACK TO THE BOX from the end card did
the same. The director no longer starts the flythrough from that event: every
path that wants it asks for it by name. The bus dispatches in subscription
order rather than in whatever order a table iterates, and the title handoff is
spent when the player leaves the title, so it cannot come due again mid-session.
An effect that has finished sometimes leaves its last frame of particles
standing. Three clouds of dust and splinters were hanging over a settled city
with nothing having been hit for five minutes, one of them in shot on the title
card. The set slice now gives the idle pool back at the beats where nothing is
playing and no frame is being flown.
The Kid's verdict left the end card after the clip finished rather than after
the twelve seconds the card is written to hold it for; a line running out no
longer clears the words.
Six modules shipped the scaffolded README placeholder into a public world; they
now say what they are. World validation: 8 warnings down to 2.2016bb1c78set: re-rendered block material previews
The previews were re-generated by a batching A/B that pointed the ten block
materials at pbr and back again. The mat.yaml bytes are unchanged from the
previous commit; only the rendered previews differ.c28394b1fdset: the room is lit, the blocks are wood, and every hit throws dust
Grade off the UI. The playroom_grade PostProcess declares layer = "scene", so
the pass runs before the interface is composited. Its twelve-tap bloom was
printing a displaced copy of every cream glyph over the 0.90 threshold, which
read as a second misregistered heading on every card, and its tilt-shift band
was defocusing the top and bottom of each one. The scene is still graded.
The sun comes over the player's shoulder. It travelled -Z, towards the camera,
so every block face the player saw was backlit and the fill did the lighting on
its own; that is what read as pale plastic. It now travels (-0.78, -0.42, 0.46)
and rakes the camera-facing faces, with the fill warmed to room bounce and
lifted to 0.28, the key dropped from 3.7 to 2.6 (at 3.7 the newly-lit faces sat
at 0.85 luminance and had no colour left in them), the sky IBL down to 0.20 and
the grade's saturation from 0.26 to 0.15 now the colour comes from the light.
The window opening runs from z = -40 rather than -22 to fit the new angle: the
key crosses the +X wall 14.7 m before the point it lands on, and at the old
opening the whole launcher end of the table stood in the wall's shadow.
The ten block materials move to playroom_paint, the shader the table already
wears, at grain_scale 3.2 / grain_strength 0.42 / wear 0.32 / clearcoat 0.22
and reflectance down from 0.35 to 0.12. The painted_wood texture they used to
bind is white to within four code values, so the albedo pass showed ten flat
colours; it now shows grain and edge wear (albedo spread 115 -> 125).
impacts.module is new: one subscriber on the game's bus that plays the wood
impact effect on impact and blockDisplaced, a bigger burst plus a shockwave
ring on towerToppled, and a puff where a block leaves the table. Plays are
rate-limited by a token bucket, and a burst the bucket refuses is folded into
the next play's count rather than dropped, so a collapsing tower is a handful
of large clouds and not fifty small ones.
The lamp shade and the window get playroom_glow, a new surface with a gradient
down world Y and a fresnel term, so the shade reads as lit paper rather than a
flat white triangle and the window as sky rather than a hole. The four picture
frames get playroom_crayon, also new: a child's drawing of the aeroplane and a
child's tower of blocks, in wax crayon on sugar paper.
box() is now shape() with the cube already chosen. Model.mobility = "static"
was tried on the 58 props and taken back out: three 20-second windows read
mesh_transform_compose at 0.82 ms with no flag, 0.80 on auto and 0.83 on
static. Set gains onModuleReload so a sibling's edit to game.game does not
leave the effects silently unsubscribed.b1f23f4fdcflight: wind the key — a held Launch, the called shot, and a wreck that waits for the city
Launch is HELD now. Each Rules.LAUNCH.windSeconds of hold is one wind of the
key, the last wind gets a window of its own, past it a red zone of
overwindSeconds throws overwound (faster, five seconds of boost fuel, and an
airframe that breaks overwindDamage times as easily), and past THAT the spring
slips and the throw is a dud. The modelled key on the toy's back turns a full
turn per wind, trembles in the red zone and spins back when the spring goes.
Boost is what the wind bought: boostFuel is seconds of thrust, it drains only
while Boost is thrusting, and an empty tank is a dead throttle.
On the launcher Boost and Dive step the called shot forward and back through
the landmarks City:landmarks() reports still standing, with 'no call' as one of
the stops — no new control on any device.
The round now ends when the airframe has settled AND City:atRest() agrees, or
after a further restCityGrace; measured last-moving-to-wreck fell from ~1.8 s to
1.20 / 1.22 s on a settled city. The permanent no-op Game.tickChain call is
gone, telemetry publishes elevation / winds / windCharge / winding / overwound /
boostFuel / launchSpeed every frame, and onModuleReload re-subscribes the bus.
Verified on keyboard, gamepad and touch: holds of 0.8 / 1.35 / 1.9 s read
1 / 2 / 3 winds and throw at 9 / 12 / 15 m/s (peaks 8.3 / 10.9 / 13.9), a 2.4 s
hold releases overwound at 16 with boostFuel 5.0, a 3.5 s hold is a 6 m/s dud;
the called ring reads none/tower/span/tank on all three; a called SPAN topple
pays 500 x tier x 2 x 2 = 4000; Escape on the launcher pauses; boosted peak
19.11 m/s under the 20 cap with no CCD anywhere.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0139MdCaDTnP2jpG8zgk5N2Nba8f9f2ac4screens: the caption comes to the card, the HUD stops relaying out, and the room shows through
CAPTIONS. Screens subscribes with Caption.on and claims the caption for as
long as any card is up, so the Kid's line is printed inside the card and the
sound slice's own band stands down; the claim is released the moment the last
card comes down. The fourteen-event payload harvest and Screens:say - which
nothing ever wrote to - are gone.
FRAME COST. The HUD key is coarse (speed to 1 m/s, heading to 1/8 rad, the pop
term at 6 Hz) and now carries the wind, fuel, altitude, called shot and
landmark bits the new instruments read; a nextHudAt timer holds HUD pushes to
20 Hz while show/hide and the card branch stay per-frame. Measured over one
flight: the old key changed 158 times where this pushes 76. Theme.pulse
breathes on opacity with a finite count instead of an infinite transform:
scale, which was relaying the whole tree out every frame. Every tree build is
inside a pcall that logs once per fault and keeps the last good tree.
THE CARDS. Title and end card are printed on a see-through backdrop over the
real launcher, the untouched city and the camera's swing across the wreckage,
and drop the drawn skyline emblem; cardBackdrop's see argument is now the share
of the room that shows through. The end card renders a snapshot taken from the
sessionEnd payload, so BACK TO THE BOX no longer blanks it to zeroes. The
column no longer eats the backdrop's slack, so the how-to and end cards stop
reading as a third of empty ground. An unearned star sits in a lit socket. The
pause card wears a wind-up key rather than a crosshair. The how-to gains a
row for winding and one for calling a landmark, and a legend saying which chip
colour is which device.
UNDERNEATH. Theme.chip and Theme.stat collapse four near-identical builders;
restartSession collapses the two identical act branches; Focus keeps the open
menu in modules.state() so an edit no longer leaves a card nothing can walk;
Theme.punch, Focus.isFocused and Focus.generation are gone. Screens, cards,
theme and Focus are --!strict with typed card views, and the three HUD views
are hud.module's own exported types. onModuleReload re-registers everything.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0139MdCaDTnP2jpG8zgk5N2N8e7baf9dc7camera: the toy is the subject — a closer chase, an altitude-biased aim, and the shots nobody saw
Chase: framing 2.3 -> 1.7 spans, speedPushBack 0.55 -> 0.3, speedOpenLens 9 -> 5,
positionLag 0.18 -> 0.13, restPullIn 0.55 -> 0.10 so the launcher station stays
where it was while the flight one comes in. Measured on one launch, same method
before and after: the eye stood 15.5 m off the toy at fov 63 and now stands
12.1 m off at fov 60 — 1.36x the toy in the frame — and the gap holds rather
than opening as the toy accelerates.
The aim gains an altitude bias against the STANDING city's own height band
(Cam.cityBounds, from City:bounds() with the seeded layout as the fallback): it
tips down as the toy climbs over the skyline so the city stays in the frame, and
a floor at the table top holds the belly slide, which used to pitch the camera
into the slab.
Director: every station composed against the city now measures it rather than
trusting a constant. The opening's first station lands over the towers (pz 17.1,
inside the city's z band) instead of past the table edge; the end wide aims at
the city's own middle. A new held TITLE wide stands behind the launcher with the
whole skyline across the frame and the toy in the lower third — the shot the
title card is laid over. The wreck cut was filming the inside of a block: at
0.78 spans it was pulled to 56 % of even that by the geometry, 2.6 m off a 5.9 m
toy. It now stands 1.8 spans out at the launcher side, unobstructed (frac 1.00),
with the city behind the toy. A held beat now stands down whenever the state
that opened it has moved on, so an end-card wide can no longer keep the frame at
weight 1 after the machine advanced.
Underneath: cam.module's mutable state moved into modules.state() — the measured
span above all, which an edit of that file used to reset to the default under a
camera that never re-measures; the poses are published in place so both
components keep holding one table across a reload. ChaseCamera's offX: number?
sentinel became seeded + offX = 0 and the four casts went. Both components carry
onModuleReload.
Kept: ChaseCamera is still the only writer of the rig; launch kick, impact shake,
the topple dip to 0.35 released to exactly 1, the orbit-then-cut, skipOpening,
the aspect rules (3:4 -> 58 deg/x1.0, 9:16 -> 66.5 deg/x1.15) and a pause holding
the beat where it is — all replayed after.d5290aa12ahud: the launcher's instruments and the flight tape
The wind HUD gains what the aim was missing. Three wind pips fill with the
key's charge and turn crimson together in the overwind red zone; an elevation
ladder stands beside the trim dial; and a side-on throw picture draws the
table, the standing city as a band, and the trimmed throw arcing into it with
a ring where it arrives. The launcher also shows what can be called — the
landmark strip with the called one in gold — and says how to call it in the
words of whichever surface is driving.
The flight HUD gains a boost-fuel gauge under the speed bar in the same
painted idiom, and an altitude tape at the right with the standing city's
height drawn across it: the lit column and the metres beside it read gold
inside the towers, blue over them and crimson below.
The arc is a closed-form constant-acceleration solution, and it falls at
gravity times one minus the wings' lift share rather than at a bare 9.81 —
solved with the bare figure the arc lands at z = -8 whatever the player does,
short of a city that starts at z = 0, and the instrument would be telling
them they can never reach what the game throws them into every time.
Both builders now carry exported WindView / FlightView / RestingView types
under --!strict, and every field is read through a guard, so a view built
before this pass still draws. Nothing animates for ever any more: the two
infinite transform keyframes are finite opacity breaths, which is what took
a Taffy relayout off every frame the HUD was up. The glyphs whose arguments
enumerate are assembled once and kept, which put the flight tree's build at
0.026 ms against 0.027 ms before it — with sixteen more nodes in it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0139MdCaDTnP2jpG8zgk5N2N2d3aac4182city: three landmarks, THE TANK's burst, and a city the frame stops paying for
THE TOWER, THE SPAN and THE TANK are elected on every build — the tallest
skyscraper, the bridge, and the water tower nearest the centre line — and each
flies a pennant on the block that stands highest in it, parented so the flag
rides the structure down. City:landmarks(), City:atRest() and City:bounds()
are what the launcher, the HUD and the camera read them through. A landmark's
topple pays its multiple and the called one pays again, applied at the single
place a topple is now recorded. THE TANK bursts when it goes: every live block
inside six metres takes an outward shove that falls off to nothing at the rim,
and the governor bounds it like any other debris.
Underneath, the city stops costing the frame what it used to. The 143 block
ids are bound once at build and every frame's positions arrive in one call
into a typed vec3 buffer, which the sweep then reads as BYTES — measured over
143 blocks and 200 frames on this engine: 0.307 ms per entity, 0.438 ms
through batchRead into Lua tables, 0.077 ms through the buffer's getVec3,
0.036 ms this way. The per-block state moved from 143 tables to arrays indexed
by slot, 0.59 ms of sweep against 0.054 ms. City's update reads 0.11-0.22 ms
where it read 0.40-0.46. The arming pass writes armPerFrame joints a frame
instead of all 126 in one step, so the fifth of a second it used to spend
frozen two seconds into every session is spread across eight frames; the log
line still reports all 126 armed from 50..1885 N. And a block whose joint has
broken sheds its Joint component from the break handler, so a flattened city
ticks no joint pumps at all where it used to tick 126.
blocks.module closes every archetype through one finish(), which names the 3.2
metres a topple tier is worth once instead of six times; PAINT_COUNT and KINDS
are gone, and the layout's zMax clamp stays as the check that Rules.CITY.zMax
is still where the far street is.
Seed 7 builds the same city it did: 17 structures, 143 blocks, 126 joints, the
same x/z/height/tier for every one.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0139MdCaDTnP2jpG8zgk5N2N37aa93d2e8sound: the Kid calls it — payload-keyed lines, the key's ratchet, and a mix that stops talking to the engine
Selection is keyed off what actually happened. Every spoken cue now carries a
weight — a chain, a tier, a landmark, whether the shot was called, why the
round ended, what it earned, how many stars — and Lines.pick answers with the
nearest line that has not been used this session, falling back to a used one
rather than ever going silent. One voice source and one queue: a cue that
loses to a line already speaking waits, a cue that outranks it interrupts, and
a line that waited past its moment is dropped instead of arriving stale.
New cues on the new events: the key's ratchet clicks windup at 0.90 / 1.075 /
1.25 across the three notches with a rising ui_tick beside it, the red zone
creaks every 0.20 s for as long as the player holds and speaks a warning line
bought once from audio_gen, a called shot ticks and names the landmark, and
the launch cue's volume and pitch ride the speed the wind bought.
caption.module keeps shown / claimant / listeners in modules.state(), so
editing it no longer unsubscribes a caller — proven with the screens slice's
live Caption.on subscription across two edits. captionTree reads Theme.metrics
for the inset and the bottom band instead of re-deriving both (identical: 37
and 353 at 1080x1440). Lines.byId is gone; game/audio/** is four spaces and
--!strict throughout.
Underneath: the six per-frame Audio writes are dead-banded and the two reads
are gone, measured at 0.007 writes a frame at rest and 2.5 in flight, down
from six unconditionally — process_script_mutations_router.epilogue 1.16 ->
0.90 ms over matched 100 s / 430 s windows on this engine. snd_world's entity
is captured at awake instead of looked up by name per impact. Both beds carry
loadType decompressOnLoad: audio.observe reports streaming false with the
data.zaud bytes untouched, so the streaming pump has nothing left to refill.
Storefront: the star line reads 20,000 / 55,000 / 100,000 to match
Rules.SCORE.stars, and both control tables carry the hold-to-wind and
called-shot rows. 2.2 MB of generated scratch and 4.2 MB of probe shots leave
the world.9d565151c4art: the toy stops reading as a ball with a run of bands
One registry: game/art/planeAssets.module.parts is the toy's single list of
parts — the rig name, the mesh asset, the material, whether a hit can take it
off, and the geometry that makes it. PlaneArt.build loops it, bake loops it,
PlaneArt.partNames derives from it, and the duplicate MESHES/PAINT/METAL tables
in plane.module are gone. ensure() now asks for the LAST mesh as well as the
first, so a bake that stopped part way through is not mistaken for a finished
toy.
The hull is sampled from a profile instead of typed out as twelve rings: a
sine-series ogive nose closed by a rounded tip, a straight barrel, and a tail
cone that tapers and sweeps up, at 37 rings of 32 segments. The nose is slimmer
through its whole length, is flattened a little across the crown and droops
toward the tip, so the low front three-quarter reads as a nose rather than as a
red sphere with wings. The aerofoil loft spends its chord steps by cosine, which
crowds them at the leading and trailing edges and takes the chordwise facets off
the top of every wing.
The paint: toy767_paint gains a clearcoat over its diffuse coat, so the plastic
carries a specular roll along the crown the way the table's painted wood does,
and toy767_metal reads the atlas through a rectangle of its own. The atlas gains
a wear pass — the nose rubbed back where the toy has been landed on, the belly
scraped along its length, the wing tips and the fin chipped, grime settled in a
soft mottle, and a bright ring around the key's bow where fingers wind it. The
hull's panel lines are drawn wide apart and faint, because a line every quarter
metre reads at the chase camera's distance as banding.
The key's pivot is now at the base of its shaft, on the shaft's own axis, so
rotating the child about its local Y turns the key in place; its bow and collar
carry real UVs into the new atlas rectangle.
Geo.HALF and Geo.PART_HALF are re-stated from the bake's own measurement
(2.62 / 1.27 / 2.82 against a measured 2.62 / 1.268 / 2.812).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0139MdCaDTnP2jpG8zgk5N2Nd4ac74c83bplan: BLOCKBUSTER 767 — WIND THE KEY
The polish pass's design, appended to design/spec.md: hold Launch to wind the
key (three winds, an overwind red zone, boost fuel bought by the wind), the
aim shown as an elevation ladder and a throw arc, three named landmarks with a
called shot chosen on the launcher with Boost / Dive, an altitude tape against
the standing city, rounds that end when the city has settled, the Kid choosing
a line from what actually happened, and the screens seeing the room. The
decisions table's star thresholds now match the live 20k / 55k / 100k.
The two cross-slice contract files carry the interface every slice codes
against: rules gains the wind and landmark constants and the wind / callShot
events and puts the city's far edge where the layout always placed it;
game keeps its session, telemetry and bus in modules.state() so an edit no
longer wipes every subscriber, publishes the winding telemetry, and scores a
landmark and a called shot inside recordTopple.24faf3104eshowcase: five gameplay screenshots for the world page36f0b4e8b8fix: the playroom keeps its paint, the wreck has something to look at, and the Kid's words fit on one card
- Set re-asserts the table's painted-wood material rather than assigning it
once, so a hot reload's outgoing onDestroy can no longer leave the biggest
surface in the game wearing plain white plastic.
- The wreck beat stages its station on the table's own footprint: a toy that
goes over the edge keeps falling, and the resolution shot was framing a bare
wall. It now holds the edge it went over, with the table and city behind.
- The caption pill stretches its children instead of centring them, so a
wrapping line has a width to measure against. It was breaking one word per
line and growing down the whole screen.
- Star thresholds re-cut from played sessions (20k / 55k / 100k). At the old
3k / 8k / 15k every session finished on three stars and the rating carried
no signal.
- Game.plane() falls back to the live player registry, so a reload that loses
the entrypoint's one-time handover does not leave every reader answering nil.
- Plane767 holds the builtin walking map live so its own suppression covers it:
the touch overlay was drawing that map's Crouch / Jump / Sprint buttons and
its look-drag zone over the table.
- A player-facing README at design/README.md.
f70f366623presentation: every authored screen of BLOCKBUSTER 767, and the console scheme that drives them
Title, how-to-play, wind-up HUD, flight HUD, pause card, wreck tally and end
card, each composed for a tall 1080x1440 frame and laid out from the live
ui.screenSize() so it stays whole on a wide one.
- game/ui/theme palette, four typefaces, and metrics capped against BOTH the
shorter side and the height, so a card that fits 3:4 also
fits 16:9
- game/ui/art the toy 767, the wind-up key, the block skyline, the rating
stars, the airframe pictograms and the HUD marks, as SVG
- game/ui/cards the five cards, as pure builders
- game/ui/hud the wind-up, flight and resting readouts, all inside a top
band that clears the touch stick and button zones
- game/ui/Screens the driver: which card is up, which row is lit, the console
map's lifetime, captions, and the three state moves that
belong to presentation plus a watchdog on the opening
- game/input/console.inputMap navigate / navUp / navDown / confirm / back /
restart / pause, on keyboard and pad; cards are tapped
Verified in play at 1080x1440: title -> how-to -> title -> play, pause card
navigation and the end card's return to title, each driven with the keyboard
alone, with a pad alone (inputSim pad + padStick + padPress) and with touch
alone (inputSim touch on the rows). The HUD's lowest pixel sits at y=510
against a touch stick zone starting at 576 and a button band at 648.61d1de18e8city: six block archetypes, joints sized from the load they carry, and the score for knocking them down
The skyline is a plan before it is bodies. game.city.blocks lays out six
archetypes - a tapering skyscraper, a banded office slab, a water tower on four
legs, a thin antenna mast, a three-span bridge and a gate with a lintel - across
four streets from a seed, and hands back block specs and joint edges. It spawns
nothing and reads no entity, so a layout can be counted and validated without a
simulation. Sites are shares of the table's own half-width, and the far street
keeps clear of the table edge so a toppled block has somewhere to fall.
Every structure is a TREE of fixed joints in which each block holds at most one.
An entity carries one Joint component and a second silently replaces the first,
so that rule is what makes Physics.jointReaction(blockId) answer for a known
joint - which is what lets the thresholds be measured. Blocks.validate checks it
and the component refuses to build a structure that fails.
Joints are created with no threshold. The city then stands on its own until
every few blocks read below Rules.PHYS.settleSpeed, the resting load is sampled
over 15 frames, and each joint is armed at
breakForce = measured force x Rules.PHYS.jointBreakMargin
breakTorque = measured torque x Rules.PHYS.jointBreakMargin
floored so a joint under nothing is not released by its own settling. Nothing is
guessed. Sizing the ANGULAR threshold from the measured torque rather than from
the linear one is what stopped the bridge and the gate collapsing on their own:
a cantilevered deck rests under 180 Nm of angular reaction and almost no force,
so a threshold derived from the force alone released on the first step.
Home is re-read at arming, so settling is never scored as damage, and a
structure that failed to stand up is reported instead of counted as the
player's work.
Every frame a block that moved is clamped to Rules.PHYS.debrisMaxSpeed and
debrisMaxSpin - the governor that stands in for CCD, which is off on every body
here - and scored: displaced by mass, off the table, and a structure past
toppleFraction going through Game.recordTopple for the chain. A block reaching
the playroom floor is despawned a couple per frame so a wave of debris does not
rebuild the solver's islands at once.
Painted wood: ten materials over one generated grain texture, each structure
turned off the grid and each free-standing stack given a per-block twist, so a
tower reads hand-stacked. A block's yaw is why the joint anchors are rotated
into each body's own frame before they are handed over.
Verified in play at 1080x1440: 17 structures, 143 blocks, 126 joints, all
standing and nothing displaced after a rebuild. A boosted launch down the middle
lane toppled 8 towers with the chain reaching 8 and the multiplier 4.5, for
35220. A repeatable 40 kg strike topples 2-4 and the census reads back the
standing count the capture shows. The antenna mast clipped at 12.6 m keeps
blocks 1-8 within 0.02 m of where they were built and loses only the top four;
the same mass into a skyscraper's base shoves its bottom four storeys 4.8 m
along the table still stacked at their own heights. Physics step median 0.16 ms
across every run, 0.53 ms peak over a full collapse on a quiet engine, ccdMs 0
throughout, and no loose body above the debris clamp once everything rests.9bd5d5f726camera-director: the chase camera's feel and the staged beats
ChaseCamera is the only writer of the rig; Director writes an override pose
into game.camera.cam and ChaseCamera blends the frame toward it, so a staged
move can land on the live chase pose with no seam.
- chase feel: speed pushes back and opens the lens, boost adds to both, a
stopped airframe is closed in on, decaying shake / lens punch / distance
kick, and a slow handheld sway
- every distance is a multiple of the toy's own measured span, so the rig
reframes itself if the model changes size
- every fov is authored at the filmed 3:4 and carried to any screen: wider
keeps the vertical lens, taller opens it partway and stands further off
- beats: an opening flythrough over the block city that lands on the launcher
and releases the state to wind, a launch kick, impact shake, a topple that
dips the clock to 0.35 and leans the aim onto the tower, a wreck orbit that
cuts to a low close station for the tally, and an end-card wide
- the staged holds clear their line of sight, so a wreck among the towers is
not filmed from inside a block24e9b2ab0aflight: the toy 767 flies, breaks and answers every device
The airframe slice, end to end.
Launcher: steer x trims the heading, steer y trims the launch elevation, and
Launch throws the toy along the nose it is pointing. Every sign was read back
off the running airframe rather than assumed.
Flight: a force-driven arcade model. The nose follows the stick, the velocity
is pulled onto the nose over followTime, the wings hand back the share of
gravity they carry, Boost adds speed and Dive spoils the lift. The speed the
model asks for is clamped to the Rules.PHYS envelope before a Newton is spent,
and anything above the cap is taken back the same frame. Bounded authority, so
a block still knocks the toy off its line. Once it has been scraping the table
for a moment the model stands down and lets friction end the round.
Damage: contacts past impactThreshold raise impact on the bus and fill a damage
pool; each whole point sheds the part the hit landed nearest, hiding the art
slice's child and dropping a bounded loose copy with partLost. A missing wing
costs lift, authority, and rolls the toy toward the hole; a missing engine
costs half the thrust; a missing tail costs the pitch damper. Loose parts are
speed- and spin-clamped every frame and culled below the playroom floor.
Pause freezes this airframe where it hangs and hands its speed back on resume.
Controls carry keyboard, gamepad and touch on every action: Boost moved to the
right trigger, the stick got a radial deadzone and smoothing, and the touch
column reads Launch (large) / Boost / Dive / Menu down the right edge. The map
still suppresses the engine's walking scheme.
Verified in play at 1080x1440, with each input family alone: aim, launch,
climb, bank, boost, dive and pause on keyboard, on a simulated pad and on the
on-screen controls; a run into the city shed a wing and an engine and the toy
visibly spiralled after; Physics.bodyState never read past
Rules.PHYS.planeBoostSpeed over a boosted run; every round ended in wreck with
the next plane back on the launcher; 150 rigid bodies, none with ccd = true.
---
playroom-set: the window is lit and the table is not in its shadow
Model carries a castsShadows field. It is not in the Model component README's
list of public fields, and reading the render-layer documentation - which says
a layer hides an entity from a camera 'while it still exists for lighting,
shadows and physics' - had settled the question the other way. So the emissive
pane outside the window had been removed: it stands between the low sun and the
only opening in the room, and it shadowed the whole table, opaque or transparent.
With castsShadows = false on that one mesh the window is the brightest thing in
the game again and the sun still rakes the full length of the table. The sky
itself drops to a dim warm fill, which is what it should have been all along -
its image-based light reaches an enclosed room as though the room were not
there, so it was the sky's brightness, not the window's, that was flooding
every painted surface.
Luma spread at the launcher station goes from 75 to 113, with nothing crushed
and nothing clipped. The grade still costs 0.16 ms of GPU per frame.63531fa493sound: the whole mix — seamless PCM bed and playroom ambience, a motor that follows the airframe, the wooden one-shot library, and the Kid, voiced and captioned85f2d54becplayroom-set: the room the table stands in — painted wood, a window with afternoon in it, and the game's photographic finish
The set slice builds the whole playroom around the plan's table slab: floorboards
and a rug twelve metres below the table edge, four walls and a ceiling, a wide
window down the sunny side, skirting, a dado rail, framed pictures, a shelf of
toys, a toybox with its lid open and a floor lamp in the corner. The table gets
an apron and four legs so its edge - and the drop past it - reads.
One procedural shader, playroom_paint, is every wooden surface in here: grain
streaks along the board, a seam and a per-board tint across it, and wear patches
that rub the paint back. It is built from world position, so a 48 m table slab
and a 3 m skirting board carry grain at the same physical size.
One post-process pass, playroom_grade, is the whole photographic finish: a
tilt-shift band, a bloom on the window light, a warm split-toned grade and a
vignette. 0.16 ms of GPU per frame at 1080x1440, measured against the pass it
replaces. The band is a fraction of screen HEIGHT and the vignette is measured
square-corrected, so a tall frame and a wide one get the same look.
The scene's sun, ambient and sky are retuned by name: a low warm key from the
window side, a cool dim fill under it, and the plan's ProceduralSky swapped for
a flat warm Skybox - the procedural sky was driving the sun's own direction from
its time of day and lighting an indoor room with an outdoor blue.
The only collider the slice owns is the floorboards, 2.6 m below
Rules.TABLE.floorY, so a block that leaves the table is culled before anything
here can catch it.6d371c35dbplane-art: consistently wound lofts, honest part pivots, bolder toy livery, and the art contract written down60bb8f71cdplane-art: the toy 767 as a made thing — procedural fuselage, swept wings, underslung engines with fan faces, tail, fin, wind-up key, and one painted atlas7b745c69c7plan: BLOCKBUSTER 767 — spec, scene, rules/game modules, slice skeletons