EnReal
Turn any image into a 2D platformer stage. EnReal traces the edges in a screenshot or a piece of art, and those edges become the ground you run and jump on.
Play it in your browser: pick an image, parse it, press Play. Nothing is uploaded; the engine runs on your device.
This repository holds two things:
- The engine, published on PyPI as
enreal: a rule-based computer vision pipeline (OpenCV, no machine learning) that turns image bytes into a stage skeleton plus a terrain overlay. It depends only on NumPy, OpenCV and Pydantic. - The game, a static web app built on Phaser 3. It runs the same Python engine either inside the browser (under Pyodide) or on an optional server, and shows no difference between the two.
Use the engine from Python
pip install enreal
from pathlib import Path
from enreal import generate_skeleton
result = generate_skeleton(Path("screenshot.png").read_bytes(), scene="art")
print(result.skeleton.bounds) # x=0 y=0 width=1280 height=720
print(len(result.skeleton.curves)) # terrain polylines traced from the image
result.overlay_image_b64 # "data:image/png;base64,...", edges painted pure red
Path("stage.json").write_text(result.model_dump_json())
| Argument | Default | Effect |
|---|---|---|
scene |
"ui" |
"art" for scenes and artwork, "ui" for screenshots and documents |
max_dim |
1280 |
Longest side after downscaling; all coordinates are in this space |
grid_size |
8 |
Output points snap to this pixel grid |
rectify_perspective |
True |
"ui" only: warp a dominant quadrilateral to top-down first |
generate_skeleton raises ValueError for bad parameters or bytes OpenCV cannot decode. The engine is pure: it never reads files, touches the network or reads environment variables.
The package depends on opencv-python-headless. If your environment already has opencv-python or opencv-contrib-python, keep only one of them installed, since they all provide the same cv2 module.
The full data contract and the pipeline are described in docs/design.md.
Play and controls
| Key | Action |
|---|---|
| A / D | Move |
| W or Space | Jump (double jump available) |
| S | Drop through a platform |
| Shift | Sprint |
| J | Fire, or talk to an NPC when next to one |
| K | Place or detonate a bomb |
| G | Throw or detonate a grenade |
| H | Paint terrain under the player |
Pure red pixels in the overlay are solid ground. Explosions erase them and painting adds them.
Run it locally
The project uses uv. From the repository root:
uv sync
Browser engine only, no server (how the live site works):
uv run python scripts/build_web.py # builds the engine wheel into web/engine/
python -m http.server 8000 -d web # any static file server works
Open http://127.0.0.1:8000/. The page finds no server, so it loads the engine into the browser. The first visit downloads about 22 MB (Python, NumPy, OpenCV, Pydantic), which the browser then caches. Opening index.html straight from disk does not work, because browsers refuse to load WebAssembly from file://.
With the optional server:
uv run python -m server
Open http://127.0.0.1:8000/. The page detects the server and parses there. Add ?backend=local to the URL to force the in-browser engine anyway, or use the Engine picker on the page.
| Variable | Default | Purpose |
|---|---|---|
HOST, PORT |
127.0.0.1, 8000 |
Bind address |
UVICORN_RELOAD |
0 |
1 reloads on code changes |
ENREAL_LOGLEVEL |
INFO |
DEBUG, INFO, WARNING or ERROR |
ENREAL_CORS_ORIGINS |
empty | Comma-separated origins allowed to call the API from another site |
To point a static copy of the game at a server elsewhere, open it with ?server=https://your-server/ and list the page's origin in that server's ENREAL_CORS_ORIGINS.
Development
uv run pytest # engine, server and packaging tests
uv run ruff check src server scripts tests
uv run ruff format --check src server scripts tests
uv run mypy
The Pyodide parity test runs the wheel under Pyodide in Node and checks it against CPython. It needs Node 18 or newer:
cd tests/pyodide && npm ci && cd ../..
ENREAL_PYODIDE=1 uv run pytest tests/test_pyodide_parity.py
Without npm ci that test is skipped, and CI always runs it.
Releasing
The version lives in src/enreal/__init__.py and nowhere else.
- Bump
__version__and add aCHANGELOG.mdentry. - Commit, then tag and push:
git tag v0.1.1 && git push origin v0.1.1. .github/workflows/release.ymlchecks that the tag matches the version, runs the tests, builds, and publishes to PyPI through Trusted Publishing. Nothing is ever uploaded from a local machine.- Create the GitHub release for the tag.
The website redeploys from main on every push through .github/workflows/pages.yml, independently of PyPI releases.
License
Metadata
Release files for enreal 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| enreal-0.1.0.tar.gz | 32.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| enreal-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.0 kB
Release files / enreal-0.1.0.tar.gz
| Download URL | enreal-0.1.0.tar.gz |
|---|---|
| Size | 32.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b26174e8551f370e8dcd29b32b3dd84ca81b714f5c07b6c406a78e385b8c422
|
|
BLAKE2b-256 checksum How to use checksums |
5d87d2cbfd40671923520b44eda665ae5df7f5c16a17f9eefcc4acd525b31c1d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / enreal-0.1.0-py3-none-any.whl
| Download URL | enreal-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1c22014d4363e5d1c958be209b1c7bbb318f792a9fbd11c97929a0413bbeeff1
|
|
BLAKE2b-256 checksum How to use checksums |
8a2503e62bdba49ecb82b05b39e59480f906befc09dce322ea9308b886e5234f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log