Files
metro-puzzle-jp/doc/roadmap.md
claude b67493fddb
All checks were successful
release / build-release (push) Successful in 1m42s
M3: japanska skyltar – pixelfont, ordbok, kunskap, delvis översättning, hjälp
- resources/text/fonts: PixelMplus 10/12 px (M+ FONT LICENSE) + licens;
  all text ritas via text/v2 på heltalspositioner, debugfonten är borta
- internal/lang: ordbok (60 ord, validerad), tokenisering med längsta
  matchning, Knowledge (ord + kana, nivå 0–5, hintar), Render (kända ord
  markerade/översatta, okända kvar, kana som romaji), EnglishShare/
  ShowEnglish per svårighet (deterministiskt per bana+position),
  HelpSeconds; datatest kräver att all japanska i banorna finns i ordboken
- sim.Run: AskHelp (H) med väntetid efter nivå, avbryts om man går,
  avslöjar skylten och lär första okända ordet; Knowledge delas mellan banor
- game: skylt- och avgångstavlor renderade genom kunskapen med färgkodning,
  engelsk rad på lätta banor, hjälp-förlopp, "Nytt ord"-notis, HUD visar
  resmålet på japanska från nivå 1 och japanska-nivå; meny med svårighet;
  pixelbaserad radbrytning av färgade textsegment; -know-flagga
- tools/shots: tre skyltbilder (skylt, hjälp, nytt ord) med förkunskap
- docs/README/wiki uppdaterade

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-23 20:14:36 +02:00

16 KiB
Raw Blame History

Roadmap och teknikval

Ordningen nedan är den ordning saker ska byggas i. Varje milstolpe är ett körbart, testat steg som går att visa upp. Teknikvalen står först eftersom de styr hur milstolparna byggs.

Teknikval

Område Val Varför
Språk Go 1.27 En enda installation ger kompilator, pakethanterare, testramverk och formatterare. Snabba byggen. Björn använder redan Go i andra projekt.
Spelbibliotek Ebitengine v2.10 (github.com/hajimehoshi/ebiten/v2) Byggt för 2D-pixelspel: intern upplösning + heltalsskalning, nearest-neighbour-sampling, inbyggt ljud (OGG/WAV/MP3), tangentbord/gamepad/mus, textrendering med TTF. Ren Go på Windows → korsbygge från Linux utan C-verktyg.
Tester Standardbiblioteket testing Inget att installera. go test ./... kör allt.
Speldata JSON i resources/data/ Läsbart, diffbart i git, encoding/json i standardbiblioteket. Byt till TOML bara om kommentarer blir ett verkligt behov.
Bygg go run ./tools/build Ett Go-program i stället för make/bash/PowerShell. Samma kommando på alla plattformar. Stämplar version och läge, kopierar resurser.
IDE VS Code + tillägget golang.go .vscode/tasks.json (bygg/test) och .vscode/launch.json (F5 med delve). Tillägget installerar delve åt dig.
Font PixelMplus 10/12 px via ebiten/v2/text/v2 Pixelfont med kana och kanji (JIS 1+2), M+ FONT LICENSE. Valdes framför Misaki (8 px) för läsbarhetens skull – 10 px kanji går att läsa vid 3–4× skala.
Ljud ebiten/v2/audio med OGG Vorbis (musik, jinglar) och WAV (korta effekter) Ingår i Ebitengine, inga externa bibliotek.
Slump math/rand/v2 (PCG) genom internal/rng Seedbart, deterministiskt, del-seeds per kontext.
Sparfiler JSON i os.UserConfigDir()/metro-puzzle-jp/ Rätt plats på både Linux (~/.config) och Windows (%AppData%).
Versionshantering Git, lokalt nu, Gitea senare Enligt playbooken; CI-release när projektet är redo att delas.

Varför inte …

  • Godot: utmärkt för pixel art, men bygger inte "i VS Code" på samma sätt, kräver editor + exportmallar, och C#-spåret drar in .NET. Hade passat om kravet varit "snabbast till prototyp", inte "få byggverktyg".
  • Rust + macroquad/Bevy: bra, men Windows-korsbygge kräver MinGW eller MSVC, och Bevy har långa byggtider. Rust-toolchain är en till sak att hålla i gång på två OS.
  • C++ + raylib/SDL: CMake + kompilator per plattform, pakethantering för hand. Precis det "många byggverktyg"-problem vi vill undvika.
  • Love2D (Lua): inget byggsteg alls, men distribution som en binär kräver att man "fuserar" ihop filer, och det saknas ett naturligt testramverk.

