Skip to main content

A 16-bit-era fantasy console with built-in editors and PDF carts

Project description

py-16

Eine Fantasy-Konsole im Stil der 16-Bit-Aera, geschrieben in Python mit Pygame.

Eckdaten

py-16
Aufloesung 256 x 224 @ 60 FPS
Palette 256 Farben (frei zuweisbar)
Sprite-Sheet 256 x 256 (1024 Sprites a 8x8)
Sprite-Groessen 8x8 bis 64x64 (spr(id, x, y, w, h, flip_x, flip_y))
Map 128 x 128 Tiles
Sound 8 Kanaele, 4 Wellenformen (Square, Triangle, Saw, Noise)
Editoren Sprite (F1), Map (F2)
Cart JSON mit base64-Sheet (~140 KB)

Installation

pip install pygame numpy

(numpy ist optional, beschleunigt aber Bildladen und Cart-I/O deutlich)

Installation

pip install pygame                      # Pflicht
pip install numpy pillow reportlab pypdf pymupdf   # Optional, fuer alle Features

Oder in einem Schritt mit den Optional-Gruppen:

pip install py-16[all]      # Alles
pip install py-16[fast]     # Nur numpy
pip install py-16[pdf]      # PDF-Export
pip install py-16[covers]   # PDF-Cover-Vorschauen

Sicherheitshinweis

py-16 fuehrt den Code im Cart als ganz normalen Python-Code aus - es gibt keine Sandbox. Oeffne nur Carts, denen du vertraust.

Ein boeser Cart kann alles, was Python kann: Dateien lesen/loeschen, Internet-Verbindungen, dein Mikrofon, deine Webcam, dein Adressbuch. Das gilt fuer .p16- und .pdf-Carts gleichermassen. Behandle Carts wie Python-Skripte aus dem Internet, nicht wie Bilder oder Lieder.

Wenn du Carts aus dem Netz lädst, lies vorher den Code im Code-Editor durch (F6 -> F8 zum Laden ohne Ausfuehrung -> dann kannst du den Code sehen, bevor du F9 zum Reload druckst).

Schnellstart

import py16

def init():
    py16.sset(8, 0, 8)          # roter Pixel ins Sprite-Sheet
    py16.fset(1, 0, True)       # Sprite 1 bekommt Flag 0

def update():
    if py16.btn('right'):
        ...

def draw():
    py16.cls(0)
    py16.spr(1, 100, 50)
    py16.text("HELLO", 4, 4, 7)

py16.run(update, draw, init)

Modulstruktur

py16/
├── __init__.py        Public-API (alles re-exportiert)
├── state.py           Zentraler mutabler Zustand
├── core.py            Konstanten, Palette, run(), Auto-Boot-Countdown
├── graphics.py        cls, pset, rect, line, text, camera, clip, pal/palt
├── sprites.py         spr, sset, sget, load_spritesheet
├── maps.py            mset, mget, draw_map, fset, fget
├── input.py           btn, btnp, mouse_*
├── audio.py           tone() + Wellenformen-Generator
├── sfx_data.py        Datenmodelle fuer SFX/Music
├── tracker.py         Hintergrund-Sequencer mit Effekten
├── mathx.py           rnd, flr, mid, sin, cos, atan2, t, fps
├── cart.py            save_cart, load_cart (.p16 und .pdf)
├── cart_pdf.py        PDF-Export mit Handbuch
├── cart_runtime.py    run_cart, push_cart, pop_cart (Stack)
├── config.py          ~/.py16/config.json verwalten
├── bios.py            BIOS-Bildschirm mit Cart-Liste, Power-Menue
├── editors.py         Sprite- und Map-Editor (F1/F2)
├── editors_audio.py   SFX- und Music-Editor (F3/F4)
└── code_editor.py     Code-Editor (F6) mit Live-Reload (F9)

BIOS und Boot-Cart

py-16 startet wahlweise direkt in einen Cart oder in den BIOS-Bildschirm:

# Direkt einen Cart starten
python3 demo.py

# Mit Boot-Cart starten (laedt automatisch ~/.py16/carts/boot.p16,
# 3 Sekunden Countdown, ESC oder beliebige Taste = BIOS)
python3 -c "import py16; py16.run()"

Der BIOS-Bildschirm zeigt alle Carts im Cart-Verzeichnis und bietet:

  • Cart starten (Enter)
  • Code-Editor fuer neuen Cart (F6)
  • Power-Menue mit Shutdown/Reboot/Quit (F12)

F12 ist ueberall der Notausgang zurueck zum BIOS - egal ob ein Cart abgestuerzt ist oder ein Editor offen ist.

