M0: skelett, byggkedja och dokumentation för JP Subway Pussel
- Go 1.27 + Ebitengine v2.10, intern upplösning 320x180 med heltalsskalning - internal/res (resursuppslag), internal/rng (seedad slump), internal/level (banformat, validering, BFS-lösbarhet) med tester; internal/archtest kontrollerar att bara presentationslagret beror på Ebitengine - tools/build: debug -> build/debug/, release -> build/release/<os>-<arch>/ med resources/ bredvid binären; Windows korsbyggs utan C-verktyg - VS Code tasks (build/test/release) och launch (dlv) - Första banan 001-flygplatsen, sv/en-texter, skyltordbok, placeholder-sprite - doc/: spelbeskrivning (renskriven), mål och tester, roadmap med teknikval (M0–M12), plan.md; README med bygg- och beroendeinformation Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
233
doc/roadmap.md
Normal file
233
doc/roadmap.md
Normal file
@@ -0,0 +1,233 @@
|
||||
# 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) eller **Misaki** (8 px) via `ebiten/v2/text/v2` | Pixelfonter med kana **och kanji**. Fri licens. Krävs för att skyltar ska kunna visas på riktigt. Beslut i M3. |
|
||||
| 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()/jp-subway-pussel/` | 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
|
||||
|
||||
```
|
||||
jp-subway-pussel/
|
||||
├── cmd/jp-subway-pussel/ 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)
|
||||
│ ├── game/ Ebitengine-loop, scener, rendering ← får använda Ebitengine
|
||||
│ ├── archtest/ beroenderegler
|
||||
│ └── … kommande: sim/, lang/, nav/, score/, save/, minigame/, ui/, audio/
|
||||
├── tools/build/ byggverktyget
|
||||
├── resources/ kopieras bredvid binären vid bygge
|
||||
│ ├── sprites/ bilder, tilesets, UI
|
||||
│ ├── sound/ OGG/WAV
|
||||
│ ├── text/ sv.json, en.json, jp-dictionary.json, fonts/
|
||||
│ └── data/ levels/, items, skills (JSON)
|
||||
├── doc/ denna dokumentation
|
||||
├── .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/jp-subway-pussel` + `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/jp-subway-pussel.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 `jp-subway-pussel v0.1.0` i `-version`.
|
||||
|
||||
## 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
|
||||
|
||||
- **Mål:** gå runt i en labyrint som är större än skärmen.
|
||||
- Spelare som rör sig i 4 riktningar (tangentbord + gamepad), kollision mot
|
||||
väggar, kamera som följer och klampas till kartan.
|
||||
- Scen-system (meny → bana → resultat) som en enkel tillståndsmaskin.
|
||||
- Tileset i stället för färgade rutor; sprite-animation (gå/stå).
|
||||
- **Teknik:** `internal/game/scene`, `internal/sim` (rörelse/kollision som
|
||||
ren logik), Ebitengine `inpututil`.
|
||||
- **Klar när:** man kan gå från S till P i bana 001, kameran följer, testerna
|
||||
i mål-dokumentet för M1 är gröna.
|
||||
|
||||
### M2 – Stationen: tåg, spärrar och vinst/förlust → första spelbara banan
|
||||
|
||||
- **Mål:** bana 001 går att klara och misslyckas.
|
||||
- Tåg med tidtabell som står vid perrongen en stund och avgår; nästa avgång
|
||||
visas vid perrongen.
|
||||
- Spärrar som kräver kort (kortet finns och har alltid saldo i M2).
|
||||
- Vinst när rätt tåg tas; förlust när fel tåg tas. Resultatskärm.
|
||||
- Interaktion med skyltar (visar text, än så länge på svenska/engelska).
|
||||
- **Teknik:** `internal/sim/schedule`, `internal/level` utökas med
|
||||
tidtabell + skyltinnehåll.
|
||||
- **Klar när:** en simuleringstest låter en bot klara bana 001 headless;
|
||||
manuellt spel från start till mål fungerar.
|
||||
|
||||
### M3 – Japanska och skyltsystemet
|
||||
|
||||
- **Mål:** spelets identitet – skyltar på japanska som man lär sig läsa.
|
||||
- Pixelfont med kana + kanji (beslut PixelMplus/Misaki, licens in i repot).
|
||||
- Kunskapsmodell: vilka tecken/ord spelaren kan. Skyltar renderas med
|
||||
delvis översättning, egen färg för det som är översatt, interaktion för
|
||||
att se översättning.
|
||||
- Andel engelska på skyltar styrs av banans svårighet.
|
||||
- "Fråga en japan": NPC-interaktion med väntetid beroende på japanska-nivå.
|
||||
- Hintar i UI/bana skalar med japanska-nivå.
|
||||
- **Teknik:** `internal/lang` (ordbok, kunskap, översättningslogik – ren
|
||||
Go), `text/v2` i `internal/game`.
|
||||
- **Klar när:** samma skylt visar olika mycket beroende på kunskap, och det
|
||||
är testat; 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.
|
||||
Reference in New Issue
Block a user