Asteroids (raylib classic)

Vector-space rotation, wrap-around physics, score HUD.

▶ Run in browser

Upstream: https://github.com/raysan5/raylib-games/tree/master/classics/src

Tags: port tier-0

Run desktop: uv run python ported_games/raylib_classics/asteroids/simvx_port/main.py Headless: uv run python ported_games/raylib_classics/_capture.py asteroids Web export: uv run simvx export web ported_games/raylib_classics/asteroids/simvx_port/main.py -o ported_games/raylib_classics/asteroids/simvx_port/web/index.html

Controls: Up / W Thrust Left / A Rotate left Right / D Rotate right Space Shoot R / Enter Restart after game over Esc Quit

Source

 1#!/usr/bin/env python3
 2"""Asteroids (raylib classic): Vector-space rotation, wrap-around physics, score HUD.
 3
 4# /// simvx
 5# tags = ["port", "tier-0"]
 6# upstream = "https://github.com/raysan5/raylib-games/tree/master/classics/src"
 7# web = { width = 800, height = 600, responsive = true }
 8# ///
 9
10Run desktop:  uv run python ported_games/raylib_classics/asteroids/simvx_port/main.py
11Headless:     uv run python ported_games/raylib_classics/_capture.py asteroids
12Web export:   uv run simvx export web ported_games/raylib_classics/asteroids/simvx_port/main.py \
13                  -o ported_games/raylib_classics/asteroids/simvx_port/web/index.html
14
15Controls:
16    Up / W       Thrust
17    Left / A     Rotate left
18    Right / D    Rotate right
19    Space        Shoot
20    R / Enter    Restart after game over
21    Esc          Quit
22"""
23
24# /// script
25# requires-python = ">=3.13"
26# dependencies = ["simvx-core", "simvx-graphics", "numpy", "pillow"]
27# ///
28
29from __future__ import annotations
30
31import math
32import os
33import random
34import sys
35
36_HERE = os.path.abspath(os.path.dirname(__file__))
37if _HERE not in sys.path:
38    sys.path.insert(0, _HERE)
39
40from simvx.graphics import App  # noqa: E402
41
42from nodes.asteroids_game import WIDTH, HEIGHT, AsteroidsGame  # noqa: E402
43
44
45def main():
46    test_mode = "--test" in sys.argv
47    app = App(width=WIDTH, height=HEIGHT, title="Asteroids (raylib classic)", visible=not test_mode)
48    if test_mode:
49        from pathlib import Path
50        from simvx.graphics import save_png
51        out = Path(__file__).resolve().parent / "screenshots"
52        out.mkdir(exist_ok=True)
53        frames = app.run_headless(AsteroidsGame(), frames=120, capture_frames=[60, 119])
54        for idx, n in enumerate([60, 119]):
55            save_png(out / f"frame_{n}.png", frames[idx])
56            print(f"wrote frame_{n}.png")
57        app.quit()
58        return
59    app.run(AsteroidsGame())
60
61
62if __name__ == "__main__":
63    main()