Cauldron2D.Collision (Cauldron2D v0.1.3)

Copy Markdown View Source

Bodies against a tile grid, and against each other.

The grid is a function from a tile coordinate to what is there:

:open                          nothing
:solid                         the whole tile
{:diagonal, :nw | :ne | :sw | :se}   the half toward that corner

sweep/5 moves a body of some radius from one point to another in steps no longer than a quarter tile, so nothing passes through a wall however fast it travels, and reports the last clear point, the surface normal and the tile it would have entered. bounce/3 reflects a velocity off that normal.

case Cauldron2D.Collision.sweep(grid, from, to, radius) do
  {:clear, at} -> at
  {:blocked, at, normal, cell} -> ...
end

Cauldron2D.Collision.Buckets finds bodies near each other without comparing every pair.

Summary

Functions

Reflect velocity off a surface with unit normal.

The tile a point is in.

Whether two circles overlap.

The square of the distance between two points.

Whether point lies in solid material.

Move a body of radius from from to to.

Types

cell()

@type cell() :: {integer(), integer()}

corner()

@type corner() :: :nw | :ne | :sw | :se

grid()

@type grid() :: (cell() -> solid())

normal()

@type normal() :: {float(), float()}

point()

@type point() :: {float(), float()}

solid()

@type solid() :: :open | :solid | {:diagonal, corner()}

Functions

bounce(velocity, arg, restitution)

@spec bounce(point(), normal(), number()) :: point()

Reflect velocity off a surface with unit normal.

The component along the normal is reversed and scaled by restitution; the component along the surface is kept. A velocity already moving away from the surface is returned unchanged.

cell_of(arg)

@spec cell_of(point()) :: cell()

The tile a point is in.

circles_overlap?(arg1, r1, arg2, r2)

@spec circles_overlap?(point(), number(), point(), number()) :: boolean()

Whether two circles overlap.

distance_sq(arg1, arg2)

@spec distance_sq(point(), point()) :: float()

The square of the distance between two points.

inside?(grid, point)

@spec inside?(grid(), point()) :: boolean()

Whether point lies in solid material.

sweep(grid, from, to, radius)

@spec sweep(grid(), point(), point(), number()) ::
  {:clear, point()} | {:blocked, point(), normal(), cell()}

Move a body of radius from from to to.

Returns {:clear, to} when nothing is in the way, or {:blocked, at, normal, cell} with the last clear position, the unit normal of the surface struck, and the tile struck. A body already inside a wall is blocked at from with a normal opposing its motion.