Skip to main content

Saga2D

A small Python framework for 2D games where the developer writes game logic, not engine plumbing. It renders sprites and simple shapes on the GPU through pyglet, lays out a small UI toolkit, runs a scene stack, hosts online matches and packages standalone builds. Game code never touches the backend.

Three games prove it, each in its own repository: Tribes (turn-based, Polytopia-style), Warband (real-time strategy) and Shardbound (an Eador-inspired campaign). Procedural assets — sound synthesis and a software low-poly renderer — live in sagaforge; the hosted server and website in saga-online.

Install

Requires Python 3.12 or newer. Pin the engine in a game so engine development cannot change that game's build:

uv add 'saga2d==0.2.0'
# or: python -m pip install 'saga2d==0.2.0'

Commit the game's pyproject.toml and lockfile. Upgrade the pin deliberately, then run that game's tests before committing the upgrade. See the release guide for compatibility policy, publishing and testing a local engine checkout.

Develop the engine

uv sync --extra dev
uv run pytest -q          # headless suite on the mock backend

Set SAGA2D_SILENT=1 to keep any pyglet-backed script off the speakers (SAGA2D_HEADLESS=1 implies it and also hides windows).

A complete game

This example needs no image or sound files:

from saga2d import Anchor, Button, Column, Game, Label, Scene


class World(Scene):
    background_color = (18, 20, 30, 255)
    controls = {"escape": "close"}

    def on_enter(self):
        self.gold = 0
        self.ui.add(Column(
            Label(lambda: f"Gold: {self.gold}", text_style="heading"),
            Button("Collect a coin", shortcut="Space", on_click=self.collect, width=220),
            Label("Esc closes the window.", text_style="caption"),
            spacing=16, anchor=Anchor.TOP_LEFT, margin=24,
        ))

    def draw(self):
        self.draw_circle(360, 220, 32, (230, 190, 90, 255))

    def collect(self):
        self.gold += 1

    def close(self):
        self.game.quit()


Game("My Game", resolution=(640, 400)).run(World())

What you get

  • Two coordinate spaces. "world" is transformed by the scene's Camera (pan, zoom, shake) on the GPU; "screen" is for UI. Sprites default to world space; draw_rect, draw_circle, draw_line, draw_polygon, draw_text and draw_image take space=.
  • Measured paragraphs. Scene.draw_paragraph(text, x, y, width) wraps against the actual font and returns the height for subsequent layout.
  • Hex boards. HexGrid supplies centers, corners, picking, neighbours, weighted movement ranges and shortest paths; the game supplies terrain costs. See the cookbook.
  • Sprites with a logical size. Sprite("name", size=(64, 64)) draws any texture at that size, so procedural textures rendered at the display's pixel density stay crisp on HiDPI screens.
  • Declarative input. controls maps keys and chords to methods; bind_key does the same at runtime; mouse events carry world coordinates and modifier keys.
  • A scene stack with transparent overlays, deferred push/pop, and per-scene ownership of sprites, timers and particle emitters.
  • UI: reactive Label, Button with keycap shortcuts, KeyHints, Panel, Row, Column, ProgressBar, Minimap, anchors, flow layout, wrapped text and a Theme. Text is measured by the backend, so layout fits. See wrapped labels, measuring a tree and button shortcuts.
  • Actions, tweens, timers, particle emitters, frame animation, transient effects, audio with master/music/sfx channels and a silent driver, JSON save slots and persisted settings.
  • Multiplayer. MatchHost/MatchClient for LAN, OnlineClient and the shared MatchMenu/MatchLobby for hosted rooms, and saga2d.server, the authoritative room server any game registers with through a GameSpec. Follow the counter-room tutorial and the transport notes.
  • Packaging. saga2d.packaging builds, verifies and installs standalone games with PyInstaller from a ten-line tools/package.py.
  • Testing. A mock backend that records every draw call, render_scene for offscreen screenshots you can look at, a CPU budget for long checks, paced native frames, and a counter test game for the server.

See DESIGN.md for the architecture and the reasoning behind the cuts.

Release files for saga2d 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for saga2d 0.2.0
File Size Uploaded
saga2d-0.2.0.tar.gz 419.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for saga2d 0.2.0
File Interpreter ABI Platform
saga2d-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 740.9 kB

Release files / saga2d-0.2.0.tar.gz

Download URL saga2d-0.2.0.tar.gz
Size 419.5 kB
Tags Source
SHA-256 checksum
How to use checksums
f2998d1f0e6c99766efa5a41aa485929d25f746c93f978da26875f8641a74c1a
BLAKE2b-256 checksum
How to use checksums
2a5c438202920ce7f52c445fa918bfbfa74f98f914a1a7484fbd469e4c622203
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.10

Release files / saga2d-0.2.0-py3-none-any.whl

Download URL saga2d-0.2.0-py3-none-any.whl
Size 321.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6256579c26616cfa6815d1be492ab1d01c6661fb186cb13e9b220dc1af0a929b
BLAKE2b-256 checksum
How to use checksums
5deff976d33480e16461eb7c8b466724297748e76e5ccd2727f8f627848391a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.10

Release history Release notifications | RSS feed

0.3.14

2 release files

0.3.13

2 release files

0.3.12

2 release files

0.3.11

2 release files

0.3.10

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page