Pixel Runner¶
Clear Code’s Pygame endless runner, with Timer signals, flipbook sprites and synthesised audio.
▶ Run in browserUpstream: https://github.com/clear-code-projects/UltimatePygameIntro
Licence: this port's own code is offered under MIT, not the SimVX Examples Licence the rest of the gallery carries. See ATTRIBUTION.md for the upstream it re-implements, the terms of anything it bundles, and the credit each one requires.
Ports live in the repository only, not in the simvx-examples distribution, because each is a derivative work licensed individually against the game it re-implements. Read it with git clone https://git.simvx.com/simvx/simvx.
Tags: port tier-0
Pixel Runner: SimVX Port¶
Faithful port of Clear Code’s Ultimate Pygame Intro endless runner to SimVX.
What it demonstrates¶
The whole game is one root node (nodes/runner.py) holding two states, the title
screen and the run, exactly as the upstream tutorial does. Along the way it shows
how the pygame idioms the tutorial teaches map onto engine features:
Pygame |
SimVX |
|---|---|
|
|
|
child nodes + |
|
a |
swapping |
|
|
|
|
|
|
|
|
|
a fixed 800x400 surface |
layout driven by the tree’s |
Run¶
uv run python examples/ports/ultimate_pygame_intro/main.py # interactive
uv run python examples/ports/ultimate_pygame_intro/main.py --test # headless capture
Controls¶
Key |
Action |
|---|---|
|
Jump |
|
Start / restart after death |
|
Quit |
Web export¶
uv run simvx export web examples/ports/ultimate_pygame_intro/main.py -o /tmp/pixel_runner.html
Asset licence¶
No upstream assets are bundled (the upstream repository declares no licence).
Character and enemy sprites and the ground tiles are from Kenney’s CC0
Platformer Art Complete Pack (https://kenney.nl / https://opengameart.org/content/platformer-art-complete-pack-often-updated),
resized to the original port geometry. The sky is generated, and all audio is
synthesised at load time (nodes/audio.py): the music loop through the engine’s
AudioSynth, the jump chirp as a swept sine fed to AudioClip.from_pcm.
See ATTRIBUTION.md and LICENSE (MIT).
Source files¶
File |
Summary |
Lines |
|---|---|---|
Pixel Runner: Clear Code’s Pygame endless runner, with Timer signals, flipbook sprites and synthesised audio. |
60 |
|
Pixel Runner: SimVX port package. |
1 |
|
Pixel Runner port: node modules. |
1 |
|
Where the port’s bundled art lives. |
10 |
|
Procedural audio: built on the engine’s AudioSynth API. |
103 |
|
Obstacle nodes: replaces Pygame |
80 |
|
Player node: replaces Pygame |
137 |
|
Pixel Runner: root scene replacing the pygame |
293 |
Source¶
1#!/usr/bin/env python3
2# /// script
3# requires-python = ">=3.14"
4# dependencies = ["simvx-core", "simvx-graphics", "numpy", "pillow"]
5# ///
6"""Pixel Runner: Clear Code's Pygame endless runner, with Timer signals, flipbook sprites and synthesised audio.
7
8# /// simvx
9# tags = ["port", "tier-0"]
10# upstream = "https://github.com/clear-code-projects/UltimatePygameIntro"
11# web = { width = 800, height = 400, responsive = true }
12# ///
13
14Run::
15
16 uv run python examples/ports/ultimate_pygame_intro/main.py
17 uv run python examples/ports/ultimate_pygame_intro/main.py --test # headless capture
18
19Web export::
20
21 uv run simvx export web examples/ports/ultimate_pygame_intro/main.py -o /tmp/pixel_runner.html
22"""
23
24import os
25import sys
26
27# Allow running this file directly via ``python main.py``: make the package
28# importable by adding its parent directory to sys.path.
29_HERE = os.path.abspath(os.path.dirname(__file__))
30if _HERE not in sys.path:
31 sys.path.insert(0, _HERE)
32
33from nodes.runner import Runner # noqa: E402
34
35from simvx.graphics import App # noqa: E402
36
37WIDTH, HEIGHT = 800, 400
38
39
40def main():
41 if "--test" in sys.argv:
42 from pathlib import Path
43
44 from simvx.graphics import save_png
45
46 capture_at = [30, 60, 120]
47 app = App(title="Pixel Runner", width=WIDTH, height=HEIGHT, visible=False)
48 frames = app.run_headless(Runner(), frames=130, capture_frames=capture_at)
49 out_dir = Path(_HERE) / "screenshots"
50 out_dir.mkdir(exist_ok=True)
51 for idx, img in zip(capture_at, frames, strict=False):
52 out_path = out_dir / f"frame_{idx}.png"
53 save_png(img, out_path)
54 print(f"saved {out_path}")
55 else:
56 App(title="Pixel Runner", width=WIDTH, height=HEIGHT).run(Runner())
57
58
59if __name__ == "__main__":
60 main()