Zum Inhalt springen

Pocket Knight

Ein kleines Gerät im Hosentaschenformat. Es ist ein Mini Roguelike für unterwegs, bei dem man durch Schritte Fortschritt macht. Die Schritte, die man über den Tag sammelt schalten Events frei, wodurch man auf unterschiedliche Ereignisse und Kämpfe trifft. Mit jedem Kampf sammelt der Spieler Erfahrung, verbessert seine Ausrüstung und wird stärker.

Die Ereignisse werden gesammelt, sodass man sie abends in Ruhe nacheinander spielen kann und das Gerät nur tagsüber bei sich tragen muss. Etwas ausführlicher schreibe ich über den Entwicklungsprozess in diesem Blogbeitrag.

Art
Elektronik · Spiel
Jahr
2026
Details
Status: spielbarer Prototyp
Pocket Knight: ein 3D-gedruckter Handheld mit kleinem Display

01 — Steckbrief

Rolle
Soloprojekt: Konzept, Elektronik, Firmware, Game Design, Pixelart und Gehäuse
Zeitraum
Rund 3 Monate in meiner Freizeit, 2026
Werkzeuge
  • C++ (Arduino IDE)
  • U8g2
  • Aseprite
  • Fusion 360
  • PrusaSlicer
  • Prusa MINI+ (FabLab Kiel)
  • Claude (AI assistant)
Hardware
  • DFRobot FireBeetle 2 ESP32-E
  • SSD1306-OLED-Display, 128 × 64 px
  • Seeed-Grove-Schrittzähler (BMA456)
  • Passiver Piezo-Summer und Mini-Vibrationsmotor
  • 3 Taster
  • Li-Ionen-Akku mit 1800 mAh
  • Lochrasterplatine, zweifarbiges Gehäuse aus PLA
Links

02 — Idee

Ich wollte ein Gerät bauen, das an die Digivice-Spielzeuge aus meiner Kindheit erinnert: klein genug für die Hosentasche und mit einem Spiel, das beim Gehen vorankommt. Tagsüber bleibt das Gerät in der Tasche und zählt Schritte, abends spielt man die gesammelten Events in Ruhe durch.

Drei Anforderungen haben fast jede Entscheidung bestimmt: Das Gerät muss in eine Hosentasche passen, es muss wochenlang ohne Laden auskommen, und es muss den ganzen Tag Schritte zählen, ohne dass jemand es bedient. Die letzten beiden widersprechen sich: Dauerhaftes Zählen kostet Strom, eine lange Laufzeit verlangt, dass der Prozessor fast immer schläft.

03 — Vorgehen

Ich habe einen FireBeetle 2 ESP32-E gewählt, weil das Laden des Akkus schon auf dem Board passiert und ich nur noch eine Li-Ionen-Zelle anschließen musste. Für die Schritte nutze ich einen BMA456, der Schritte selbstständig in der Hardware zählt. Zuerst lief alles auf einem Breadboard, darauf habe ich den Großteil der Firmware geschrieben.

Als Schaltung und Code stabil waren, habe ich alle Teile möglichst kompakt auf eine Lochrasterplatine gelötet und danach Spielablauf, Inhalte und Sprites verfeinert, bis es sich wie ein vollständiges Spiel anfühlte.

Breadboard-Prototyp: Das OLED-Display zeigt einen Kampfbildschirm, verkabelt mit dem ESP32, drei Tastern und dem Schrittzähler
Der erste Prototyp auf dem Breadboard

04 — Schritte zählen im Schlaf

Die Lösung für den Widerspruch oben ist, die Arbeit zu teilen. Der BMA456 zählt die Schritte durchgehend selbst, und der ESP32 geht nach 30 Sekunden ohne Eingabe in den Deep Sleep. Taste A weckt ihn wieder.

Was zuerst schiefging: Der Schrittzähler hat aufgehört zu zählen und sich zurückgesetzt, sobald er keine Stromversorgung hatte. Sein Zählerstand lag danach unter dem Wert, den das Spiel zuletzt gespeichert hatte.