Regler för Windows-portabilitet (gäller från dag 1)

  1. Bygg sökvägar med filepath.Join, aldrig med / i strängar.
  2. Inga Linux-specifika syscalls eller /proc-läsningar. Behövs OS-specifik kod: lägg den i *_linux.go / *_windows.go.
  3. Sparfiler och konfiguration via os.UserConfigDir(), aldrig ~ i strängar.
  4. Resurser hittas relativt binären (internal/res), aldrig relativt arbetskatalogen i release.
  5. Textfiler skrivs med \n; läsning tål \r\n.
  6. Varje milstolpe avslutas med go run ./tools/build -mode release -os windows så att Windows-bygget aldrig hinner gå sönder obemärkt.
  7. Inget cgo i vår egen kod.

Katalogstruktur

metro-puzzle-jp/
├── cmd/metro-puzzle-jp/   main.go – flaggor, fönster, startar spelet
├── internal/
│   ├── buildinfo/          version + läge (sätts av byggverktyget)
│   ├── res/                hittar och läser resources/ (ren Go)
│   ├── rng/                seedad slump (ren Go)
│   ├── level/              banformat, validering, BFS (ren Go)
│   ├── sim/                rutbaserad rörelse, kollision, kamera, banomgång (Run: klocka, kort, spärrar, tåg, hjälp) – ren Go
│   ├── lang/               ordbok, tokenisering, kunskap, delvis översättning, engelska-andel, hjälptid – ren Go
│   ├── game/               Ebitengine-loop, scener, input, rendering, skriptläge  ← får använda Ebitengine
│   ├── archtest/           beroenderegler
│   └── …                   kommande: lang/, nav/, score/, save/, minigame/, ui/, audio/
├── tools/build/            byggverktyget
├── tools/genart/           genererar placeholder-grafik (tiles.png, player.png)
├── tools/shots/            tar dokumentationens skärmdumpar till doc/img/
├── resources/              kopieras bredvid binären vid bygge
│   ├── sprites/            bilder, tilesets, UI
│   ├── sound/              OGG/WAV
│   ├── text/               sv.json, en.json, jp-dictionary.json, fonts/PixelMplus*.ttf
│   └── data/               levels/, items, skills (JSON)
├── doc/                    denna dokumentation (doc/img/ = skärmdumpar från tools/shots)
├── .gitea/workflows/       CI: test + release-zippar för linux/windows på brasse-linux01-runnern
├── .vscode/                tasks.json, launch.json
└── build/                  (gitignorerad) debug/ och release/<os>-<arch>/

Byggflöde

Vad Kommando Resultat
Debug (standard, Ctrl+Shift+B) go run ./tools/build build/debug/metro-puzzle-jp + resources/; inga optimeringar, full debuginfo
Debug med debugger (F5) VS Code "Debug (dlv)" Kompilerar och startar under delve med cwd = repots rot
Release Linux go run ./tools/build -mode release -os linux -arch amd64 build/release/linux-amd64/ – strippad, -trimpath
Release Windows go run ./tools/build -mode release -os windows -arch amd64 build/release/windows-amd64/metro-puzzle-jp.exe – GUI-subsystem, inget konsolfönster
Tester go test ./...

Versionen i binären kommer från git describe --tags --always --dirty, så en tagg v0.1.0 ger metro-puzzle-jp v0.1.0 i -version.

Skärmdumpar till dokumentationen

README och wikin visar bilder från doc/img/. De tas av spelet självt i skriptläge så att de alltid är pixelexakta och går att återskapa:

go run ./tools/genart   # bara om placeholder-grafiken ska genereras om
go run ./tools/shots    # bygger debug, kör spelet med -script, skriver doc/img/*.png

Regel: när sprites, tileset eller UI ändras – kör tools/shots och committa doc/img/ i samma commit, så visar README och wiki alltid aktuell grafik. Nya vyer läggs till i listan i tools/shots/main.go.

CI

.gitea/workflows/release.yaml kör go vet + go test, bygger linux-amd64 och windows-amd64 och lägger zipparna på den rullande releasen latest (en tagg vX.Y.Z ger en versionerad release). Jobbet körs på brasse-linux01-runnern (label linux-amd64), aldrig på Pi5:n.

Milstolpar

M0 – Skelett och byggkedja ✓ (klar 2026-10-23)

  • Repo, Go-modul, Ebitengine-fönster 320×180 med heltalsskalning.
  • internal/res, internal/rng, internal/level med tester.
  • Byggverktyg, VS Code-tasks och launch-konfigurationer.
  • Första banan (001-flygplatsen) renderad som färgade rutor med placeholder-sprite.
  • Verifierat: debug-bygge, Linux-release, Windows-korsbygge, smoke-test med fönster, alla tester gröna.