Cart-Verzeichnis

Default: ~/.py16/carts/. Override per Umgebungsvariable PY16_CARTS_DIR=/pfad/zu/carts.

Configuration in ~/.py16/config.json:

{
  "carts_dir":      "~/.py16/carts",
  "boot_cart":      "boot.p16",
  "power_off_cmd":  "sudo poweroff",
  "reboot_cmd":     "sudo reboot",
  "boot_countdown": 3
}

Cart-Wechsel zur Laufzeit

py16.run_cart("/pfad/spiel.p16")     # Reset, alter Cart wird verworfen
py16.push_cart("/pfad/menu.p16")     # Stack: vorigen Cart merken
py16.pop_cart()                       # zurueck zum vorherigen Cart
py16.go_to_bios()                     # zurueck ins BIOS

Der Boot-Cart-Pattern: ein Browser-Cart nutzt push_cart() zum Starten eines Spiels; das Spiel nutzt pop_cart() oder F12 -> BIOS, um zurueck zu kommen.

Beispiel-Boot-Cart

boot_cart.py ist ein fertiger Cart-Browser im 2x3-Grid mit Cover-Stilen. Speichern als ~/.py16/carts/boot.p16 und beim naechsten Start wird er automatisch geladen.

Pi-Image-Hinweise

Fuer eine Einplatinen-Konsole:

  • System auf Auto-Login fuer den Pi-User konfigurieren
  • ~/.bash_profile: python3 -c "import py16; py16.run()"
  • power_off_cmd muss ohne Passwort funktionieren -> visudo: pi ALL=NOPASSWD: /sbin/poweroff, /sbin/reboot
  • Vollbild aktivieren in ~/.py16/config.json: "fullscreen": true

Vollbild

py16.toggle_fullscreen()

Oder per Tastatur F11 zur Laufzeit. Persistent ueber Config:

{
  "fullscreen":     true,
  "display_scale":  "auto",        // oder fester Faktor wie 4
  "hide_cursor":    "auto"         // im Vollbild aus
}

Bei display_scale: "auto" waehlt py-16 den groessten ganzzahligen Skalierungsfaktor, der auf den Bildschirm passt - ergibt scharfe Pixel ohne Sub-Pixel-Filtering. Das nicht abgedeckte Letterbox-Gebiet wird schwarz gefuellt. Maus-Koordinaten werden korrekt zurueckgerechnet.

PDF-Cover-Vorschauen

py16.get_cart_cover(pdf_path, w, h) liefert ein 2D-Array mit Paletten-Indizes als Vorschau der ersten PDF-Seite. Cache unter ~/.py16/cart_covers/. Der mitgelieferte boot_cart.py zeigt damit echte Cover statt generischer Booklet-Symbole.

Braucht pip install pymupdf pillow.

API-Uebersicht

Grafik

Funktion Zweck
cls(c=0) Bildschirm fuellen
pset(x, y, c) / pget(x, y) Einzelnes Pixel
rect(x, y, w, h, c) / rectfill(...) Rechteck
line(x0, y0, x1, y1, c) Linie
circ(x, y, r, c) / circfill(...) Kreis
text(s, x, y, c=7) Text mit eingebautem 3x5-Font
camera(x, y) Kamera-Offset setzen
clip(x, y, w, h) Scissor-Rechteck
pal(c0, c1) Farbe c0 wird als c1 dargestellt
palt(c, transparent) Transparenz-Set anpassen

Sprites & Map

Funktion Zweck
sset(x, y, c) / sget(x, y) Pixel im Sprite-Sheet
spr(id, x, y, w=1, h=1, flip_x=False, flip_y=False) Sprite zeichnen
load_spritesheet(file) PNG laden + auf Palette quantisieren
mset(cx, cy, id) / mget(cx, cy) Map-Zelle
draw_map(cx, cy, sx, sy, w, h, layer_flag=-1) Map-Bereich
fset(id, flag, value) / fget(id, flag) Sprite-Flags 0..7

Eingabe

Funktion Zweck
btn(name) Taste gehalten?
btnp(name) Taste in diesem Frame neu gedrueckt?
mouse_x(), mouse_y() Mausposition (Logik-Koordinaten)
mouse_btn(idx), mouse_btnp(idx) Maustasten 0/1/2

Tasten: up, down, left, right, z, x, a, s, space, enter, shift

Audio

Funktion Zweck
sfx(id, channel=-1) SFX-Patch abspielen
music(track_id, fade_ms=0) Music-Track im Hintergrund starten (-1 = Stop)
tone(pitch_hz, dur_ms, wave, channel=-1) Low-Level-Ton ohne Patch

