Treasures and the balls in them, for capture the flag.
Every * on the map is a treasure belonging to the team of the nearest base, and a
ball starts in each. A ball is a body of its own: gravity pulls it, it drifts with its
velocity and bounces off walls (or goes home from them, with ballswallbounce off).
A ship flying within reach of a loose ball picks it up; the ball then hangs on a string
of string/0 tiles, and when the string is taut it pulls the ball after the ship and
the ship back toward the ball, the ship being the lighter of the two. Stretched past
break/0 times its length the string snaps and the ball is loose again; dropping it
(:connector) or dying lets it go too. A team's own ball sitting at home is left alone
by that team. Flying into one of your own treasures with another team's ball scores it,
and the ball goes home. Without teams there is nothing to score, so a map without
teamplay has no balls.
ExPilot.Ball.new(arena)
ExPilot.Ball.step(balls, ships, dt, %{grid: grid, fields: fields, size: size, wrap?: false, bounce?: true})
Summary
Functions
How far the string stretches, as a factor of its length, before it snaps.
The ball a ship is carrying, or nil.
A carrier flying into a treasure of its own team with another team's ball scores it: the ball goes home and the carrier's team gains points.
A ball in every treasure of arena, each with its treasure's team.
Move the balls for one tick: a loose ball is picked up by a ship in reach that carries
none or drifts on; a carried ball hangs on its string, pulling its carrier when taut,
and snaps free when overstretched. Balls fall in fields, bounce off grid or go home
when bounce? is off, and wrap in size when wrap?.
The length of the string, in tiles.
Types
@type env() :: %{ grid: Cauldron2D.Collision.grid(), fields: [Cauldron2D.Body.field()], size: {number(), number()}, wrap?: boolean(), bounce?: boolean() }
Functions
@spec break() :: float()
How far the string stretches, as a factor of its length, before it snaps.
The ball a ship is carrying, or nil.
@spec deliver([ball()], %{required(term()) => map()}, ExPilot.Map.t()) :: {[ball()], [{term(), integer(), pos_integer(), integer() | nil}]}
A carrier flying into a treasure of its own team with another team's ball scores it: the ball goes home and the carrier's team gains points.
Returns {balls, scored}, each score {carrier_id, team, points, team_scored_against}.
@spec new(ExPilot.Map.t()) :: [ball()]
A ball in every treasure of arena, each with its treasure's team.
@spec step([ball()], %{required(term()) => map()}, float(), env()) :: {[ball()], %{required(term()) => map()}}
Move the balls for one tick: a loose ball is picked up by a ship in reach that carries
none or drifts on; a carried ball hangs on its string, pulling its carrier when taut,
and snaps free when overstretched. Balls fall in fields, bounce off grid or go home
when bounce? is off, and wrap in size when wrap?.
Returns {balls, ships}, the ships as pulled by their balls and freed of a snapped
string.
@spec string() :: float()
The length of the string, in tiles.