M1 – Rörelse, kollision och kamera ✓ (klar 2026-10-23)

  • Mål: gå runt i en labyrint som är större än skärmen.
  • Rutbaserad rörelse i 4 riktningar (pilar/WASD + gamepad d-pad/spak), mjukt interpolerad, riktningsbyte vid rutgränser; kollision mot väggar; kamera som följer spelaren och klampas till kartan (centrerar små kartor).
  • Scen-system: meny (banlista) → bana → resultat (rätt/fel tåg, R = spela om).
  • Tileset (tiles.png) och spelarsprite med gå-animation i fyra riktningar (player.png), genererade av tools/genart tills riktig pixel art finns.
  • Större testbana 002-shinjuku (33×21 rutor) som bevisar kamerascrollen.
  • Skriptläge (-script) och tools/shots som tar dokumentationens skärmdumpar deterministiskt.
  • Teknik: internal/sim (Mover, Camera – ren Go med tester), internal/game (scener, input, assets), Ebitengine inpututil/vector.
  • Avsteg: resultatskärmen visar redan rätt/fel tåg eftersom perrongen är det naturliga slutet på en bana; tidtabell, spärrar och väntan på tåg kommer i M2 som planerat.

M2 – Stationen: tåg, spärrar och vinst/förlust ✓ (klar 2026-10-23)

  • Mål: bana 001 går att klara och misslyckas.
  • Tåg med tidtabell per perrong (schedule: första ankomst, intervall, uppehåll). Tågvagnen ritas bortom perrongkanten när tåget är inne; HUD:en visar spår, linje, resmål och "avgår om / nästa tåg om".
  • Ombordstigning är ett aktivt val: stå på perrongen och tryck Enter medan tåget är inne. Rätt tåg = vinst, fel tåg = förlust, resultatskärm med tid, steg, spärrpassager och kortsaldo.
  • Spärrar kräver kort med saldo (startsaldo 2000 ¥, avgift per bana, dras när man går in i en spärr från en vanlig ruta). Tomt kort stoppas med meddelande. Riktig ekonomi och påfyllning kommer i M6.
  • Skyltar har text (signs i bandatan, sv/en/ja) som visas när man står stilla på skyltrutan. Japanskan ritas först i M3.
  • Regel för banor: alla perronger ska ligga innanför spärrar. level.UngatedPlatforms kontrolleras i det datadrivna testet; bana 001 byggdes om när regeln avslöjade två genvägar.
  • Teknik: internal/sim.Run (klocka, kort, spärrlogik, ombordstigning – ren Go), level.Schedule, level.Path (BFS), skriptkommandot waittrain.
  • Klar när: TestBotWinsLevel001 låter en bot gå kortaste vägen, passera spärren, vänta in tåget och kliva på – headless. ✓

M3 – Japanska och skyltsystemet ✓ (klar 2026-10-23)

  • Mål: spelets identitet – skyltar på japanska som man lär sig läsa.
  • Font: PixelMplus 10/12 px (M+ FONT LICENSE, i repot under resources/text/fonts/), ritad med text/v2 på heltalspositioner. All text i spelet går via den; debugfonten är borta.
  • Ordbok (resources/text/jp-dictionary.json, 60 ord): japanska → kana, romaji, sv, en, tier. Ett test kräver att all japanska i banorna (skyltar, namn, resmål, linjer) finns i ordboken.
  • Kunskapsmodell (lang.Knowledge): kända ord + kana-läsning. Nivå 0–5 = kända ord / 4. Kana låses upp efter tre kända kana-ord.
  • Rendering (lang.Render): skylten tokeniseras med längsta matchning; kända ord markeras i gult i originalet och översätts i raden under, okända står kvar på japanska i grått, kana-ord som kan läsas men inte förstås visas som romaji i grönt. Avgångstavlan på perrongen är en skylt som alla andra.
  • Engelska efter svårighet (lang.ShowEnglish): andel skyltar med engelsk rad 100/60/30/10/0 % för svårighet 1–5, deterministiskt per bana + position.
  • Fråga någon om hjälp (H): tar lang.HelpSeconds(nivå) sekunder (6 s på nivå 0, ned till 2 s), avbryts om man går, avslöjar hela skylten och lär spelaren det första okända ordet på den. Notis "Nytt ord".
  • Hintar efter nivå: från nivå 1 visar HUD:en resmålet på japanska (att matcha mot skyltarna), från nivå 2 visas läsningen efter kända ord.
  • Kunskapen följer med mellan banor under en session (Game.Know); att spara den på disk är M8. Flaggan -know ord,ord ger förkunskap för tester och skärmdumpar.
  • Teknik: internal/lang (ren Go, 11 tester + datatester), sim.Run (hjälp-tillstånd, avslöjade skyltar), internal/game/text.go (pixelbaserad radbrytning av färgade textsegment).
  • Klar när: samma skylt visar olika mycket beroende på kunskap, och det är testat (TestRenderPartialTranslation, TestKanaReadingWithoutMeaning, TestAskHelpRevealsSignAndTeachesWord); bana 001 spelas med japanska skyltar. ✓

