samples/PhysicsDemo ties physics, audio, input, and rendering together through nothing but the kernel's own vocabulary — no plugin here references another plugin's implementation, only Contracts. Press Space to drop a box; engine.physics simulates it falling onto a static ground; CubeRenderer (new — engine.render's QuadRenderer drew flat cards, no good for a physics demo where a BoxCollider needs to actually look like a box) draws it; physics-demo-game watches each spawned box's own Y velocity via IPhysicsService and plays a bounce sound via IAudioService the moment a real fall settles. A looping ambient track plays throughout via AudioSource's own PlayOnAwake. project.json deliberately excludes engine.editor — this is the shippable configuration M4's "done when" actually asks for, not the dev one. "Landed" isn't a Box3D contact event — the native shim never exposed one (nothing but scalars crosses that boundary, see lingua_physics.c). Watching velocity every frame is the honest, right-sized alternative for a demo this size, not a shortcut around missing infrastructure. Verified two ways. First, real Space-key input isn't simulable here (no xdotool/ydotool under this Wayland session) — so PhysicsDemoGame.Tests drives the actual PhysicsDemoGamePlugin.Configure/Tick through the real Schedule with a controllable fake IEngineInput (and fake IPhysicsService/ IAudioService, since engine.physics/engine.audio's own correctness is already covered elsewhere): spawn-on-press with edge detection, the Rigidbody/BoxCollider/CubeRenderer combo the spawned box actually gets, and — the case most likely to be subtly wrong — a box that never actually falls doesn't false-positive as "landed," only one that fell past FallingThreshold and then settled does, exactly once. All 5 passed immediately. Second, a real windowed run: a box placed in scene.json above the ground visibly falls and settles onto it on screen after a real few-second wait — screenshotting by --screenshot-after-frames alone turned out not to prove this (VSync is off, so frames race by far faster than real physics time passes; enough elapsed frames isn't enough elapsed seconds), an interactive run with a real sleep before the screenshot command is what actually shows it. Full suite: 92 tests. Remaining for M4: the Linux + Windows build pipeline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N1qPfzq8TDCUMFMV3UwV5N
43 lines
1.7 KiB
JSON
43 lines
1.7 KiB
JSON
[
|
|
{
|
|
"name": "Ground",
|
|
"transform": {
|
|
"position": [0, 0, 0],
|
|
"rotation": [0, 0, 0, 1],
|
|
"scale": [8, 1, 8]
|
|
},
|
|
"components": [
|
|
{ "type": "Engine.Physics.Contracts.Rigidbody, Engine.Physics.Contracts", "data": { "Type": 0, "Friction": 0.6, "Restitution": 0.3 } },
|
|
{ "type": "Engine.Physics.Contracts.BoxCollider, Engine.Physics.Contracts", "data": { "HalfExtents": { "X": 4, "Y": 0.5, "Z": 4 } } },
|
|
{ "type": "Engine.Render.Contracts.CubeRenderer, Engine.Render.Contracts", "data": {} }
|
|
],
|
|
"children": []
|
|
},
|
|
{
|
|
"name": "DemoBox",
|
|
"transform": { "position": [0, 3, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1] },
|
|
"components": [
|
|
{ "type": "Engine.Physics.Contracts.Rigidbody, Engine.Physics.Contracts", "data": { "Type": 2, "Friction": 0.6, "Restitution": 0.3 } },
|
|
{ "type": "Engine.Physics.Contracts.BoxCollider, Engine.Physics.Contracts", "data": {} },
|
|
{ "type": "Engine.Render.Contracts.CubeRenderer, Engine.Render.Contracts", "data": {} }
|
|
],
|
|
"children": []
|
|
},
|
|
{
|
|
"name": "Music",
|
|
"transform": { "position": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1] },
|
|
"components": [
|
|
{ "type": "Engine.Audio.Contracts.AudioSource, Engine.Audio.Contracts", "data": { "ClipPath": "assets/music.wav", "Volume": 0.35, "Loop": true, "PlayOnAwake": true } }
|
|
],
|
|
"children": []
|
|
},
|
|
{
|
|
"name": "Bounce",
|
|
"transform": { "position": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1] },
|
|
"components": [
|
|
{ "type": "Engine.Audio.Contracts.AudioSource, Engine.Audio.Contracts", "data": { "ClipPath": "assets/bounce.wav", "Volume": 0.8, "Loop": false, "PlayOnAwake": false } }
|
|
],
|
|
"children": []
|
|
}
|
|
]
|