M13: titelskärm, språkval, tutorial, tips och pausmeny
All checks were successful
release / build-release (push) Successful in 1m40s

Björns feedback efter v0.1.0. Titelskärm med premissen i text och menyn
Fortsätt/Starta, Tutorial, Inställningar, Avsluta (Enter två gånger);
språkval första gången spelet startar. Tutorial i fem sidor med riktiga
sprites och en exempelskylt där resmålet markeras och resten tonas ned,
plus nyckeln 番線/方面/改札 och biljettipset. Kontextuella tips i spelet
tills första banan är klarad, och resmålets tecken markeras på skyltar
och avgångstavlor under tiden. Esc i en bana öppnar en pausmeny
(Fortsätt, Lämna banan, Inställningar, Avsluta spelet) i stället för att
lämna banan; Esc på bankartan går till titeln. Kortare lägestexter så att
bankartans rader ryms på svenska. Test för markeringen, docs, wiki och
skärmdumpar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 17:13:32 +01:00
parent 86f8130735
commit f0a0bc1522
26 changed files with 622 additions and 32 deletions

View File

@@ -38,14 +38,17 @@ const (
// LevelScene är själva spelandet av en bana. All spellogik ligger i sim.Run;
// scenen översätter input och ritar.
type LevelScene struct {
id string
level *level.Level // aktuell delbana (byts när resan fortsätter på nästa station)
run *sim.Run
endless bool // målet är ett lottat mål i oändligt läge (inte storyn)
sfx sfxState
cam *sim.Camera
animT float64
hideMap bool // M döljer/visar minikartan
id string
level *level.Level // aktuell delbana (byts när resan fortsätter på nästa station)
run *sim.Run
endless bool // målet är ett lottat mål i oändligt läge (inte storyn)
sfx sfxState
tips tipState
highlight bool // tutorialen: resmålets tecken markeras på skyltar, resten tonas ned
infoBox image.Rectangle // inforutans läge denna bildruta (tom = ingen), så att tipsen inte täcker den
cam *sim.Camera
animT float64
hideMap bool // M döljer/visar minikartan
shop *shop // öppen butik i kiosken (pausar banan)
outcome LevelOutcome // progression från banan (fylls i när den avgjorts)
@@ -185,6 +188,8 @@ func (s *LevelScene) Update(g *Game) error {
}
s.updateEffects(g)
s.updateSfx(g)
s.updateTips(g)
s.highlight = s.tutorialActive(g)
if s.run.Mini != nil {
// Minispel: all input går dit; Esc avbryter minispelet, inte banan.
mx, my := miniMoveXY()
@@ -199,7 +204,7 @@ func (s *LevelScene) Update(g *Game) error {
return nil
}
if backJustPressed() {
g.SetScene(NewMapScene(g))
g.SetScene(NewPauseScene(s)) // Esc pausar; att lämna banan kräver ett val i menyn
return nil
}
if shopJustPressed() && !s.run.Player.Moving() && s.run.Level.At(s.run.Player.Tile) == level.Kiosk {
@@ -353,6 +358,7 @@ func (s *LevelScene) Draw(g *Game, screen *ebiten.Image) {
s.drawIndicator(screen, ox, oy)
s.drawHUD(g, screen)
s.drawTip(g, screen)
if r := s.run; r.TransferAt >= 0 && r.Time-r.TransferAt < transferBannerSec && r.Mini == nil && r.Outcome == sim.Ongoing {
txt := g.Assets.T("hud.transfer_done")
w := g.Assets.Width(txt) + 16
@@ -517,6 +523,7 @@ func (s *LevelScene) drawHUD(g *Game, screen *ebiten.Image) {
}
box = image.Rect(0, y, ScreenW, y+h)
}
s.infoBox = box
if !s.hideMap {
s.drawMinimap(g, screen, box, hasBox)
}
@@ -553,7 +560,11 @@ func (s *LevelScene) infoLines(a *Assets) (lines []line, accent color.Color, bar
if tr, at, secs := r.PlatformHere(); tr != nil {
// Avgångstavlan är en skylt som alla andra: japanska, sedd genom kunskapen.
rd := lang.Render(a.Dict, r.Know, tr.BoardText(), UILang)
lines = append(lines, a.wrapLine(shownLine(rd.Original, colText, r.Know.ShowsReadings()), maxW)...)
if s.highlight {
lines = append(lines, a.wrapLine(highlightLine(tr.BoardText(), lvl.Destination.Get("ja"), colGood, colDim), maxW)...)
} else {
lines = append(lines, a.wrapLine(shownLine(rd.Original, colText, r.Know.ShowsReadings()), maxW)...)
}
lines = append(lines, a.wrapLine(shownLine(rd.Partial, colText, false), maxW)...)
if english {
lines = append(lines, a.wrapLine(plainLine(fmt.Sprintf("%s: Track %s %s for %s", a.T("hud.english"), tr.Track,
@@ -594,7 +605,11 @@ func (s *LevelScene) infoLines(a *Assets) (lines []line, accent color.Color, bar
accent = colKnown
}
rd := lang.Render(a.Dict, know, sg.Text["ja"], UILang)
lines = append(lines, a.wrapLine(shownLine(rd.Original, colText, r.Know.ShowsReadings()), maxW)...)
if s.highlight {
lines = append(lines, a.wrapLine(highlightLine(sg.Text["ja"], lvl.Destination.Get("ja"), colGood, colDim), maxW)...)
} else {
lines = append(lines, a.wrapLine(shownLine(rd.Original, colText, r.Know.ShowsReadings()), maxW)...)
}
lines = append(lines, a.wrapLine(shownLine(rd.Partial, colText, false), maxW)...)
if english {
lines = append(lines, a.wrapLine(plainLine(a.T("hud.english")+": "+sg.Text.Get("en"), colEnglish), maxW)...)