Packages

A functional-core, imperative-shell 2D physics/game engine for Gleam, targeting both Erlang and JavaScript.

Current section

Files

Jump to
glemy README.md
Raw

README.md

# glemy
A small 2D circle-physics/game engine for [Gleam](https://gleam.run),
targeting both the Erlang and JavaScript runtimes. Follows a
[Functional Core, Imperative Shell](https://kennethlange.com/functional-core-imperative-shell/)
split: `glemy/physics` and its submodules are pure Gleam (entities, an
axis-aligned bounding box, gravity, integration, and a pairwise
collision sweep with a caller-supplied interaction rule), fully tested
with plain `gleam test` on both targets; `render`/`io` are the thin,
`@target(javascript)`-gated Shell that draws entities to a real WebGPU
canvas and polls keyboard/mouse input.
glemy itself ships no game — see
[glemy-games](https://github.com/recregt/glemy-games) for three
reference games (Tiers, Breakout, Platformer) built on it, and the
[live demo](https://recregt.github.io/glemy-website/play/) to try them
in a browser.
## Installing
Not yet published to Hex. Until then, depend on it directly from
GitHub, pinned to a commit (Gleam's own recommended practice over a
branch or tag):
```toml
[dependencies]
glemy = { git = "https://github.com/recregt/glemy", ref = "<commit-sha>" }
```
## Usage
```gleam
import glemy/physics
import glemy/physics/bounds.{Bounds}
import glemy/physics/collision_sweep.{Bounce}
import glemy/physics/entity.{Entity}
import glemy/physics/vector2.{Vector2}
pub fn main() {
let bounds = Bounds(min: Vector2(0.0, 0.0), max: Vector2(100.0, 100.0))
let model =
physics.Model(entities: [], bounds: bounds, gravity: Vector2(0.0, -9.8))
|> physics.spawn_entity(Entity(
position: Vector2(50.0, 90.0),
velocity: vector2.zero,
radius: 5.0,
kind: 0,
resting_time: 0.0,
))
// Advance one frame: integrate under gravity, bounce off `bounds`,
// and resolve any overlaps as plain elastic bounces (`Bounce`) --
// pass your own function instead of `fn(_a, _b) { Bounce }` to merge,
// destroy, or otherwise react to a specific pair of entities.
let #(next_model, _events) =
physics.update(model, 1.0 /. 60.0, bounds.bounce, fn(_a, _b) { Bounce })
physics.entity_count(next_model)
}
```
See `ARCHITECTURE.md` for where new code goes and why, and
`docs/technical-architecture.md` for the project-level architecture
spanning this repo, `glemy-games`, and `glemy-website`.
## Developing
```sh
gleam test --target erlang
gleam test --target javascript
deno task check-warnings
```
See `CLAUDE.md` for the full verification checklist this project holds
every change to.