https://github.com/skywardpixel/platformer-primitives
Simple, well-commented Love2D examples of Metroidvania building blocks: character controller, camera, parallax, and room transitions.
https://github.com/skywardpixel/platformer-primitives
gamedev love2d lua metroidvania pixel-art platformer
Last synced: 4 days ago
JSON representation
Simple, well-commented Love2D examples of Metroidvania building blocks: character controller, camera, parallax, and room transitions.
- Host: GitHub
- URL: https://github.com/skywardpixel/platformer-primitives
- Owner: skywardpixel
- Created: 2026-05-29T04:49:38.000Z (29 days ago)
- Default Branch: main
- Last Pushed: 2026-05-29T05:33:18.000Z (29 days ago)
- Last Synced: 2026-05-29T07:26:34.043Z (29 days ago)
- Topics: gamedev, love2d, lua, metroidvania, pixel-art, platformer
- Language: Lua
- Size: 29.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Platformer Primitives
A small collection of **Love2D** examples covering the core building blocks of a
2D Metroidvania. Each primitive is a focused, heavily-commented example you can
read top-to-bottom and lift into your own project.
| # | Example | What it teaches |
|---|---------|-----------------|
| 1 | **Character Controller** | Run with acceleration/friction, gravity with capped fall speed, variable-height jump, **coyote time**, **jump buffering**, one-way platforms. |
| 2 | **Camera Controller** | Smooth follow camera with a **dead-zone**, **look-ahead**, zoom, and **level-bounds clamping** — with a live overlay that visualises all of it. |
| 3 | **Parallax Background** | Multiple background layers scrolling at different speeds to fake depth, tiled to repeat forever. |
| 4 | **Map / Room Transition** | Metroidvania room changes: an **edge slide** when you walk off the side, and a **door fade-warp**. |
All art is real pixel-art PNG (in `assets/`), generated by a script — see below.
## Running
You need [Love2D](https://love2d.org/) **11.x** installed.
```sh
love .
```
Then pick an example from the menu (`Up`/`Down` + `Enter`, or press `1`–`4`).
Press `Esc` to return to the menu, `H` to toggle the on-screen help/controls.
### Controls (in any example)
- **Move:** Arrow keys or `A`/`D`
- **Jump:** `Space` / `Z` / `Up` (hold for a higher jump)
- **Drop through a one-way platform:** hold `Down` + jump
- **R:** reset position
- Each example lists its extra keys in the on-screen help panel.
## Project layout
```
main.lua -- menu + scene switcher, routes input to examples
conf.lua -- window config (960x540, internal art is 480x270)
lib/
assets.lua -- image cache (nearest-neighbour filtering)
anim.lua -- sprite-sheet animation helper
camera.lua -- the follow camera (used by examples 1-4)
tilemap.lua -- tile storage, culled rendering, AABB collision
player.lua -- the character controller (used by examples 1-4)
level.lua -- small grid builder for describing levels in code
examples/
character_controller.lua
camera_controller.lua
parallax_background.lua
map_transition.lua
assets/ -- generated PNGs
tools/
gen_assets.py -- regenerates the art (Pillow)
```
The shared `lib/` modules are the reusable parts; the files in `examples/` are
the thin, readable demos that wire them together.
## Where the "feel" lives
The character controller's tuning knobs are all at the top of
[`lib/player.lua`](lib/player.lua) (`TUNING`): gravity, run speed, acceleration,
jump strength, coyote time, jump buffer, etc. Tweak those numbers to change how
the character feels.
The camera's tuning (`smooth`, `deadzoneW/H`, `lookAheadDist`) lives at the top
of [`lib/camera.lua`](lib/camera.lua) — and example 2 lets you change several of
them live with the keyboard.
## Regenerating the art
The PNGs in `assets/` are produced by `tools/gen_assets.py` using
[Pillow](https://python-pillow.org/). You only need this if you want to change
the art:
```sh
python3 -m venv .venv
.venv/bin/pip install Pillow
.venv/bin/python tools/gen_assets.py
```
## Dev smoke test
`main.lua` has a built-in self-test that runs every example through a few
hundred frames (with simulated input + forced transitions) and quits:
```sh
love . --test # run every example headlessly, report errors
love . --shots # same, but also save screenshots to the save dir
```