So funktioniert es jetzt:

  • Beim Start prüft die Firmware, warum das Gerät startet. Nach einem Kaltstart richtet sie den Sensor ein und speichert 0 als neuen Bezugswert. Nach dem Aufwachen aus dem Deep Sleep richtet sie ihn bewusst nicht neu ein, weil das seinen Zähler zurücksetzen würde.
  • Ins Spiel geht nur die Differenz zum gespeicherten Zählerstand. Ist der neue Wert kleiner, erkennt die Firmware einen Reset und setzt nur den Bezugswert neu, statt Schritte abzuziehen.
  • Schlägt das Auslesen über I²C fehl, gibt die Funktion den letzten bekannten Wert zurück. Ein Lesefehler kommt so nie als Schrittsprung im Spiel an.

Vereinfachter Ausschnitt aus progress.ino:

void syncSteps() {
  uint32_t cur = readSensorSteps();   // Zählerstand des BMA456
  if (cur > lastSensorSteps) {
    addSteps(cur - lastSensorSteps);  // nur die Differenz zählt
    lastSensorSteps = cur;
  } else if (cur < lastSensorSteps) {
    lastSensorSteps = cur;            // Sensor wurde zurückgesetzt
  }
}
Diagramm des Schlaf- und Wachzyklus: Nach 30 Sekunden ohne Eingabe speichert der ESP32 und geht in den Deep Sleep; Taste A weckt ihn, und die Differenz zum gespeicherten Zählerstand wird zu Spielschritten. Der BMA456 zählt die ganze Zeit. Eine gestrichelte Linie markiert den Interrupt des Schrittzählers als geplante zweite Weckquelle.
Schlaf- und Wachzyklus der Firmware

05 — Pixelgrafik

Alle Sprites habe ich in Aseprite als 1-Bit-Pixelart gezeichnet. Schwierig war der Weg aufs Display: Jede Grafik musste ins XBM-Format umgewandelt werden, und die Animationen werden direkt im Code gesteuert, der Bild für Bild festlegt, was gezeichnet wird. Gezeichnet wird mit der Bibliothek U8g2, die Bitmaps liegen per PROGMEM im Flash statt im knappen Arbeitsspeicher.

Rückblickend hätte eine Bibliothek oder ein kleines Werkzeug für Sprite-Animationen viel Handarbeit gespart.

Poster mit allen Pixel-Sprites von Pocket Knight – Ritter, Ereignisse, Gegner und Bosse – weiß auf schwarz
Alle Sprites des Spiels

06 — Firmware

Die Firmware ist in C++ in der Arduino IDE geschrieben und in Module aufgeteilt: Kampf, Events, Fortschritt und Speichern, Darstellung und Audio.

  • Zustandsautomat: Jeder Bildschirm ist ein eigener Zustand. Die Hauptschleife ruft die passende Funktion für Eingabe und Darstellung auf; der Kampf hat eigene Phasen (wählen, auswerten, Ergebnis, Gegenstandswahl).
  • Kein doppelter Tastendruck: Taste A weckt das Gerät und bestätigt im Menü. Damit derselbe Druck nicht sofort eine Aktion auslöst, ignoriert die Firmware nach dem Aufwachen alle Eingaben, bis jede Taste einmal losgelassen wurde.
  • Immer gespeichert: Der Fortschritt wird an jedem Checkpoint und vor dem Einschlafen in den Flash-Speicher geschrieben, getrennt nach aktuellem Durchlauf und dauerhaftem Fortschritt. Jeder Spielstand trägt eine Versionsnummer; passt sie nicht zur Firmware, wird er verworfen statt falsch gelesen.
  • Inhalte als Daten: Gegner, Gegenstände, Freischaltungen und Event-Gewichte stehen als Tabellen oben im Code. Zum Balancing muss ich die Logik nicht anfassen.
Die gelötete Lochrasterplatine, das OLED-Display zeigt einen Kampf zwischen dem Ritter und zwei Gegnern
Auf Lochraster gelötet, das Spiel läuft schon

07 — Spielmechanik und Balancing

Im Schnitt alle 300 Schritte (zufällig zwischen 220 und 380) kommt ein neues Event dazu. Ist das Gerät in dem Moment wach, piept und vibriert es. Bis zu 10 Events werden gespeichert, sodass man sie später am Stück spielen kann. An jeder Weggabelung wählt man eins von zwei Events, von Kämpfen und Händlern bis zu Fallen, Schreinen und einem Wunschbrunnen.