M4 – Lämmeltåget och mätarna

  • Mål: sällskapet följer med och ställer till det.
  • Följare som går i rad efter spelaren.
  • Mätare mat/dryck/toa per karaktär; händelser (toabesök, köpa dricka, distraktion) vars frekvens skalar med gruppstorlek.
  • Toaletter, kiosker och automater som rutor i banan.
  • Teknik: internal/sim/party, internal/sim/events (seedade via internal/rng).
  • Klar när: fler i gruppen ger mätbart fler händelser i test; händelser går att lösa i spelet.

M5 – Minikarta och utforskning

  • Mål: orientering utan att avslöja labyrinten.
  • Minikarta som visar avgångar och riktmärken från start och fylls i när man utforskar. Nollställs per bana och omgång.
  • Teknik: internal/sim/fog (ren Go), rendering i internal/game.

M6 – Kort, biljetter, telefon och minispel

  • Mål: resurshantering och de seedade minispelen.
  • Kortsaldo som dras i spärren; tomt kort → hitta automat → påfyllningsminispel.
  • Separata biljetter på svårare banor → biljettköpsminispel (rätt biljett).
  • Kort i telefonen: speed-buff + procentchans för omskanning. Batteri som tar slut på långa banor → tvingar till biljett.
  • Minispel på tåget: få plats, komma av, gå av på rätt station.
  • Teknik: internal/minigame/* med gemensamt gränssnitt (Start(seed) / Update / Result), all slump via del-seeds.
  • Klar när: varje minispel är deterministiskt för en seed (test) och spelbart.

M7 – Svårighet, tid, poäng och debuffar

  • Mål: banor som kan misslyckas och poäng att jaga.
  • Tidsgräns och maxantal missade tåg på svåra banor; lätta banor obegränsade.
  • Poängformel: tid, pengar/påfyllningar, mätarnas status, navigeringsläge.
  • Stats (speed, törst, fokus, toalett, tur) och debuffar (onda fötter, trötthet, hunger/irritation, matförgiftning); temporära debuffar 1–4 banor.
  • Svårighetsprofil per bana i JSON.
  • Teknik: internal/score, internal/sim/stats.

M8 – Progression, items och sparfiler

  • Mål: något att låsa upp och en anledning att fortsätta.
  • XP/level-ups, skill tree, items (kläder, masker, hattar) med buffar.
  • Bankarta i spelbrädesstil; sidobanor som ger skins/powers/items; items som låser upp genvägar i huvudbanor.
  • Sparfil med framsteg, items, skills, debuffar och seed. Autospar vid banstart.
  • Teknik: internal/save (JSON, versionsfält för migrering), resources/data/items.json, skills.json.
  • Klar när: sparfil round-trip-test grön; "< 33 % per omgång" går att räkna ut från datan.

M9 – Navigeringslägen: lista och skyltläge

  • Mål: de två sätten att spela story.
  • Listläge: nästa tåg visas.
  • Skyltläge: 1–4 giltiga vägar, mer poäng, förlust om man åker i fel riktning / för långt bort.
  • Teknik: internal/nav (graf över stationer/linjer, giltiga vägar, riktningskontroll – ren Go).

M10 – Story-innehåll och flerbytesbanor

  • Mål: hela resan från flygplats till flygplats.
  • Alla huvudbanor och sidobanor; banor med flera stopp och byten; buss.
  • Slutanimation (karaktärerna flyger iväg, items och poäng visas) och eftertexter.
  • Överstimulerande UI/banor som extra svårighet.
  • Teknik: baneditor-stöd behövs troligen här: ett tools/levelcheck som ritar banan som bild och rapporterar onåbara rutor.

M11 – Oändligt läge och New Game+

  • Slumpade mål från seed, poäng per mål, egen poänglista. NG+ behåller skills.
  • Låses upp när storyn är klar.

M12 – Ljud, polish och release

  • Avgångsmelodier/ankomstjinglar, effekter, musik.
  • Inställningar (ljudnivåer, språk sv/en, skala, tangenter).
  • Windows-test på riktig maskin, ikon i exe:n, eventuell Gitea-CI med releaser enligt playbooken.

Prioritering

  • Måste för ett spelbart spel: M1–M3, M6 (åtminstone kort/spärr), M7.
  • Gör spelet till det här spelet: M3, M4, M9.
  • Kan skjutas utan att något går sönder: M5, M11, delar av M8 (skill tree), överstimulerande UI i M10.
  • Windows-bygget körs vid varje milstolpe men testas på riktig Windows först i M12.