Cavern (Challacade)ยถ
Jetpack platformer, engine test only (BY-NC-ND assets).
๐ Docs onlyUpstream: https://github.com/challacade/cavern
Tags: port tier-1
Cavern: SimVX Port (Engine Test Only)ยถ
SimVX port of Challacade/cavern, a 2D adventure platformer originally written in LรVE 2D.
DO NOT REDISTRIBUTE. Source code is MIT, but the art and audio assets are licensed CC BY-NC-ND 4.0 by Challacade. This port exists solely as a SimVX engine integration test. See
../LICENSE_NOTICE.mdfor the full rules.
Runยถ
# Desktop
uv run python ported_games/cavern/simvx_port/main.py
# Skip the menu and drop straight into gameplay
uv run python ported_games/cavern/simvx_port/main.py --game
# Headless capture (writes screenshots/frame_30.png, frame_60.png, frame_120.png)
uv run python ported_games/cavern/simvx_port/main.py --test
# Web export (outputs simvx_port/web/index.html)
uv run simvx export web ported_games/cavern/simvx_port/main.py \
-o ported_games/cavern/simvx_port/web/index.html
All commands must run from /home/fezzik/dev/simvx (the workspace root); uv
wonโt resolve workspace-only packages from a port subdirectory.
Controlsยถ
Action |
Binding |
|---|---|
Move |
WASD / Arrow keys |
Jetpack thrust up |
W / Up / Space |
Aim weapon |
Mouse |
Fire blaster |
Left mouse button |
Back to menu |
Esc |
Whatโs faithful to upstreamยถ
Three rooms (
rm1,rm2,rm3) parsed from upstreamโs STI Lua exports; same wall geometry, transitions, and spike-enemy placements.Player sprite stack: jetpack + body + helmet + arm, with Cavernโs exact artwork.
Aim-with-mouse + LMB-fire blaster; camera follows player and clamps to room bounds.
Music (
cavern.ogg,menu.ogg) and sfx (laser.wav,itemGet.wav,blip.wav) wired throughAudioStreamPlayer.
Whatโs reduced (engine-test scope)ยถ
Only the blaster weapon (rocket launcher / spear gun / aquaPack are wired as pickup labels but donโt change behaviour).
Jetpack approximation: simple gravity + thrust integrator instead of LรVEโs Box2D solver. Feel is similar; tunables in
nodes/config.py.Single enemy type (Spike); Cavernโs other enemies (flyer, fish, starfish, egg, boss) are out of scope.
No water / drowning / aquaPack mechanic (Cavernโs underwater rooms behave like dry rooms here).
No breakables, vines, or boss room.
Menu is keyboard / mouse driven; the upstream
rmMainMenubespoke layout isnโt used.
Filesยถ
simvx_port/
โโโ main.py entry point + test/capture mode
โโโ pyproject.toml PEP 621 + [tool.simvx] root="CavernRoot"
โโโ nodes/
โ โโโ lua_map.py STI-Lua map parser (Walls/Transitions/Enemies/...)
โ โโโ config.py tuning constants
โ โโโ room.py Room + Pickup nodes (one per active map)
โ โโโ player.py Player, Bullet
โ โโโ enemies.py Spike, EnemyProjectile, spawn_enemy()
โ โโโ hud.py in-game HUD (health pips + room label + bottom strip)
โ โโโ menu.py MainMenu scene
โ โโโ game.py CavernGame: owns room + camera + collisions
โ โโโ root.py CavernRoot scene container (web-export entry)
โโโ assets/
โ โโโ sprites/ player, enemies, environment, items
โ โโโ sounds/ laser, itemGet, blip
โ โโโ music/ cavern.ogg, menu.ogg
โ โโโ maps/ rm1.lua, rm2.lua, rm3.lua, rmMainMenu.lua
โโโ screenshots/
โโโ web/
Sourceยถ
1#!/usr/bin/env python3
2"""Cavern (Challacade): Jetpack platformer, engine test only (BY-NC-ND assets).
3
4# /// simvx
5# tags = ["port", "tier-1"]
6# upstream = "https://github.com/challacade/cavern"
7# web = { width = 1152, height = 768, responsive = true, disabled = true, reason = "Blocked on audio refactor (uses old 'Music' bus name; upstream art also under BY-NC-ND)." }
8# ///
9
10Source code MIT (Challacade); art and audio assets are CC BY-NC-ND 4.0.
11Engine test only; see ``ported_games/cavern/LICENSE_NOTICE.md``.
12
13Run desktop : uv run python ported_games/cavern/simvx_port/main.py
14Headless : uv run python ported_games/cavern/simvx_port/main.py --test
15Web export : uv run simvx export web ported_games/cavern/simvx_port/main.py \
16 -o ported_games/cavern/simvx_port/web/index.html
17"""
18
19# /// script
20# requires-python = ">=3.13"
21# dependencies = ["simvx-core", "simvx-graphics", "numpy", "pillow"]
22# ///
23
24from __future__ import annotations
25
26import sys
27from pathlib import Path
28
29_PORT_DIR = Path(__file__).resolve().parent
30sys.path.insert(0, str(_PORT_DIR))
31
32from simvx.graphics import App # noqa: E402
33
34from nodes.root import CavernRoot # noqa: E402
35
36WINDOW_W = 1152
37WINDOW_H = 768
38
39
40def main() -> None:
41 test_mode = "--test" in sys.argv
42 skip_intro = "--game" in sys.argv
43
44 app = App(
45 width=WINDOW_W, height=WINDOW_H,
46 title="Cavern (SimVX engine test)",
47 visible=not test_mode,
48 )
49
50 start = "game" if skip_intro else "menu"
51
52 if test_mode:
53 from simvx.graphics import save_png
54 out = _PORT_DIR / "screenshots"
55 out.mkdir(exist_ok=True)
56 capture_frames = [30, 60, 120]
57 # Capture both menu and gameplay: 30 = menu, 60/120 = gameplay.
58 captured = app.run_headless(
59 CavernRoot(start_scene="game"),
60 frames=150,
61 capture_frames=capture_frames,
62 )
63 for idx, n in enumerate(capture_frames):
64 if idx < len(captured):
65 save_png(out / f"frame_{n}.png", captured[idx])
66 print(f"wrote frame_{n}.png")
67 app.quit()
68 return
69
70 app.run(CavernRoot(start_scene=start))
71
72
73if __name__ == "__main__":
74 main()