Throw and roll real objects #112

Open
opened 2026-10-20 23:40:41 +00:00 by sermuns · 0 comments
Owner

The campus has three thrown things and no way to throw them: a disc golf disc
on Rydskogen, a football at the soccer goals, and a boule on the gravel court
at Ryds motionscentrum. Each is a small rigid body — a disc that flies and
fades, a ball that bounces, a boule that rolls — and each has a scoring rule
attached to it.

Today the plan for all three is pure arithmetic: a throw is computed, a
position is compared to a target, and the answer is a hit or a miss. Rapier
gives them something better and, more usefully, gives them a shared
implementation: one thrown body with a mass, a restitution and a friction, and
a surface underneath it that decides what the body does when it lands.

What a physics body buys

  • A throw that misses because it was a bad throw. A boule thrown too hard
    overshoots the jack. A disc thrown flat drops. A football kicked from the
    wrong angle hits the post. The rule stays the same, but the skill becomes
    real, which is the whole point of a game about throwing.
  • One implementation for three sports. The disc, the football and the
    boule differ in mass, restitution, friction and shape, not in code. The
    scoring rules stay where they are — the football issue owns the goal, the
    disc issue owns the basket, the boules issue owns the round.
  • Things that are not thrown. A ball left on a pitch is still a ball. It
    rolls to a stop, and it stays there until somebody kicks it.

Where it fits

The thrown bodies are server-authoritative, like the vehicles. A score is
a score, so the rule that decides it belongs on the server, and the server is
already the thing that owns the vehicles and the day/night cycle. The bodies
live in the server's physics world, and their state travels on the wire.

That means a new ServerMsg variant, appended to the end (postcard tags a
variant by its position, so variants are appended and never reordered), and a
new ClientMsg variant for the throw itself. A thrown body on the wire needs
an id, a position, a rotation and a velocity — enough for a client to draw it
and to interpolate it between the 20 Hz updates. The bodies themselves are
drawn the way every other object is drawn: a SceneSpec object slot, not
baked geometry, because they move and they are not part of the campus.

The physics step belongs in liuverse-world, next to vehicle and trail,
because that is where the engine-free simulation lives and where the tests can
run without a GPU.

The surfaces

The interesting part of a thrown body is the ground it lands on, and the campus
has exactly the surfaces that would make it interesting: asphalt on the roads,
gravel on the paths, grass on the lawns, and ice at Isovalen in the winter.
Rapier pairs a friction and a restitution with a collider, so each of those
gets its own, and the same throw on gravel and on grass lands differently.

The material is not far off today. The bake buckets an area into an
AREA_* kind and gives each path a palette entry that picks one of three
ground tiles — grass, gravel, asphalt — so there is already a coarse material
under every path and area. Reading the exact surface= tag is the paths and
pitches work's job; the collision layer the physics engine needs can carry
the same tag once it exists, and the coarse bucket is enough to start.

Related

  • #110 the physics engine itself is the blocker.
  • #11 the disc, #44 the goal and #70 the boules each own their scoring rule;
    this issue owns the body they share.
  • #114 a thrown body that reaches a player knocks them over.
  • The ice surface is the same friction idea the winter work wants.
The campus has three thrown things and no way to throw them: a disc golf disc on Rydskogen, a football at the soccer goals, and a boule on the gravel court at Ryds motionscentrum. Each is a small rigid body — a disc that flies and fades, a ball that bounces, a boule that rolls — and each has a scoring rule attached to it. Today the plan for all three is pure arithmetic: a throw is computed, a position is compared to a target, and the answer is a hit or a miss. Rapier gives them something better and, more usefully, gives them a *shared* implementation: one thrown body with a mass, a restitution and a friction, and a surface underneath it that decides what the body does when it lands. **What a physics body buys** - **A throw that misses because it was a bad throw.** A boule thrown too hard overshoots the jack. A disc thrown flat drops. A football kicked from the wrong angle hits the post. The rule stays the same, but the skill becomes real, which is the whole point of a game about throwing. - **One implementation for three sports.** The disc, the football and the boule differ in mass, restitution, friction and shape, not in code. The scoring rules stay where they are — the football issue owns the goal, the disc issue owns the basket, the boules issue owns the round. - **Things that are not thrown.** A ball left on a pitch is still a ball. It rolls to a stop, and it stays there until somebody kicks it. **Where it fits** The thrown bodies are **server-authoritative**, like the vehicles. A score is a score, so the rule that decides it belongs on the server, and the server is already the thing that owns the vehicles and the day/night cycle. The bodies live in the server's physics world, and their state travels on the wire. That means a new `ServerMsg` variant, appended to the end (postcard tags a variant by its position, so variants are appended and never reordered), and a new `ClientMsg` variant for the throw itself. A thrown body on the wire needs an id, a position, a rotation and a velocity — enough for a client to draw it and to interpolate it between the 20 Hz updates. The bodies themselves are drawn the way every other object is drawn: a `SceneSpec` object slot, not baked geometry, because they move and they are not part of the campus. The physics step belongs in `liuverse-world`, next to `vehicle` and `trail`, because that is where the engine-free simulation lives and where the tests can run without a GPU. **The surfaces** The interesting part of a thrown body is the ground it lands on, and the campus has exactly the surfaces that would make it interesting: asphalt on the roads, gravel on the paths, grass on the lawns, and ice at Isovalen in the winter. Rapier pairs a friction and a restitution with a collider, so each of those gets its own, and the same throw on gravel and on grass lands differently. The material is not far off today. The bake buckets an area into an `AREA_*` kind and gives each path a palette entry that picks one of three ground tiles — grass, gravel, asphalt — so there is already a coarse material under every path and area. Reading the exact `surface=` tag is the paths and pitches work's job; the collision layer the physics engine needs can carry the same tag once it exists, and the coarse bucket is enough to start. **Related** - #110 the physics engine itself is the blocker. - #11 the disc, #44 the goal and #70 the boules each own their scoring rule; this issue owns the body they share. - #114 a thrown body that reaches a player knocks them over. - The ice surface is the same friction idea the winter work wants.
sermuns added this to the Play milestone 2026-10-20 23:40:41 +00:00
Sign in to join this conversation.
No description provided.