This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

# Collision2D

Detect collision/intersection of geometry in a defined 2D coordinate space AKA tell me when objects are touching or overlapping.

All objects use the same coordinate system you might see in an algebra or physics problem, origin (0,0) is at the center of the object, so they're compatible with the core Graphics.Collage coordinate system.

# Basic geometry

type Rectangle = Rectangle { cx: Float, cy: Float, w : Float, h : Float }

Represents rectangular hitbox geometry.

rectangle : Float -> Float -> Float -> Float -> Rectangle

Create a Rectangle hitbox from coordinates (cx, cy) and geometry (width and height)

Arguments:

``````rectangle centerX centerY width height
``````

Example:

``````rectangle 5 5 10 10
-- a 10 x 10 rectangle centered on coordinates 5,5
``````
type Circle = Circle { cx: Float, cy: Float, radius : Float }

Represents circular geometry.

circle : Float -> Float -> Float -> Circle

Create a Circle Hitbox from from coordinates (cx, cy) and geometry (radius)

Arguments:

``````circle centerX centerY radius
``````

Example:

``````circle 5 5 10 -- a radius 10 circle centered on coordinates 5,5
``````

# Rectangle to Rectangle Collision

axisAlignedBoundingBox : Rectangle -> Rectangle -> Bool

Super efficient collision detection between two Rectangles that are axis aligned — meaning no rotation.

``````rect1 = rectangle 5 5 10 10
rect2 = rectangle 7 5 10 10

axisAlignedBoundingBox rect1 rect2 -- True
-- rect1 is coliding with rect2
``````
rectangleSide : Rectangle -> Rectangle -> Maybe Side

Very efficiently detect which side of a Rectangle is colliding with another Rectangle

``````rect1 = rectangle 5 5 10 10
rect2 = rectangle 7 5 10 10

rectangleSide rect1 rect2 -- Just Right
-- rect1 is coliding with it's right side onto rect2
``````
type Side = Top | Right | Bottom | Left

Represents sides of a Rectangle

# Circle to Circle Collision

circleToCircle : Circle -> Circle -> Bool

Super efficient collision detection between two Circles

``````circle1 = circle 5 5 5
circle2 = circle 7 5 5

circleToCircle circle1 circle2 -- True
-- circle1 is coliding with circle2
``````
``````module Collision2D exposing
( axisAlignedBoundingBox
, circleToCircle
, Side(Top, Right, Bottom, Left)
, rectangleSide
, Rectangle
, rectangle
, Circle
, circle
)

{-| Detect collision/intersection of geometry in a defined 2D coordinate space
AKA tell me when objects are touching or overlapping.

All objects use the same coordinate system you might see in an algebra or
physics problem, origin (0,0) is at the center of the object,
so they're compatible with the core Graphics.Collage coordinate system.

# Basic geometry
@docs Rectangle, rectangle, Circle, circle

# Rectangle to Rectangle Collision
@docs axisAlignedBoundingBox, rectangleSide, Side

# Circle to Circle Collision
@docs circleToCircle
-}

{-| Represents rectangular hitbox geometry.
-}
type Rectangle = Rectangle { cx: Float, cy: Float, w : Float, h : Float }

{-| Create a Rectangle hitbox from coordinates (cx, cy) and geometry (width and height)

Arguments:

rectangle centerX centerY width height

Example:

rectangle 5 5 10 10
-- a 10 x 10 rectangle centered on coordinates 5,5
-}
rectangle : Float -> Float -> Float -> Float -> Rectangle
rectangle centerX centerY width height =
Rectangle { cx = centerX, cy = centerY, w = width, h = height }

{-| Represents circular geometry.
-}
type Circle = Circle { cx: Float, cy: Float, radius : Float }

{-| Create a Circle Hitbox from from coordinates (cx, cy) and geometry (radius)

Arguments:

Example:

circle 5 5 10 -- a radius 10 circle centered on coordinates 5,5
-}
circle : Float -> Float -> Float -> Circle
Circle { cx = centerX, cy = centerY, radius = radius }

{-| Super efficient collision detection between
two Rectangles that are axis aligned — meaning no rotation.

rect1 = rectangle 5 5 10 10
rect2 = rectangle 7 5 10 10

axisAlignedBoundingBox rect1 rect2 -- True
-- rect1 is coliding with rect2
-}
axisAlignedBoundingBox : Rectangle -> Rectangle -> Bool
axisAlignedBoundingBox (Rectangle rect1) (Rectangle rect2) =
let
startingPoint centerPoint length = centerPoint - (length / 2)
x1 = startingPoint rect1.cx rect1.w
x2 = startingPoint rect2.cx rect2.w
y1 = startingPoint rect1.cy rect1.h
y2 = startingPoint rect2.cy rect2.h
in
if x1 < x2 + rect2.w &&
x1 + rect1.w > x2 &&
y1 < y2 + rect2.h &&
rect1.h + y1 > y2 then
True
else
False

{-| Super efficient collision detection between two Circles

circle1 = circle 5 5 5
circle2 = circle 7 5 5

circleToCircle circle1 circle2 -- True
-- circle1 is coliding with circle2
-}
circleToCircle : Circle -> Circle -> Bool
circleToCircle (Circle circle1) (Circle circle2) =
let
dx = circle1.cx - circle2.cx
dy = circle1.cy - circle2.cy
distance = sqrt ((dx * dx) + (dy * dy))
in
True
else
False

{-| Represents sides of a Rectangle
-}
type Side
= Top
| Right
| Bottom
| Left

{-| Very efficiently detect which side of a Rectangle is colliding with another Rectangle

rect1 = rectangle 5 5 10 10
rect2 = rectangle 7 5 10 10

rectangleSide rect1 rect2 -- Just Right
-- rect1 is coliding with it's right side onto rect2
-}
rectangleSide : Rectangle -> Rectangle -> Maybe Side
rectangleSide (Rectangle rect1) (Rectangle rect2) =
{-
Calculate which side of a rectangle is colliding w/ another, it works by
getting the Minkowski sum of rect2 and rect1, then checking where the centre of
rect1 lies relatively to the new rectangle (from Minkowski) and to its diagonals
* thanks to sam hocevar @samhocevar for the formula!
-}
let
w = 0.5 * (rect1.w + rect2.w)
h = 0.5 * (rect1.h + rect2.h)
dx = rect2.cx - rect1.cx
dy = rect2.cy - rect1.cy
wy = w * dy
hx = h * dx

in
if abs dx <= w && abs dy <= h then
if (wy > hx) then
if (wy > -hx) then
Just Top
else
Just Left
else
if (wy > -hx) then
Just Right
else
Just Bottom
else
Nothing
```
```