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:
130
doc/mal-och-tester.md
Normal file
130
doc/mal-och-tester.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Mål och tester
|
||||
|
||||
## Projektmål
|
||||
|
||||
### Vision
|
||||
|
||||
Ett pixel art-pusselspel där känslan av att vara vilse på en japansk
|
||||
station är själva spelet – och där man faktiskt blir bättre på att läsa
|
||||
skyltarna ju mer man spelar. Spelet ska vara en enda binär som är lika lätt
|
||||
att bygga på Linux som på Windows.
|
||||
|
||||
### Konkreta mål
|
||||
|
||||
1. **Spelbar story** från flygplatsen till flygplatsen, med stigande
|
||||
svårighet, flerbytesbanor, sidobanor, slutanimation och eftertexter.
|
||||
2. **En binär + en `resources/`-mapp** per plattform. Inga installers, inga
|
||||
runtime-beroenden utöver vad ett vanligt skrivbord redan har.
|
||||
3. **Få byggverktyg.** Go är det enda kravet (Linux behöver dessutom en
|
||||
C-kompilator och X11/GL-headers för fönsterhanteringen). Allt byggs med
|
||||
`go run ./tools/build`.
|
||||
4. **Debug och release i VS Code** med F5 respektive Ctrl+Shift+B, utan
|
||||
extra skript.
|
||||
5. **All spellogik testbar utan fönster.** Bara presentationslagret känner
|
||||
till Ebitengine.
|
||||
6. **Deterministiskt.** Samma seed ger samma minispel och samma mål i
|
||||
oändligt läge.
|
||||
7. **Windows utan omskrivning.** `-os windows` ska vara allt som krävs för
|
||||
att få en fungerande Windows-binär från Linux.
|
||||
|
||||
### Mätbara mål
|
||||
|
||||
| Mål | Mått | Status 2026-10-23 |
|
||||
|-----|------|-------------------|
|
||||
| Inkrementellt debug-bygge | < 10 s | 4,7 s |
|
||||
| Release-binär | < 20 MB | 10,2 MB (Linux), 10,8 MB (Windows) |
|
||||
| Testsviten | `go test ./...` grön på < 30 s | ~0,1 s |
|
||||
| Banor | 100 % passerar det automatiska lösbarhetstestet | 1 av 1 |
|
||||
| Windows-korsbygge från Linux | fungerar utan extra verktyg | ✓ (CGO_ENABLED=0) |
|
||||
| Linux-binärens länkade bibliotek | bara libc | ✓ (GL/X11 laddas dynamiskt vid körning) |
|
||||
| Bildfrekvens | 60 fps vid 4× skala på integrerad grafik | ej mätt |
|
||||
| Uppstart | < 2 s till första bildruta | ej mätt |
|
||||
|
||||
## Teststrategi
|
||||
|
||||
### Principer
|
||||
|
||||
- **Ren logik → enhetstester.** Paket under `internal/` som inte är
|
||||
presentation får inte importera Ebitengine. Det kontrolleras av
|
||||
`internal/archtest`, som läser beroendegrafen med `go list` och faller om
|
||||
något annat paket än `internal/game`, `internal/ui`, `internal/audio`
|
||||
eller `cmd/…` drar in Ebitengine.
|
||||
- **Data testas som data.** Varje bana, språkfil och ordbok som ligger i
|
||||
`resources/` valideras av tester, så att trasigt innehåll stoppar bygget
|
||||
i stället för att krascha spelet.
|
||||
- **Slump går alltid via `internal/rng`** med en känd seed. Då går
|
||||
minispel och event-timing att testa deterministiskt.
|
||||
- **Inga tester kräver display.** Smoke-testet av själva fönstret körs
|
||||
manuellt (eller på en maskin med skärm) med `-smoke`.
|
||||
|
||||
### Testnivåer
|
||||
|
||||
| Nivå | Vad | Hur | Körs |
|
||||
|------|-----|-----|------|
|
||||
| 1. Enhet | Funktioner i ett paket | `*_test.go` bredvid koden | `go test ./...` |
|
||||
| 2. Data | Allt under `resources/` | Datadrivna tester som läser filerna | `go test ./...` |
|
||||
| 3. Arkitektur | Beroenderegler | `internal/archtest` | `go test ./...` |
|
||||
| 4. Simulering | En bot spelar en bana headless | Deterministisk körning av spelloopen utan rendering (kommande) | `go test ./...` |
|
||||
| 5. Smoke | Binären öppnar fönster och avslutar | `jp-subway-pussel -smoke 90` | manuellt / med skärm |
|
||||
| 6. Speltest | Känsla, svårighet, buggar | Checklistan nedan | före varje release |
|
||||
|
||||
### Tester som finns i dag
|
||||
|
||||
| Paket | Test | Verifierar |
|
||||
|-------|------|------------|
|
||||
| `internal/res` | `TestLocate_*` | Uppslagsordningen env → bredvid binären → uppåt från cwd |
|
||||
| `internal/res` | `TestDir_RealRepo` | Att repots `resources/` hittas och att sv.json + placeholder.png går att läsa |
|
||||
| `internal/rng` | `TestDeterministic`, `TestDeriveIsStableAndContextual` | Samma seed → samma sekvens; del-seeds per kontext |
|
||||
| `internal/level` | `TestParseAndSolve`, `TestUnsolvableWhenWalledOff` | BFS hittar/hittar inte väg till rätt perrong |
|
||||
| `internal/level` | `TestValidationErrors` | Ojämna rader, okända tecken, fel antal starter, tåg vid saknad perrong … |
|
||||
| `internal/level` | `TestAllShippedLevels` | Varje bana i `resources/data/levels` parsar, har id = filnamn, är lösbar och har inga onåbara interaktiva rutor |
|
||||
| `internal/archtest` | `TestOnlyPresentationPackagesImportEbitengine` | Beroenderegeln ovan |
|
||||
|
||||
### Planerade tester per milstolpe
|
||||
|
||||
| Milstolpe (se roadmap) | Tester som ska finnas när den är klar |
|
||||
|------------------------|----------------------------------------|
|
||||
| M1 Rörelse & kamera | Kollision mot vägg, rörelse i 4 riktningar, kamera klampas till kartan |
|
||||
| M2 Stationen | Tidtabell: nästa avgång beräknas rätt; spärr släpper igenom med giltigt kort/biljett och stoppar annars; vinst när rätt tåg tas, förlust vid fel tåg; simuleringstest: bot går kortaste vägen och klarar bana 001 |
|
||||
| M3 Japanska & skyltar | Delvis översättning ger exakt de ord spelaren kan; andel engelska följer svårighetstabellen; ordboken: alla nycklar har kana/romaji/en/sv; alla skyltord i banorna finns i ordboken; hjälptid = f(japanska-nivå) |
|
||||
| M4 Lämmeltåget | Mätare sjunker med rätt takt; event-frekvens ökar med gruppstorlek; event väljs deterministiskt per seed |
|
||||
| M5 Minikarta | Upptäckta rutor markeras, återställs per bana; avgångar syns från start |
|
||||
| M6 Kort/biljetter/minispel | Saldo dras i spärr; tomt kort → automatkrav; biljettminispel: rätt/fel biljett; telefon-skanning misslyckas med given procent per seed; batteri tar bara slut över tröskeltid |
|
||||
| M7 Svårighet/poäng/debuffs | Poängformeln (tid, pengar, mätare, läge); tidsgräns och maxantal missade tåg; varje debuff ändrar rätt stat; temporära debuffar räknar ned 1–4 banor |
|
||||
| M8 Progression & sparfil | Sparfil round-trip (skriv → läs ger samma tillstånd inkl. seed); skill tree-krav; upplåsningar efter rätt bana; "< 33 %"-regeln kontrolleras mot itemlistan |
|
||||
| M9 Navigeringslägen | Listläge genererar rätt ordning av tåg; skyltläge: 1–4 giltiga vägar; fel-riktnings-förlust triggar vid rätt slutstation |
|
||||
| M10 Story-innehåll | Alla banor lösbara (redan automatiskt); flerbytesbanor har sammanhängande byten; sista banan slutar på flygplatsen |
|
||||
| M11 Oändligt läge & NG+ | Målsekvens deterministisk per seed; NG+ behåller skills men nollställer items |
|
||||
| M12 Ljud & polish | Alla ljudfiler som refereras finns och går att avkoda; Windows-binär startar (manuellt) |
|
||||
|
||||
### Acceptanskriterier för "klar"
|
||||
|
||||
En milstolpe är klar när:
|
||||
|
||||
1. Alla tester i raden ovan finns och är gröna.
|
||||
2. `go vet ./...` och `go test -race ./...` är gröna.
|
||||
3. Debug- och release-bygget går igenom för Linux och Windows.
|
||||
4. Roadmapen är uppdaterad med datum och eventuella avsteg.
|
||||
|
||||
### Manuell testchecklista (speltest)
|
||||
|
||||
- [ ] Spelet startar till meny på under 2 s; ESC/avsluta fungerar.
|
||||
- [ ] Fönstret kan skalas; pixlarna är skarpa (heltalsskalning).
|
||||
- [ ] Bana 001 går att klara i både listläge och skyltläge.
|
||||
- [ ] Fel tåg ger tydlig förlust med förklaring.
|
||||
- [ ] Mätarna syns, sjunker och går att fylla på.
|
||||
- [ ] Tomt kort tvingar till automaten; minispelet är begripligt första gången.
|
||||
- [ ] Minikartan fylls i när man går runt och nollställs vid ny bana.
|
||||
- [ ] Spara mitt i en bana, ladda, och få samma minispelsutfall.
|
||||
- [ ] Ljud spelas vid ankomst och avgång; inget knaster vid loop.
|
||||
- [ ] Samma sparfil fungerar på Linux och Windows.
|
||||
|
||||
### Kommandon
|
||||
|
||||
```bash
|
||||
go test ./... # hela sviten
|
||||
go test -race -v ./... # utförligt med race-detektor
|
||||
go test ./internal/level/ -run TestAllShippedLevels -v # bara banorna
|
||||
go vet ./...
|
||||
go run ./tools/build -mode debug -run -- -smoke 90 # bygg + smoke-test med fönster
|
||||
```
|
||||
64
doc/plan.md
Normal file
64
doc/plan.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# jp-subway-pussel – plan
|
||||
|
||||
Navet för projektets dokumentation. Detaljerna ligger i de länkade filerna.
|
||||
|
||||
## Mål
|
||||
|
||||
Ett pixel art-pusselspel där ett sällskap ska hitta rätt tåg genom japanska
|
||||
stationer byggda som labyrinter, med skyltar på japanska som spelaren lär sig
|
||||
läsa. Spelet ska vara en enda binär med en resursmapp bredvid, lika lätt att
|
||||
bygga på Linux som på Windows, utan andra byggverktyg än Go.
|
||||
Hela spelidén: [spelbeskrivning.md](spelbeskrivning.md).
|
||||
|
||||
## Stack
|
||||
|
||||
Go 1.27 + Ebitengine v2.10, JSON-data, standardbibliotekets tester,
|
||||
byggverktyg i Go (`go run ./tools/build`), VS Code med `golang.go`.
|
||||
Motivering och alternativ som valts bort: [roadmap.md › Teknikval](roadmap.md#teknikval).
|
||||
|
||||
## Målplattformar
|
||||
|
||||
Linux x64 först. Windows x64 byggs från dag 1 (korsbygge utan C-verktyg)
|
||||
men speltestas på riktig Windows först i M12. Linux arm64 (Pi5) är inte ett
|
||||
mål för spelet, men Gitea-CI kan byggas på Pi5-runnern senare.
|
||||
|
||||
## Leverans
|
||||
|
||||
Mönster A enligt playbooken (nedladdningsbar binär), när projektet ska
|
||||
delas: `build/release/<os>-<arch>/` är redan formen som en release-zip ska
|
||||
ha. Repot är **lokalt** nu och synkas till Gitea senare (Björn skapar repot
|
||||
och lägger till `claude` som medlem, därefter `git remote add origin
|
||||
gitea-claude:brasse/jp-subway-pussel.git`).
|
||||
|
||||
## Milstolpar
|
||||
|
||||
M0 skelett ✓ → M1 rörelse → M2 första spelbara banan → M3 japanska/skyltar
|
||||
→ M4 lämmeltåget → M5 minikarta → M6 kort/biljetter/minispel → M7
|
||||
svårighet/poäng/debuffar → M8 progression/sparfiler → M9 navigeringslägen →
|
||||
M10 story-innehåll → M11 oändligt läge/NG+ → M12 ljud/polish/release.
|
||||
Innehåll per milstolpe: [roadmap.md › Milstolpar](roadmap.md#milstolpar).
|
||||
Vad som ska vara testat per milstolpe: [mal-och-tester.md](mal-och-tester.md).
|
||||
|
||||
## Idéer till expansioner (ej beslutade)
|
||||
|
||||
- **Baneditor i spelet** eller ett `tools/levelcheck` som ritar banor som
|
||||
PNG och rapporterar onåbara rutor – blir troligen nödvändigt i M10.
|
||||
- **Daglig utmaning:** oändligt läge med dagens datum som seed och en lokal
|
||||
topplista.
|
||||
- **Lärande-läge:** en ordlista i menyn över tecken man mött, med
|
||||
repetition – går hand i hand med skyltsystemet.
|
||||
- **Lokalt samarbete:** en andra spelare styr en av polarna (delad skärm på
|
||||
samma tangentbord/gamepad).
|
||||
- **Steam Deck:** Linux-binären bör fungera som den är; gamepad-stöd från M1
|
||||
gör det gratis.
|
||||
- **Modbara banor:** eftersom banor är JSON i `resources/data/levels` kan
|
||||
spelare lägga till egna – kräver bara att banväljaren läser mappen.
|
||||
|
||||
## Öppna frågor
|
||||
|
||||
- Repo-namn: behålla `pussel` (svenska) eller byta till `puzzle`?
|
||||
- "Game box-liknande" banval: tolkat som spelbräde/världskarta – stämmer det?
|
||||
- Font: PixelMplus (fler kanji, 10/12 px) eller Misaki (8 px, tajtare)?
|
||||
Avgörs i M3 när skyltar renderas på riktigt.
|
||||
- Ska Oändligt läge dela sparfil med story eller ha egen?
|
||||
- Hur många huvudbanor siktar vi på i storyn? (Påverkar M10:s omfattning.)
|
||||
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.
|
||||
189
doc/spelbeskrivning.md
Normal file
189
doc/spelbeskrivning.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# JP Subway Pussel – spelbeskrivning
|
||||
|
||||
Renskriven och omsorterad version av den ursprungliga idébeskrivningen
|
||||
(2026-10-23). Allt innehåll från originalet finns med; där originalet var
|
||||
otydligt står tolkningen i [§15](#15-tolkningar-av-originalet).
|
||||
|
||||
## 1. Koncept i korthet
|
||||
|
||||
- 2D-pusselspel i pixel art.
|
||||
- Du leder ett sällskap – *lämmeltåget* – genom japanska tågstationer som
|
||||
är byggda som labyrinter.
|
||||
- Målet på varje bana: **hitta rätt tåg och anländ till rätt resmål.**
|
||||
- Nästan alla skyltar är på japanska. Hur mycket du förstår beror på vad du
|
||||
har lärt dig.
|
||||
- Svårigheten kommer från sällskapets behov (mat, dryck, toa), tidsgränser,
|
||||
tågkort och biljetter, samt stationer och UI som är byggda för att förvirra.
|
||||
|
||||
## 2. Story
|
||||
|
||||
- Några polare är på semester i Japan.
|
||||
- Spelet **börjar på flygplatsen** när man landar och **slutar när man ska
|
||||
tillbaka till flygplatsen**.
|
||||
- Under resan upplever man Japan och köper saker: kläder, masker, hattar
|
||||
m.m. Dessa kan tas på och ger olika buffar allt eftersom man spelar.
|
||||
- Slutet är en animation där karaktärerna flyger iväg. Alla items och poäng
|
||||
från omgången visas, sedan rullar eftertexterna.
|
||||
- När storyn är klar låses **Oändligt läge** och **New Game+** upp.
|
||||
|
||||
## 3. Spellägen
|
||||
|
||||
### 3.1 Story-läge
|
||||
|
||||
- Banorna är statiska (handgjorda).
|
||||
- Minispelen är slumpade utifrån en **seed** som genereras när banan startas
|
||||
och sparas när man sparar spelet, så en laddad omgång ger samma utfall.
|
||||
- Två navigeringslägen att välja mellan:
|
||||
|
||||
| Läge | Så funkar det | Poäng |
|
||||
|------|---------------|-------|
|
||||
| **Listläge** | Du får en lista över vilket tåg du ska ta härnäst för att komma rätt. | Normal |
|
||||
| **Skyltläge** | Ingen lista. Du använder skyltar och terminaler för att lista ut vilka tåg som tar dig rätt. 1–4 olika vägar kan vara korrekta. Tar du ett tåg/buss vars slutstation ligger i fel riktning i förhållande till starten, eller hamnar för långt bort, förlorar du. | Högre |
|
||||
|
||||
### 3.2 Oändligt läge
|
||||
|
||||
- Låses upp när storyn är klar. Separat spelläge med egen poänglista.
|
||||
- Du får en slutstation. När du är framme får du dina poäng och sedan nästa
|
||||
mål. Målen är slumpade.
|
||||
|
||||
### 3.3 New Game+
|
||||
|
||||
- Spela om storyn och behåll alla dina skills.
|
||||
|
||||
## 4. En bana – kärnloopen
|
||||
|
||||
1. Du startar på en station (eller kliver av ett tåg).
|
||||
2. Stationen är en labyrint med skyltar. Du navigerar med hjälp av symboler,
|
||||
skyltar, terminaler och det du lärt dig (se §6).
|
||||
3. Du passerar spärrar (kräver kort eller biljett, se §8), hittar rätt
|
||||
perrong och kliver på rätt tåg innan det går.
|
||||
4. Banan är klar när du **anländer till rätt resmål**.
|
||||
|
||||
- De första och enklaste banorna är **ett enda tåg eller en buss**. Längre
|
||||
fram består en bana av **flera stopp och byten**.
|
||||
- På vissa tåg och bussar förekommer minispel: att **få plats** på ett fullt
|
||||
fordon, att **kunna ta sig av**, och att **veta vilken station** man ska
|
||||
gå av på.
|
||||
- Tåg avgår enligt tidtabell. Missar du ett tåg får du vänta på nästa, och på
|
||||
svåra banor kostar det tid du inte har (se §9).
|
||||
|
||||
## 5. Sällskapet – lämmeltåget
|
||||
|
||||
- Dina polare följer efter dig i en rad – därav *lämmeltåget*.
|
||||
- Varje karaktär har mätare för **mat**, **dryck** och **toa**.
|
||||
- Folk måste gå på toa, köpa dricka och kan bli distraherade.
|
||||
- **Ju fler i lämmeltåget, desto svårare** blir det och desto oftare händer
|
||||
specialhändelser (dricka, mat, toa m.m.).
|
||||
|
||||
## 6. Japanska, skyltar och hjälp
|
||||
|
||||
- Nästan alla skyltar i banorna är på japanska.
|
||||
- Hur mycket **engelska** som finns på skyltarna beror på banans svårighet:
|
||||
lätt bana = mer engelska, svår bana = nästan bara japanska.
|
||||
- Allt som översätts åt dig baserat på dina skills eller din japanska-nivå
|
||||
visas i **en annan färg**, eller måste **interageras med** för att visa
|
||||
översättningen.
|
||||
- Översättningen kan vara **delvis**: bara de tecken eller ord du har lärt
|
||||
dig översätts, resten står kvar på japanska.
|
||||
- Du kan **fråga en japan om hjälp**. Det tar tid, och tiden beror på hur bra
|
||||
din japanska är.
|
||||
- Ju bättre din japanska är, desto **fler hintar** kan synas i UI och i banan.
|
||||
- Huvudsyftet med stationslabyrinten är att navigera med symboler och
|
||||
skyltar, med stöd av dina skills.
|
||||
|
||||
## 7. Minikarta
|
||||
|
||||
- Visar bara **avgångar** och några **riktmärken** som man kan förhålla sig
|
||||
till.
|
||||
- När du upptäcker delar av stationen **fylls minikartan i** – för just den
|
||||
banan under just den spelomgången.
|
||||
|
||||
## 8. Tågkort, biljetter och telefon
|
||||
|
||||
- Du har ett **tågkort** (IC-kort) med saldo. Att hålla koll på kortet är en
|
||||
egen svårighetsgrad.
|
||||
- Är kortet tomt måste du **hitta en automat** och klara ett **minispel** för
|
||||
att fylla på.
|
||||
- På svårare banor måste du ibland köpa en **separat biljett**. Då kör du ett
|
||||
separat minispel för att köpa **rätt** biljett, annars kommer du inte på
|
||||
tåget i slutet av banan.
|
||||
- Har du kortet **i telefonen** får du en **speed-buff**, men med en liten
|
||||
procentchans att behöva **skanna flera gånger** i spärren eller vid
|
||||
påfyllning.
|
||||
- Telefonen har **batteri**. Dör det måste du köpa biljett i stället. Detta
|
||||
ska nästan bara kunna hända på **långa banor**.
|
||||
|
||||
## 9. Svårighet och tid
|
||||
|
||||
- **Lätta banor:** ingen tidsgräns, försök hur länge du vill.
|
||||
- **Svåra banor:** tidsgräns. Gör du för många fel missar du för många tåg
|
||||
och banan misslyckas.
|
||||
- **Extra svårigheter:** överstimulerande UI och banor byggda för att förvirra
|
||||
spelaren räknas som egna, extra svårigheter.
|
||||
- Variabler som styr svårighet: antal i sällskapet, andel engelska på
|
||||
skyltar, kort-/biljettkrav, tidsgräns, antal byten, UI-störningar.
|
||||
|
||||
## 10. Poäng
|
||||
|
||||
Per bana baseras poängen på:
|
||||
|
||||
- **Tid.**
|
||||
- **Minst pengar spenderade** och färst kortpåfyllningar.
|
||||
- Hur bra **alla karaktärers mat-, dryck- och toamätare** står vid målgång.
|
||||
- Skyltläge (§3.1) ger mer poäng än listläge.
|
||||
|
||||
## 11. Stats, buffar och debuffar
|
||||
|
||||
**Stats** som påverkas: speed, törst, fokus, toalett, tur.
|
||||
|
||||
**Debuffar** man kan drabbas av under spelet:
|
||||
|
||||
- onda fötter
|
||||
- trötthet
|
||||
- hunger / irritation
|
||||
- matförgiftning (kortare toamätare)
|
||||
|
||||
**Temporära debuffar** från sidouppdrag (varar 1–4 banor), beroende på hur
|
||||
bra man gjorde ifrån sig:
|
||||
|
||||
- träningsvärk
|
||||
- skoskav (köpt dåliga skor)
|
||||
- köpt något tungt eller stort
|
||||
- proppmätt
|
||||
- svettig och varm
|
||||
|
||||
**Buffar** kommer från kläder, masker, hattar och items som köps längs vägen,
|
||||
från skills i skill tree, och från unika skills man får av sidouppdrag.
|
||||
|
||||
## 12. Progression och upplåsningar
|
||||
|
||||
- **Level-ups** och ett **skill tree**.
|
||||
- **Skins** låses upp efter banor.
|
||||
- **Bankarta** i spelbrädes-/världskartestil där man väljer bana.
|
||||
- **Sidobanor** ger speciella skins, powers och items. Vissa items låser upp
|
||||
**genvägar** i andra huvudbanor.
|
||||
- **Många items och skills** – man ska knappt få tag på 33 % av allt under
|
||||
en omgång.
|
||||
- Sidouppdrag kan ge unika skills men också temporära debuffar (§11).
|
||||
|
||||
## 13. Ljud och grafik
|
||||
|
||||
- Pixel art.
|
||||
- Ljud som påminner om japanska stationer: **avgångsmelodier** och
|
||||
**ankomstjinglar** som spelas när tåg kommer och går.
|
||||
|
||||
## 14. Slump och sparande
|
||||
|
||||
- Story-banor är statiska. Minispel är slumpade utifrån banans seed.
|
||||
- Seeden genereras när banan startas och sparas med spelet.
|
||||
- Oändligt läge drar slumpade mål.
|
||||
- Sparfilen innehåller framsteg, items, skills, aktiva debuffar och seed.
|
||||
|
||||
## 15. Tolkningar av originalet
|
||||
|
||||
| Originalet | Tolkning här | Kommentar |
|
||||
|------------|--------------|-----------|
|
||||
| "Lämel tåg" | *Lämmeltåg*: sällskapet som följer efter dig i rad | Styr §5 |
|
||||
| "level maps game box liknande styl av level väljande" | Bankarta i spelbrädes-/världskartestil | Kan ändras om något annat avsågs |
|
||||
| "bilder och eventuella språk och tester" (resursmappen) | bilder, språk och *texter* | Se resurslayouten i roadmap |
|
||||
| Repo-namnet "jp-subway-pussel" | Behållet; *pussel* är korrekt svenska | Byt till `-puzzle` om det ska vara helengelskt |
|
||||
Reference in New Issue
Block a user