Die Kämpfe sind rundenbasiert: Der Gegner zeigt seinen nächsten Zug vorher an, und der Spieler antwortet mit Angriff, Block, einer von 5 Fähigkeiten oder einem Verbrauchsgegenstand. Nach jeweils 10 Events wartet ein Boss; wer den vierten besiegt, gewinnt den Durchlauf. Insgesamt gibt es 7 Gegnertypen mit eigenem Verhalten und 22 Gegenstände. Endet ein Durchlauf, schalten Meta-Punkte dauerhafte Startboni frei.

Balancing: In der ersten Fassung kam alle 250 Schritte ein Event, und bis zu 20 konnten sich ansammeln. Das machte die Session am Abend mühsam. Mit etwas mehr Schritten pro Event und höchstens 10 gespeicherten Events bleibt der Abend kurz, und ein Durchlauf mit 40 Events dauert ungefähr eine Woche.

08 — Gehäuse

Das Gehäuse habe ich in Fusion 360 entworfen und im FabLab Kiel auf einem Prusa MINI+ zweifarbig gedruckt: grau für den Körper, blau für den Displayrahmen und die Lilien-Embleme. Eine kleine Münze mit dem Emblem dient als Schlüsselanhänger. Nach dem ersten Druck gab es eine Überarbeitung, in der ich nur die Tiefe des Gehäuses leicht angepasst habe.

Druckdateien und Slicer-Einstellungen liegen im GitHub-Repository, sodass sich das Gerät nachbauen lässt.

Das Pocket-Knight-Gehäuse und die Schlüsselanhänger-Münze mit Lilien-Emblem in Fusion 360
Gehäuse und Anhänger-Münze in Fusion 360

09 — Ergebnis

Pocket Knight ist ein spielbarer Prototyp: ein kompletter Durchlauf mit 11 Eventarten, 7 Gegnertypen, 4 Bossen, 22 Gegenständen und dauerhaftem Fortschritt über mehrere Durchläufe, in rund 3.700 Zeilen Firmware. Das Gerät ist seit Wochen im Alltag im Einsatz. Im Hauptmenü steckt noch ein Debug-Eintrag zum Testen; da es nur dieses eine Gerät gibt, bleibt der Status bei Prototyp.

Die Laufzeit habe ich über die Akkuanzeige des Geräts abgeschätzt: Je eine Woche im normalen Betrieb und im Standby habe ich beobachtet, wie weit die Prozentanzeige sinkt, und das hochgerechnet. Daraus ergeben sich etwa 3–4 Monate pro Akkuladung. Firmware, Gehäusedateien und Artwork sind unter MIT-Lizenz offen.

Die gelötete Elektronik mit OLED-Display neben einer Banane als Größenvergleich
Banane zum Größenvergleich

10 — Was ich gelernt habe und ändern würde

  • Energie gegen Spielgefühl: Der Deep Sleep sichert die Laufzeit, kostet aber eine Funktion. Neue Events melden sich mit Piepen und Vibration nur, solange das Gerät wach ist. In der Tasche schläft es fast immer, deshalb sammeln sich die Events still an. Der nächste Schritt ist, den Interrupt des BMA456 als zweite Weckquelle zu nutzen.
  • Kleinerer Akku: 1800 mAh reichen für Monate, sind aber das schwerste Bauteil. Beim nächsten Mal würde ich zuerst die gewünschte Laufzeit festlegen und den Akku danach wählen.
  • Genauere Akkuanzeige: Die Prozentanzeige rechnet die Spannung linear um. Li-Ionen-Zellen entladen sich aber nicht linear, deshalb ist auch die Laufzeit-Schätzung nur grob. Eine Tabelle mit der echten Entladekurve wäre genauer.
  • Inhalte für das Display entwerfen: 128 px Breite reichen nicht für jeden Text. Manche Texte werden abgeschnitten, und einige Mechaniken erklärt das Spiel zu wenig.
  • Werkzeuge für Grafiken: Für Sprites und Animationen würde ich von Anfang an eine Bibliothek oder ein eigenes Export-Skript nutzen.

Vorerst gestrichen: Koop- und Versus-Multiplayer über ESP-NOW, eine Online-Bestenliste, flüssigere Animationen, weitere Startklassen und eine englische Fassung der Spieltexte.

11 — Medien

Das Video wird erst nach dem Klick von YouTube geladen.

Fragen, Ideen oder Feedback? Ich freue mich über eine Nachricht.

Schreib mir