1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
//! Gravity, air, wind, collision, and force fields of your own.
//!
//! Anything that falls in a cart used to be written the same three ways: a `vy` kept next to the
//! entity's position, a constant added to it every update, and a cap so that a long drop does not
//! end with the entity a screen below the floor. This module gives those pieces names, and then
//! takes them off the cart's hands altogether.
//!
//! A [`World`] *owns* the scene's moving matter. A cart describes each member in turn with
//! [`Member::builder`] — where this one stands, how big it is, what it wears, what stops it —
//! [enlists](MemberBuilder::enlist) it into the world, and keeps the [`MemberId`] it gets back
//! beside its own game data. Where each member is, how fast, what rectangle it covers and what it
//! last ran into are the world's, stored once, and asked of the member the id names, borrowed from
//! the world: `world.member(hero).draw_pos()`, `world.member(hero).contacts()`,
//! `world.member_mut(hero).set_velocity(v)`. Forces act on velocity, never on position, and no
//! member moves itself. One [`step`](World::step) an update runs the scene's weather over every
//! velocity, stops whatever ran into the map's tiles or into the rest of the cast, holds each
//! member inside the rectangle it may not leave, moves the bodies by what survived, and writes down
//! what everybody met. One call a scene, an update. And one [`draw`](World::draw) a frame puts the
//! whole cast on screen, where the step left it and looking the way the update said, so a cart's
//! `draw` is one call and whatever it paints of its own.
//!
//! The weather belongs to the scene rather than to the things in it: the same gust that bends the
//! whole cast is one [`Wind`] the world [owns](World::with_forces), driven where it lives.
//!
//! Nothing here allocates or pulls in a dependency; a force costs a couple of floats and a
//! multiplication or two an update.
//!
//! Everything here stays in this module — a cart's `use pixel8::*;` does not reach it, so name
//! what the game needs:
//!
//! ```no_run
//! use pixel8::{
//! physics::{Atmosphere, Gravity, Member, MemberId, Wind, World},
//! *,
//! };
//!
//! struct Autumn {
//! // The scene: sixteen seats of leaf, and the whole of the weather they fall through — the
//! // pull, the air, and a wind that gusts, and so changes from one update to the next.
//! world: World<16, (Gravity, Atmosphere, Wind)>,
//! leaves: [MemberId; 16],
//! // The cart's own, which the world has never heard of: how many leaves the player caught.
//! caught: u16,
//! }
//!
//! impl Autumn {
//! fn new() -> Self {
//! let mut world = World::new()
//! .with_forces((Gravity::new(), Atmosphere::new(), Wind::new(0.4)));
//! let leaves = core::array::from_fn(|i| {
//! Member::builder(i as f32 * 8.0, 0.0, 4, 4)
//! .wearing(SpriteId(1))
//! // A leaf weighs next to nothing, so the wind has three times the grip on it —
//! // and the still air three times the drag. Gravity does not read this:
//! // everything falls alike.
//! .weighing(0.3)
//! .enlist(&mut world)
//! .expect("a seat apiece for sixteen leaves")
//! });
//!
//! Self { world, leaves, caught: 0 }
//! }
//! }
//!
//! impl Game for Autumn {
//! fn update(&mut self, ctx: &mut Context) {
//! // The gust first, where it lives, so every leaf is bent by the same one.
//! self.world.forces_mut().2.update(ctx);
//! self.world.step(ctx);
//! }
//!
//! fn draw(&self, gfx: &mut Graphics) {
//! gfx.clear(Color::BLACK);
//! self.world.draw(gfx, BitFlags::empty());
//! }
//! }
//! ```
//!
//! # Units
//!
//! Velocities are in pixels per update and accelerations in pixels per update squared — the units
//! [`Body::move_by`](crate::Body::move_by) already speaks. They are per *update* and not per
//! second, so a 30 fps cart tunes its constants, exactly as it already must for everything else it
//! moves.
//!
//! # Mass
//!
//! [`MemberBuilder::weighing`] is how hard a member is to push, relative to everything else in the
//! scene: `1.0` is the default nobody has to think about, `4.0` takes four times the shove for the
//! same movement and `0.25` a quarter of it. A member opts in by saying so once, and a cart that
//! never mentions mass carries on exactly as it did.
//!
//! What to make of it is each force's business. [`Wind`] divides its grip by mass, so the gale
//! that carries a leaf off barely stirs a boulder beside it, and [`Atmosphere`] divides its drag
//! by it in the same way. [`Gravity`] never reads it at all: everything falls alike, whatever it
//! weighs. Mass is how hard a thing is to push, not how hard it falls — the feather and the anvil
//! are told apart by the air between them, not by the pull.
//!
//! # Gravity
//!
//! [`Gravity::new`] is the pull a platformer usually arrives at by trial and error: a quarter of a
//! pixel per update squared, and a fall that tops out at four pixels an update. The terminal
//! velocity is the part worth keeping even when the strength is retuned — without it, a long fall
//! ends with the member moving further in one update than a wall is thick, and it goes straight
//! through.
//!
//! It pulls whichever way it is pointed, so a cart is not stuck with down:
//!
//! ```no_run
//! # use pixel8::{physics::Gravity, Direction};
//! // The moon: an eighth of the pull, and nothing falls very fast there.
//! let moon = Gravity::new().with_strength(0.03).with_terminal_velocity(1.5);
//! // A station spinning the other way up, or a room the player has walked into upside down.
//! let ceiling = Gravity::new().with_direction(Direction::Up);
//! ```
//!
//! # Atmosphere
//!
//! Gravity's cap is the cheap way to keep a fall in hand. [`Atmosphere`] is the honest one: air
//! that takes a share of whatever moves through it, every update, on every axis. A fall under it
//! settles because the drag grows with the speed until it matches the pull, and sideways motion
//! slows too — which the cap never did.
//!
//! Where gravity is blind to [mass](MemberBuilder::weighing), the air is not, and that is what
//! finally tells the feather from the anvil: the same air takes a great share of the light thing
//! and almost nothing of the heavy one, so the feather settles to a drift while the anvil goes on
//! gaining. [`Atmosphere::new`] is air at sea level, tuned so that a `1.0`-mass body settles
//! exactly where the default [`Gravity`] would have capped it.
//!
//! The two work together — a cart wanting the air alone to decide its terminal velocity puts
//! gravity's cap out of the way with `with_terminal_velocity(f32::MAX)` — and
//! [`Atmosphere::vacuum`] is the airless version, where nothing drags and everything falls
//! forever.
//!
//! # Wind
//!
//! A [`Wind`] is named for the side it comes *from*, the way weather always is: the default blows
//! in over the left edge of the screen and pushes things to the right. Unlike gravity it does not
//! accelerate what it pushes forever — velocity eases *towards* the wind's speed and stops there,
//! which is the drag a real wind has. How fast it gets there is
//! [`with_exposure`](Wind::with_exposure) — a leaf takes the wind almost at once, a boulder barely
//! notices it — divided by what the member itself weighs, so something heavy enough shrugs off a
//! wind it is fully exposed to.
//!
//! A steady wind is a constant. [`with_gusts`](Wind::with_gusts) makes its speed wander inside a
//! range instead, never quite repeating itself, which is what stops a windy scene from reading as
//! a scrolling texture. Gusty wind needs [`update`](Wind::update) once an update, before it is
//! handed to anything.
//!
//! # Collision
//!
//! Nothing here asks a cart to walk its own pairs, and nothing asks a member to detect anything. A
//! member's [enlisting](Member::builder) only *describes*: the rectangle it covers, the flags that
//! stop it, the sprite it wears, how far it is let go. [`World::step`] does the rest for the whole
//! cast — it stops each member at
//! everything solid to it, tiles and cast alike, and writes the flags of everything it ran into
//! into that member's [`contacts`](Member::contacts). The cart enlists and reads; it never detects.
//!
//! Every member covers one rectangle — [`Member::bounds`] — because that is what the step is judged
//! over, and the same rectangle answers the two questions a cart asks off its own bat:
//! [`Bounds::overlaps`] against a rectangle it knows about already, and [`Bounds::on_screen`] for
//! something that has left the screen altogether.
//!
//! ```no_run
//! # use pixel8::physics::{Bounds, MemberId, World};
//! /// A bullet against the doors the level put down once — and nothing at all once it is off
//! /// screen.
//! fn hit(world: &World<8>, bullet: MemberId, doors: &[Bounds]) -> bool {
//! let bounds = world.member(bullet).bounds();
//!
//! bounds.on_screen() && doors.iter().any(|door| bounds.overlaps(*door))
//! }
//! ```
//!
//! ## What is in the way
//!
//! The map is the level standing still, and the console has always answered for it: what a scene
//! calls a wall is a sprite flag, named once on the world in [`World::with_solid`], and every
//! member stops at every tile carrying it, over the rectangle it covers everywhere else. It is the
//! flag a cart already marks its walls with for [`Graphics::map`](crate::Graphics::map). A member
//! the scene's word does not fit is [`stopped_by`](MemberBuilder::stopped_by) rules of its own,
//! which replace the world's for that member alone.
//!
//! The tiles taught the console one vocabulary — a thing *is* whatever flags it carries, written
//! once in the sprite editor — and the cast speaks it too. [`MemberBuilder::wearing`] is where a
//! member says which cell it wears, and the flags on that cell are what everybody else meets when
//! they meet it. So one [`World::step`] settles both: a flag shared with `solid` stops the member,
//! whether it is on a tile or on a neighbour, in the same one-axis-at-a-time pass; a rising lift
//! pushes the rider standing on it and the rider goes on reading [`below`](Contacts::below); and
//! everything met, wall or not, tile or member, comes back in [`Contacts::touched`]. One step
//! answers the three questions an update asks at once: am I grounded, am I in the water, did I walk
//! into the badie.
//!
//! Three flags, three directions, and they are the whole of it:
//!
//! * [`stopped_by`](MemberBuilder::stopped_by) — which flags are a **wall to me**. The world's word
//! ([`World::with_solid`]) by default, and rules of this member's own where it gives them; under
//! a world that declared nothing, nothing anywhere stops it.
//! * [`wearing`](MemberBuilder::wearing) — which cell I **wear**, and so which flags others meet in
//! me. Nothing by default: nobody is stopped by it, and nobody is told about it. It is still
//! stopped by everything, and still told everything — a sensor needs no flag of its own.
//! * [`heeding`](MemberBuilder::heeding) — which flags I **care to be told about**. Everything by
//! default, which is why a cart never has to think about it until it wants to.
//!
//! ## What a member cares to meet
//!
//! A member describes what it wants to hear about, and the world spends nothing on the rest. That
//! is [`heeding`](MemberBuilder::heeding), and it is the one place a cart can make a scene cheaper
//! by saying something true about it: a bullet fired at the enemy cares about the enemy and about
//! nothing else in the sky — not the other bullets beside it, not the tiles scrolling past behind
//! it. Say so, and a neighbour carrying nothing it heeds is refused before a single edge of that
//! neighbour is worked out, and a tile's flags are dropped before they are collected. In a scene
//! where everything is in one cast, that is most of the work of an update, and it is spent on
//! answers nobody was going to read.
//!
//! The promise stays one sentence, whatever a cart narrows: **you are told what you heed, and you
//! are stopped by what you call solid.** `solid` is heeded whether it was named or not, so
//! narrowing this can never cost a member a wall — one it never asked to hear about still stops
//! it, and being stopped by it still reports it. And it reads the same off a tile as off a
//! neighbour: the mask is one word, applied to the one vocabulary.
//!
//! A whole scene can say the same thing about its map. [`World::mapless`] is a world whose tiles
//! are the picture behind the fight and nothing else — a shoot-'em-up scrolling a landscape past,
//! anything whose collisions are all between moving things — and its steps never ask the map a
//! question. [`World::new`] is unchanged and reads the map as it always has.
//!
//! ```no_run
//! # use pixel8::{physics::{Member, MemberId, World}, *};
//! # const AIRCRAFT: SpriteFlag = SpriteFlag::Flag0;
//! # const ENEMY_SHOT: SpriteFlag = SpriteFlag::Flag1;
//! // The level scrolls past behind the fight; nothing on it is in anybody's way.
//! const SKY: World<32> = World::mapless();
//!
//! // And she is rammed and she is shot, and the rest of the sky is somebody else's business.
//! # fn f(sky: &mut World<32>) -> MemberId {
//! Member::builder(60.0, 100.0, 8, 8)
//! .heeding(AIRCRAFT | ENEMY_SHOT)
//! .enlist(sky)
//! .expect("a seat for the aircraft")
//! # }
//! ```
//!
//! Stopping and meeting are answered over different ground. A member is *stopped* where an axis
//! was trying to go — the endpoint, which is where a wall has to be to be one — and it is told what
//! it *met* over the whole of the step: where it began, the ground each axis swept across, and
//! where it ended up. So a member that walks out of the water this update is told it was in the
//! water, and a hazard crossed between one pixel and the next is named rather than missed. The
//! difference has one consequence, and it is better said than discovered: something thinner than an
//! update's movement can be stepped clean over without stopping the member, and is reported all the
//! same. [`Gravity`]'s terminal velocity is the guard — nothing moving slower than a wall is thick
//! can pass through one — which is exactly why it is there.
//!
//! ```no_run
//! # use pixel8::{physics::{Gravity, MemberId, World}, *};
//! # const WATER: SpriteFlag = SpriteFlag::Flag3;
//! # fn f(world: &mut World<4, Gravity>, ctx: &Context, hero: MemberId) {
//! world.step(ctx);
//! let contacts = world.member(hero).contacts();
//! let (grounded, swimming) = (contacts.below(), contacts.touches(WATER));
//! # }
//! ```
//!
//! ## The cast, and the order it is in
//!
//! The cast is the world's own: `N` seats, filled by [`enlist`](MemberBuilder::enlist) and emptied
//! by [`retire`](MemberMut::retire), and nothing to gather at the top of an update. Three things
//! follow, and they are the whole of the contract:
//!
//! * **Same frame.** Everybody is where they are. A member meets its neighbours at the rectangles
//! they cover *now*, not at a picture of them taken earlier, so a shot that lands is a hit its
//! target feels in the same update, and something that dies on arrival can be retired the moment
//! the step returns.
//! * **Seat order.** Members are stepped one at a time, lowest seat first, and each of them meets
//! the ones stepped before it where they have *just* moved to. So a lift enlisted before its
//! rider carries the rider with no lag at all, and one enlisted after it is a frame behind.
//! Enlist the cast the way the scene works. A seat freed by `retire` is the next one filled, so
//! the order a scene is seated in is the order it keeps. It is the order the cast is
//! [drawn](World::draw) in, too: a later seat over an earlier one. Where the two orders pull
//! apart — a shot takes whatever seat is free, yet belongs under the aircraft whichever it was —
//! [layers](#drawing) are the way out.
//! * **Never itself.** The world knows who is who — a member is simply left out of its own
//! questions — so a member's own kind is a wall like anybody else's. Two crates whose
//! [`wearing`](MemberBuilder::wearing) cell carries `CRATE`, each with `CRATE`
//! [solid](MemberBuilder::stopped_by) to it, block each other and neither is ever shoved off its
//! own feet.
//!
//! And one refinement for the things a cart drives itself: a member that says it is a
//! [prop](MemberBuilder::prop) is met and never moved. Its rectangle and its flags stand in
//! everybody's way from wherever the cart last [put](MemberMut::set_pos) it — a hazard patrolling
//! a fixed beat, a lift on a track — and the forces, the walls and the contacts all pass it by.
//!
//! ```no_run
//! # use pixel8::{physics::{Bounds, Gravity, Member, MemberId, World}, *};
//! /// Walls and floors are whatever the cart flagged as such in the sprite editor.
//! const SOLID: SpriteFlag = SpriteFlag::Flag0;
//! /// And this walker's own sprite is flagged `WALKER`, which is how everybody else's step reports
//! /// having met one — and how two walkers come to be walls to each other.
//! const WALKER: SpriteFlag = SpriteFlag::Flag1;
//! /// The cell it is drawn from, which is where that flag is written.
//! const WALKER_SPRITE: SpriteId = SpriteId(4);
//!
//! struct Walkers {
//! world: World<3, Gravity>,
//! walkers: [MemberId; 3],
//! }
//!
//! impl Walkers {
//! fn new() -> Self {
//! // The level's pull, and the level's word for a wall, both said once on the world.
//! let mut world = World::new().with_solid(SOLID).with_forces(Gravity::new());
//! let walkers = core::array::from_fn(|i| {
//! // One sprite's worth: what a wall stops, and what everything else judges it by.
//! // What it is made of, so that everybody who meets it is told they met a walker. And
//! // what is a wall to it — a rule of its own rather than the scene's, because its own
//! // kind is in it, which no world-wide word could say for walkers alone. Plus the
//! // edge of the world, which is not a wall and is on no tile.
//! Member::builder(i as f32 * 24.0, 64.0, 8, 8)
//! .wearing(WALKER_SPRITE)
//! .stopped_by(SOLID | WALKER)
//! .confined_to(Bounds::screen())
//! .enlist(&mut world)
//! .expect("a seat apiece for three walkers")
//! });
//!
//! Self { world, walkers }
//! }
//!
//! /// What the buttons ask for, written into each velocity before the world runs.
//! fn steer(&mut self, ctx: &Context) {
//! for walker in self.walkers {
//! // Borrowed for the few lines that change it, and let go before the next one.
//! let mut walker = self.world.member_mut(walker);
//! let mut velocity = walker.velocity();
//! if walker.contacts().below() && ctx.is_button_pressed(Button::O) {
//! velocity.dy = -3.25;
//! }
//! velocity.dx = if ctx.is_button_down(Button::Left) {
//! -0.7
//! } else if ctx.is_button_down(Button::Right) {
//! 0.7
//! } else {
//! 0.0
//! };
//! walker.set_velocity(velocity);
//! }
//! }
//!
//! fn update(&mut self, ctx: &mut Context) {
//! self.steer(ctx);
//! // The pull, the walls, the walkers and the movement, in one call.
//! self.world.step(ctx);
//! }
//! }
//! ```
//!
//! Where that setting-up goes is the cart's business, and a cart that ships its state placed —
//! [`game!`](crate::game) with a constant initializer — has an obvious place for it. A world is a
//! constant: [`World::new`], [`World::mapless`] and [`with_forces`](World::with_forces) are all
//! `const`, so the scene itself is part of the cart's memory image. Seating the cast is not — it is
//! the world handing out seats — so it happens in [`Game::boot`](crate::Game::boot), where
//! [`with_solid`](World::with_solid)'s in-place twin [`declare_solid`](World::declare_solid) says
//! the scene's word for a wall too. `examples/platformer` is written that way.
//!
//! One rectangle does both jobs, so a wall stops a member exactly where another member would have
//! hit it.
//!
//! Flags say what *kind* of thing was met and never which one — two patches of water read as one
//! patch of water, and one badie reads like another. A cart that must know which, because
//! something has to happen to it, already holds the handle: it looks at its own state, and compares
//! [`Member::bounds`] if it must ask a rectangle anything at all. The step says *the hero met a
//! badie*; which badie, and what it costs the hero, is the cart's and was never anybody else's.
//!
//! ## The edge of the world
//!
//! The last thing a member runs into is not a wall and is nowhere on the map: nothing stops it
//! walking off the last tile and falling for ever. [`MemberBuilder::confined_to`] is where it says
//! it may not — [`Bounds::screen`], or the level itself where that is the bigger of the two — and
//! [`World::step`] holds it there, putting the rectangle back against the edge and spending the
//! speed that took it out, exactly as a wall would have. It is declared once, with everything else
//! a member is enlisted under, rather than enforced by a call an update can forget; the sides it
//! was held at arrive in the same [`Contacts`], so a hold at the bottom of the level reads
//! [`below`](Contacts::below) as a floor tile does. A room the player walks into changes them with
//! [`MemberMut::set_confines`].
//!
//! Saying nothing — the default — is a member free to leave, which is what a bullet or a spent
//! enemy wants: it walks off the map, and the cart [retires](MemberMut::retire) it when
//! [`Bounds::on_screen`] says it has gone.
//!
//! # Drawing
//!
//! The world draws its cast as it steps it. One [`World::draw`] a frame puts every member on
//! screen where the last step left it, and what it draws is the member's *look*, which is the
//! world's like everything else about it: the cell it [wears](MemberBuilder::wearing), which way
//! round it faces ([`flipped`](MemberBuilder::flipped), [`set_flip`](MemberMut::set_flip)), how
//! many cells of the sheet it spans ([`spanning`](MemberBuilder::spanning),
//! [`set_span`](MemberMut::set_span)), and whether it is shown at all
//! ([`hidden`](MemberBuilder::hidden), [`set_hidden`](MemberMut::set_hidden)). A member that wears
//! nothing is not drawn: nobody is stopped by it, nobody is told about it, and nobody sees it
//! either.
//!
//! The look is decided in the update, beside the velocity, by the code that knows why it changed:
//! a walker turns round in the update that turned it, and puts on the next cell of its walk in the
//! update that carried it there. By the time [`Game::draw`](crate::Game::draw) runs — holding the
//! game by `&self` — there is nothing left to decide, and only the showing to do:
//!
//! ```no_run
//! # use pixel8::{physics::{Member, MemberId, World}, *};
//! /// Two cells of a walk, flagged alike on the sheet: which one is worn changes how the walker
//! /// looks and nothing about what it is met as.
//! const WALK: [SpriteId; 2] = [SpriteId(16), SpriteId(17)];
//!
//! struct Stroll {
//! world: World<1>,
//! walker: MemberId,
//! }
//!
//! impl Game for Stroll {
//! fn update(&mut self, ctx: &mut Context) {
//! let mut walker = self.world.member_mut(self.walker);
//! let mut velocity = walker.velocity();
//! velocity.dx = if ctx.is_button_down(Button::Left) {
//! -1.0
//! } else if ctx.is_button_down(Button::Right) {
//! 1.0
//! } else {
//! 0.0
//! };
//! walker.set_velocity(velocity);
//! // How it looks, said beside how it moves: facing the way it was last sent, and a step
//! // of the walk for every four pixels it has come.
//! if velocity.dx != 0.0 {
//! walker.set_flip(velocity.dx < 0.0, false);
//! }
//! let (x, _) = walker.draw_pos();
//! let stride = WALK[(x / 4).rem_euclid(2) as usize];
//! walker.set_sprite(Some(stride));
//!
//! self.world.step(ctx);
//! }
//!
//! fn draw(&self, gfx: &mut Graphics) {
//! gfx.clear(Color::BLACK);
//! self.world.draw(gfx, BitFlags::empty());
//! }
//! }
//! ```
//!
//! Seat order is drawing order, as it is stepping order: a later seat is drawn over an earlier
//! one. A scene that wants it otherwise draws in layers, and `draw`'s `layers` is the very filter
//! [`Graphics::map`](crate::Graphics::map) takes — an empty set draws everybody, and anything else
//! only the members whose worn cell carries one of those flags. It is one call a layer, and
//! whatever draw state a layer needs — a transparency, a palette swap for a hurt flash — is set
//! around its call, as it would be around a `map`.
//!
//! Everything that is not a member is the cart's, drawn before the cast or after it: the map
//! behind it, the HUD over it, a particle effect, the line of a rotor at a member's
//! [`draw_pos`](Member::draw_pos).
//!
//! # Forces of your own
//!
//! A [`Force`] is one method, so a cart's own force fields — a current, a magnet, the drag of deep
//! water — work everywhere the ones here do: hand [`with_forces`](World::with_forces) a tuple with
//! them in it and the world owns the lot, applying it to every member it moves — a
//! [prop](MemberBuilder::prop) steers itself, so no force bends one — before any of them takes a
//! step:
//!
//! ```no_run
//! # use pixel8::{physics::{Force, Gravity, Subject, World}, Context};
//! /// Water: it drags whatever moves through it, and it holds it up a little.
//! struct Water {
//! drag: f32,
//! }
//!
//! impl Force for Water {
//! fn apply(&self, subject: &mut Subject) {
//! // Something heavier carries its momentum through the water further, so the drag eases
//! // it less; the clamp is what stops a light enough diver being dragged past a halt.
//! let drag = (self.drag / subject.mass()).clamp(0.0, 1.0);
//! let velocity = subject.velocity_mut();
//! velocity.dx -= velocity.dx * drag;
//! velocity.dy -= velocity.dy * drag;
//! }
//! }
//!
//! /// The pull down there, which is the level's own with the fall taken out of it.
//! const SINKING: Gravity = Gravity::new().with_terminal_velocity(0.8);
//!
//! /// The pool: its own pull and its own drag, owned by the world that will do the stepping.
//! fn pool() -> World<8, (Gravity, Water)> {
//! World::new().with_forces((SINKING, Water { drag: 0.3 }))
//! }
//!
//! fn sink(world: &mut World<8, (Gravity, Water)>, ctx: &Context) {
//! world.step(ctx);
//! }
//! ```
//!
//! Which order they run in is the cart's to choose, and it is the tuple's: a tuple of forces is
//! one [`Force`], applied front to back. The difference is one update's worth either way — a drag
//! that runs before this update's pull has not felt it yet — so it shows in where a fall settles,
//! not in how it looks.
//!
//! # What it costs
//!
//! A seat is the forty-four bytes of the record it crosses the ABI in, plus nine the world keeps
//! beside it, held for as long as the world lives. That is not fewer bytes than the same fields
//! kept in a cart's own structs — it is a few more — and it is the wrong thing to count. What
//! single ownership buys is that nothing is ever copied: the step hands the console the world's own
//! array and the console answers into it, so a cart pays for one call an update and not for a
//! marshalling loop over its cast. The collisions themselves are the console's native work and cost
//! a cart no fuel at all. The same array goes across again to be drawn, and the console draws it
//! natively too: one call a frame, however long the cast.
pub use Atmosphere;
pub use Bounds;
pub use ;
pub use ;
pub use Gravity;
pub use Kinetic;
pub use ;
pub use Velocity;
pub use Wind;
pub use World;