ExCollision

View Source

A library for server-side collisions, physics world simulation (AABB), tilemap pathfinding (A*), and Tiled TMX map parsing.

Features

  • TMX parsing — load Tiled maps: tile layers (CSV/base64), objectgroup, tilesets
  • Collision world — static and dynamic bodies (AABB), intersection checks, step-by-step movement simulation
  • Pathfinding — A* algorithm over the tilemap with the TileSource protocol
  • TMX → World integration — automatic construction of the collision world from map layers (e.g. "Walls") and objectgroup

The project uses Elixir features: protocols (Collidable, TileSource), delegates (defdelegate), protocol implementations for structs (defimpl), and Enumerable for the body world.

Installation

def deps do
  [
    {:ex_collision, "~> 1.1.0"}
  ]
end

Example (map data/Dun.tmx)

# Parse TMX
map = ExCollision.parse_tmx!("data/Dun.tmx")

# Collision world from "Walls" layer and objectgroup
world = ExCollision.world_from_tmx(map, collision_layer: "Walls")

# Pathfinding over Floor layer (0 = walkable)
layer = ExCollision.tmx_layer_by_name(map, "Floor")
source = ExCollision.TMX.TileLayerTileSource.new(layer)
{:ok, path} = ExCollision.find_path(source, {10, 10}, {20, 15})

# Dynamic body and movement
{world, id} = ExCollision.World.add_body(world, ExCollision.World.Body.from_xywh(:player, 50, 50, 16, 16))
{:ok, world, body} = ExCollision.World.move_body(world, id, 2, 0)

Collision handling (on_collision)

When a body moves (move_body or step), the on_collision callback is invoked on collision if set. Signature: (world, body_id, collided_body_ids, hit_static) -> world.

Example: a bullet that disappears when hitting a wall or a player; when hitting a player you can update their data (damage).

# Bullet is removed on any collision
bullet_callback = fn world, body_id, _collided_ids, _hit_static ->
  # body_id is the bullet id; remove it from the world
  ExCollision.World.remove_body(world, body_id)
end

bullet = ExCollision.World.Body.from_xywh(bullet_id, x, y, 4, 4, velocity: {vx, vy}, on_collision: bullet_callback)
{world, _} = ExCollision.World.add_body(world, bullet)

# On step/move_body the callback runs on collision and the world is returned without the bullet (or with updated player data)

Modules

ModulePurpose
ExCollision.TMX.ParserTMX parsing (file or XML string)
ExCollision.TMX.MapMap structure, layer_by_name/2
ExCollision.TMX.WorldBuilderBuild world from TMX (from_tmx/2)
ExCollision.WorldCollision world (bodies, static, move_body, collides?)
ExCollision.World.BodyDynamic/static body (AABB)
ExCollision.Pathfinding.AStarA* pathfinding over tilemap
ExCollision.Protocols.CollidableProtocol: aabb/1
ExCollision.Protocols.TileSourceProtocol: width/1, height/1, tile_at/2, walkable?/2

License

MIT