Repository navigation
Commit e616265
Examples: Earth Defender, an arcade shooter on a globe (#1749)
* Examples: Earth Defender, an arcade shooter on a globe
Fly a craft over a hexagonal glass dome, shooting the asteroids falling onto
it. The dome is what is being defended: each pane cracks and finally shatters,
and the run ends when the glass does.
It exercises a lot of the 3D tier at once, which is why it is worth having:
- `Camera3d` posed from the player's own surface point with `setBasis`, so the
player orbits a fixed globe rather than the globe turning underneath them
- ground shadows on a sphere via `shadowGroundPoint` and `shadowGroundNormal`,
where "down" is radial rather than world down
- `Sphere` collision shapes, `raycast3d`, mesh-hosted `ShaderEffect` for the
shield bubble and the atmosphere, `Trail3d` for the exhaust
- spatial audio with a listener following the craft, HDR with bloom and tone
mapping, `ProgressBar` and `UIPanel` for the HUD and the pause menu
- sprite-sheet particles for the debris
All of the maths lives in `lib/sphereMath.ts`, which is spherical rather than
planar: positions are unit vectors, distances are arcs in radians, and motion
is rotation within a plane so a body can circle all day without drifting off
the sphere. It has its own characterisation test, `sphereMath.test.ts`, run
with `npx tsx` from `packages/examples`: 112 assertions, 32 of them golden
values and the rest invariants that hold whatever the implementation is.
Assets are credited in `packages/examples/LICENSE.md`. The Earth, the dome and
the asteroids were modelled for this; the saucer, the bomb, the sound effects
and the font come from elsewhere and are CC0 or CC BY-ND.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
* Examples: say what Earth Defender shows, in the gallery and the README
The gallery card read "Fly a craft over a globe, shooting asteroids off a
hexagonal shield dome", which says what the player does and nothing about why
the example exists. Its neighbours name the engine features and the controls:
AfterBurner lists `Camera3d`, `raycast3d` and `Box3d` with its keys, Jungle
Rabbit lists `InstancedMesh` and the rigged boat. This one now does the same,
and gives the controls, which no description without them can supply.
Also adds it to the README's example list, which it was missing from, next to
the other 3D entries.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
* Examples: the gallery card is about the tech, not the keys
Earth Defender and AfterBurner both spent their last clause listing controls,
which the example itself tells you and which is not why either one is in the
gallery. Both now stop at what they demonstrate. Earth Defender also names
what it is a tribute to, which places it faster than any feature list does.
No em dashes in either description.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
* Examples: Stardust is already on a globe
"A Stardust tribute on a globe" says the globe twice to anyone who knows the
reference, and the reference is doing the work.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
* Examples: reunite twelve doc comments with what they document
A doc comment followed by another doc comment documents nothing: the second
one wins and the first is dropped. Twelve of them had drifted apart from
their declarations here, including `deflect`'s, which I split from its own
method earlier in this branch by inserting `shove` between the two.
Nine moved back to the declaration they describe, all of which had no doc at
all until now: `deflect`, `onShipHit`, `tickShield`, `placeWorld` and
`drainHits` in the controller, `burst` in the blast pool, `nebulaField`, and
`ringBasis` and `sightlineClearance2` in the sphere maths.
Three were stale rather than misplaced, and are deleted:
- a glTF descriptor helper that no longer exists in the controller, since
`loader.getGLTF` is called directly now
- a menu key-edge helper whose logic moved to `TitleScreen.pressed` and
`seedHeld`, both of which carry the explanation already
- an older signature of `burst`, from before it took `outward`, `speed`,
`life` and `spread`; the fuller one directly below it is current
The sphere maths file header is marked `@module`, which is what makes a
leading comment the module's own rather than a comment that happens to sit
above the first declaration.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGvtaUNATVCVxD2qcbiY4t
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 82df72b commit e616265
64 files changed
Lines changed: 18633 additions & 2 deletions
File tree
- packages/examples
- public/assets/earthDefender
- bgm
- font
- sfx
- src
- examples/earthDefender
- entities
- fx
- lib
- scenes
- shaders
- ui
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
| 195 | + | |
195 | 196 | | |
196 | 197 | | |
197 | 198 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
110 | 176 | | |
111 | 177 | | |
112 | 178 | | |
| |||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
0 commit comments