Files
metro-puzzle-jp/internal/game/scene_result.go
claude f762f9554e
All checks were successful
release / build-release (push) Successful in 1m34s
M9: navigeringslägen, linjenät och terminal
internal/nav med resources/data/network.json (76 stationer, 11 linjer,
Yamanote som ringlinje). Tåg bedöms från lineId + terminus mot banans
station/to: rätt, fel håll, för långt bort (fler än 12 stationer) eller
ingen trafik; correct räknas ut för nätkopplade banor, 1-4 rätta tåg.
Tågresan visar linjens riktiga stationer. Nya förlustorsaker "Fel håll"
och "För långt bort". Listläge (nästa tåg nere till vänster) och
skyltläge (+50 % poäng) växlas med N på bankartan och sparas; -mode.
Terminalen: biljettautomaten visar linjetavlan på nätbanor. Perronger
P p Q q R r. Bana 006 Ikebukuro med fyra perronger. Banorna 001-005
kopplade till nätet. Skript: waitover och pick calm; poängraden
radbryts; skärmdumpar uppdaterade.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 13:07:36 +02:00

159 lines
5.5 KiB
Go

package game
import (
"fmt"
"strings"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/vector"
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/sim"
)
// ResultScene visas när banan är avgjord (rätt eller fel tåg).
type ResultScene struct {
from *LevelScene
}
// NewResultScene bygger resultatet för banan som just spelades.
func NewResultScene(from *LevelScene) *ResultScene { return &ResultScene{from: from} }
func (r *ResultScene) Update(g *Game) error {
switch {
case wordsJustPressed():
g.SetScene(NewWordsScene(g.Assets, r))
case inpututil_R():
s, err := g.startLevel(r.from.id)
if err != nil {
return err
}
g.SetScene(s)
case confirmJustPressed() || backJustPressed():
g.SetScene(NewMapScene(g))
}
return nil
}
func (r *ResultScene) Draw(g *Game, screen *ebiten.Image) {
r.from.Draw(g, screen) // banan i bakgrunden
run := r.from.run
a := g.Assets
vector.DrawFilledRect(screen, 20, 30, ScreenW-40, 144, colPanel, false)
accent, headline := colBad, a.T("level.lost")
if run.Outcome == sim.Won {
accent, headline = colGood, a.T("level.cleared")
}
vector.DrawFilledRect(screen, 20, 30, ScreenW-40, 3, accent, false)
a.DrawBig(screen, headline, 28, 36, accent)
if run.Outcome == sim.Won {
stars := strings.Repeat("★", run.Stars) + strings.Repeat("☆", 3-run.Stars)
a.DrawBig(screen, stars, ScreenW-28-a.Width(stars)-8, 36, colWarn)
}
y := 54
if run.Boarded == nil && run.Outcome == sim.Lost {
a.Draw(screen, a.T(run.LostReason), 28, y, colText)
y += LineH
}
if tr := run.Boarded; tr != nil {
a.Draw(screen, fmt.Sprintf("%s%s %s %s%s", tr.Track, a.T("hud.track_suffix_ja"), tr.Line.Get("ja"),
tr.Destination.Get("ja"), a.T("hud.for_ja")), 28, y, colKnown)
y += LineH
if run.Outcome == sim.Lost {
reason := a.T(run.LostReason)
if detail, ok := map[string]string{
sim.LostWrongTrain: "result.wrong_detail",
sim.LostWrongDirection: "result.wrong_direction_detail",
sim.LostTooFar: "result.too_far_detail",
}[run.LostReason]; ok {
reason += " " + fmt.Sprintf(a.T(detail), tr.Destination.Get("romaji"), run.Level.Destination.Get("romaji"))
}
for _, l := range a.wrapLine(plainLine(reason, colText), ScreenW-56) {
a.drawLines(screen, []line{l}, 28, y)
y += LineH
}
}
}
y += 4
a.Draw(screen, fmt.Sprintf("%s %.1fs (%s %.0fs) %s %d %s %.0f %%", a.T("hud.time"), run.Time, a.T("result.par"), run.ParSec(),
a.T("hud.steps"), run.Steps, a.T("result.explored"), 100*run.Fog.Explored(run.Level)), 28, y, colText)
y += LineH
a.Draw(screen, fmt.Sprintf("%s %d %s %d¥ %s %d¥ %s %d", a.T("result.gates"), run.GatePasses, a.T("hud.card"), run.Wallet.Card,
a.T("result.spent"), run.Wallet.Spent, a.T("result.missed_short"), run.MissedTrains), 28, y, colText)
y += LineH
if run.Outcome == sim.Won {
sc := run.Score
// Poängen som en uträkning; radbryts till högst två rader.
parts := []string{
fmt.Sprintf("%s %d", strings.ToLower(a.T("hud.time")), sc.Time), fmt.Sprintf("%s %d", a.T("result.money"), sc.Money),
fmt.Sprintf("%s %d", a.T("result.meters"), sc.Meters), fmt.Sprintf("%s %d", a.T("result.map"), sc.Explore),
fmt.Sprintf("%s %d", a.T("result.car"), sc.Car),
}
if sc.Bonus > 0 {
parts = append(parts, fmt.Sprintf("%s %d", a.T("result.bonus"), sc.Bonus))
}
total := fmt.Sprintf("%s %d = %s", a.T("result.score"), sc.Total, strings.Join(parts, " + "))
if sc.Penalty > 0 {
total += fmt.Sprintf(" - %s %d", a.T("result.penalty"), sc.Penalty)
}
for i, l := range a.wrapLine(plainLine(total, colText), ScreenW-56) {
if i > 1 {
break
}
a.drawLines(screen, []line{l}, 28, y)
y += LineH
}
msg := fmt.Sprintf("+%d %s", run.PointsEarned, a.T("result.lang_points"))
if len(run.LearnedDest) > 0 {
msg += " " + a.T("hud.learned") + ": " + strings.Join(run.LearnedDest, " ") + " (" + a.T("result.destination") + ")"
}
a.Draw(screen, msg, 28, y, colKnown)
y += LineH
}
if o := r.from.outcome; run.Outcome == sim.Won {
prog := fmt.Sprintf("+%d %s", o.XP, a.T("map.xp"))
if o.LevelUps > 0 {
prog += fmt.Sprintf(" %s %d (+%d %s)", a.T("result.level_up"), g.Progress.Level(), o.LevelUps+o.NewPoints, a.T("map.skill_points"))
} else if o.NewPoints > 0 {
prog += fmt.Sprintf(" +%d %s", o.NewPoints, a.T("map.skill_points"))
}
if len(o.NewItems) > 0 {
var names []string
for _, id := range o.NewItems {
names = append(names, g.Catalog.Item(id).Name.Get(UILang))
}
prog += " " + a.T("result.new_items") + ": " + strings.Join(names, ", ")
}
if len(o.Unlocked) > 0 {
var names []string
for _, id := range o.Unlocked {
if l := g.LevelByID(id); l != nil {
names = append(names, l.Name.Get(UILang))
}
}
prog += " " + a.T("result.unlocked") + ": " + strings.Join(names, ", ")
}
for i, l := range a.wrapLine(plainLine(prog, colGood), ScreenW-56) {
if i > 1 {
break
}
a.drawLines(screen, []line{l}, 28, y)
y += LineH
}
}
if len(run.NewDebuffs) > 0 {
var parts []string
for _, d := range run.NewDebuffs {
parts = append(parts, fmt.Sprintf("%s (%d)", a.T("debuff."+string(d.Kind)), d.LevelsLeft))
}
a.Draw(screen, a.T("result.new_debuffs")+": "+strings.Join(parts, ", "), 28, y, colBad)
y += LineH
}
if y <= 149 {
a.Draw(screen, fmt.Sprintf("%s Lv%d %d %s %s %d (%d %s)", a.T("hud.japanese"), run.Know.Level(), run.Know.Count(),
a.T("hud.words"), a.T("words.points"), run.Know.Points, run.Know.Helps, a.T("result.helps")), 28, y, colDim)
}
a.Draw(screen, a.T("result.hint"), 28, 161, colDim)
}