Wellenformen: WAVE_SQUARE, WAVE_TRIANGLE, WAVE_SAW, WAVE_NOISE

SFX-Patches (64 Slots): Jeder Patch hat 32 Notenzellen mit Note, Instrument (8 Wellenformen-Varianten), Lautstaerke und Effekt (Slide, Vibrato, Drop, Fade-In/Out, Arpeggio fast/slow).

Music-Patterns (64 Slots): Jedes Pattern kombiniert 4 SFX-IDs fuer 4 parallele Kanaele.

Music-Tracks (8 Slots): Eine Sequenz von Pattern-IDs, die nacheinander gespielt werden und am Ende loopen.

Editoren (zur Laufzeit)

Taste Wirkung
F1 Sprite-Editor toggeln
F2 Map-Editor toggeln
F3 SFX-Editor toggeln
F4 Music-Editor toggeln
F6 Code-Editor toggeln
F9 Code-Reload (im Editor: Code ausfuehren)
F5 Cart speichern (cart.p16 oder .pdf)
F8 Cart laden
ESC Editor verlassen / Spiel beenden

Code-Editor: Vollstaendiger Texteditor mit Cursor, Selection, Copy/Cut/Paste (Ctrl+C/X/V), Undo/Redo (Ctrl+Z/Y), Suche (Ctrl+F), Auto-Indent, Tab/Shift-Tab. Speichert mit Ctrl+S in die externe .py-Datei. Mit F9 wird der Code zur Laufzeit neu kompiliert und update/draw ersetzt - kein Programmneustart noetig.

PDF-Cart-Export

Carts koennen als PDF mit Handbuch und eingebettetem Cart exportiert werden:

py16.export_pdf("game.pdf", title="MY GAME", author="ME")
# oder einfach:
py16.save_cart("game.pdf")

Das PDF enthaelt:

  • Cover-Seite im Box-Stil mit Sprite-Vorschau
  • Manual-Seite aus # @manual ... # @end-Kommentaren im Code
  • Asset-Seite mit Sprite-Sheet, Map, SFX-Liste, Tracks
  • Code-Listing im 80er-Stil mit Zeilennummern
  • Cart-Anhang (.p16-Datei) als PDF-Attachment

Laden geht ueber py16.load_cart("game.pdf") - der Cart-Anhang wird automatisch extrahiert.

Manual-Format im Code:

# @manual
# @description
# Beschreibung des Spiels.
#
# @controls
# Pfeile : Bewegen
# Z      : Springen
#
# @credits
# Autor: Du
# @end

PDF-Export braucht: pip install reportlab pypdf pillow

SFX-Editor: Tracker-Raster mit 32 Notenzellen. Maus klickt Zellen an, Pfeiltasten navigieren, +/- aendert Werte. Klavier-Tasten (Z-X-C... fuer Oktave 3, Q-W-E... fuer Oktave 4) testen Tonhoehen live UND schreiben sie in die aktuelle Zelle. SPACE spielt den ganzen Patch ab.

Music-Editor: Track-Sequenz oben (16 Pattern-Slots), Pattern-Editor darunter (4 Kanaele mit SFX-IDs). TAB wechselt Fokus, A/S waehlt Track, ,/. waehlt Pattern. SPACE spielt Track, ENTER spielt nur Pattern.

Lizenz

GPLv3. Siehe LICENSE-Datei für weitere Details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_16-1.0.0.tar.gz (90.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_16-1.0.0-py3-none-any.whl (82.6 kB view details)

Uploaded Python 3

File details

Details for the file py_16-1.0.0.tar.gz.

File metadata

  • Download URL: py_16-1.0.0.tar.gz
  • Upload date:
  • Size: 90.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for py_16-1.0.0.tar.gz
Algorithm Hash digest
SHA256 ada060c03c47aee23cc4f20a63ba33339108504635ef2e24da77bba72bd69151
MD5 b319ba811fff142b7c7b441cbf1e31c9
BLAKE2b-256 96b09a299a199339954aeb9f5e401341599a094519723c1138d37b39a6bc06f0

See more details on using hashes here.

File details

Details for the file py_16-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: py_16-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 82.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for py_16-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e8adf05c526b2aa6a2e57eef186c79d9343be385014c88dfc2e5ca9b12ba6eef
MD5 ca2a768be6a6b7df6b7720d392b46fb5
BLAKE2b-256 2718bb34357db5a390a0918d49ff08383bb5e14b0164bfa895ee8e2cee6658ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page