All checks were successful
release / build-release (push) Successful in 1m49s
Inlärning enligt Björns regler: - lang.Knowledge: framsteg per ord (3 läsningar = känt), språkpoäng, köp av valfria ord (kostnad = tier), Award per stjärna - sim.Run: RunOptions med seed; stjärnor 1–3 mot par (parSec eller kortaste vägen × 0,5 s + 20 s); ≥2 stjärnor lär resmålets ord; att stanna på skylt/perrong ger seedad 35 % chans till framsteg per okänt ord - game: ordlista (L) med kända ord, framsteg och kostnad; stjärnor, poäng och inlärt resmål på resultatskärmen; framstegsnotis; flaggor -points/-seed M4 lämmeltåget: - sim.Party: medlemmar med mat/dryck/toa-mätare, behov under tröskel, seedade händelser var 45 s / antal (toa, törst, hunger, distraktion), fartstraff, toalett (W, 3 s/person) och kiosk (K, 150 ¥/person), följare på ledarens spår - level: rutor W och K, party och parSec i bandatan; banor med sällskap måste ha toalett och kiosk (testas); 001 har 2, 002 har 3 i sällskapet - game: följare med färgton, behovsmarkering över huvudet, mätarpanel, facilitetsrutor med förlopp; genart ritar toalett och kiosk - skriptläget: move stannar exakt på målrutan även när farten inte är bildruteexakt (sällskapets fartstraff), stall-skydd mot väggar - docs/README/wiki/spelbeskrivning uppdaterade Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
package game
|
|
|
|
import (
|
|
"fmt"
|
|
"image/color"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
|
|
|
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/lang"
|
|
)
|
|
|
|
// WordsScene är ordlistan/språkträdet: alla ord i ordboken, vad spelaren
|
|
// kan, framsteg på resten, och möjligheten att lägga språkpoäng på valfria
|
|
// ord. Blir ett riktigt träd med skills i M8.
|
|
type WordsScene struct {
|
|
back Scene
|
|
entries []*lang.Entry
|
|
sel int
|
|
top int
|
|
msg string
|
|
}
|
|
|
|
const wordsRows = 9
|
|
|
|
// NewWordsScene listar ordboken sorterad på tier och ord.
|
|
func NewWordsScene(a *Assets, back Scene) *WordsScene {
|
|
var es []*lang.Entry
|
|
for _, w := range a.Dict.Words() {
|
|
es = append(es, a.Dict.Lookup(w))
|
|
}
|
|
sort.Slice(es, func(i, j int) bool {
|
|
if es[i].Tier != es[j].Tier {
|
|
return es[i].Tier < es[j].Tier
|
|
}
|
|
return es[i].Word < es[j].Word
|
|
})
|
|
return &WordsScene{back: back, entries: es}
|
|
}
|
|
|
|
func (w *WordsScene) Update(g *Game) error {
|
|
if backJustPressed() || wordsJustPressed() {
|
|
g.SetScene(w.back)
|
|
return nil
|
|
}
|
|
if n := len(w.entries); n > 0 {
|
|
w.sel = (w.sel + menuMove() + n) % n
|
|
if w.sel < w.top {
|
|
w.top = w.sel
|
|
}
|
|
if w.sel >= w.top+wordsRows {
|
|
w.top = w.sel - wordsRows + 1
|
|
}
|
|
if confirmJustPressed() {
|
|
e := w.entries[w.sel]
|
|
switch {
|
|
case g.Know.Knows(e.Word):
|
|
w.msg = g.Assets.T("words.already")
|
|
case g.Know.Buy(e):
|
|
w.msg = fmt.Sprintf(g.Assets.T("words.bought"), e.Word, e.Translation(UILang))
|
|
default:
|
|
w.msg = fmt.Sprintf(g.Assets.T("words.too_expensive"), lang.WordCost(e))
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *WordsScene) Draw(g *Game, screen *ebiten.Image) {
|
|
a := g.Assets
|
|
k := g.Know
|
|
screen.Fill(color.RGBA{24, 20, 37, 255})
|
|
vector.DrawFilledRect(screen, 0, 0, ScreenW, 22, color.RGBA{38, 43, 68, 255}, false)
|
|
a.DrawBig(screen, a.T("words.title"), 8, 5, colText)
|
|
hdr := fmt.Sprintf("%s %d %s Lv%d %d/%d %s", a.T("words.points"), k.Points, a.T("hud.japanese"),
|
|
k.Level(), k.Count(), len(w.entries), a.T("hud.words"))
|
|
a.Draw(screen, hdr, ScreenW-8-a.Width(hdr), 6, colKnown)
|
|
|
|
y0 := 30
|
|
for i := w.top; i < len(w.entries) && i < w.top+wordsRows; i++ {
|
|
e := w.entries[i]
|
|
y := y0 + (i-w.top)*LineH
|
|
if i == w.sel {
|
|
vector.DrawFilledRect(screen, 4, float32(y-1), ScreenW-8, LineH, colBar, false)
|
|
}
|
|
status, scol := strings.Repeat("●", lang.WordCost(e)), colDim
|
|
if k.CanBuy(e) {
|
|
scol = colKnown
|
|
}
|
|
wcol := colText
|
|
switch {
|
|
case k.Knows(e.Word):
|
|
status, scol, wcol = "✓", colGood, colKnown
|
|
case k.ProgressOf(e.Word) > 0:
|
|
status, scol = fmt.Sprintf("%d/%d", k.ProgressOf(e.Word), lang.ProgressToLearn), colWarn
|
|
}
|
|
a.Draw(screen, e.Word, 8, y, wcol)
|
|
a.Draw(screen, e.Romaji, 92, y, colDim)
|
|
a.Draw(screen, e.Translation(UILang), 180, y, colText)
|
|
a.Draw(screen, status, ScreenW-8-a.Width(status), y, scol)
|
|
}
|
|
// rullningsindikator
|
|
if len(w.entries) > wordsRows {
|
|
a.Draw(screen, fmt.Sprintf("%d-%d / %d", w.top+1, min(len(w.entries), w.top+wordsRows), len(w.entries)), 8, ScreenH-38, colDim)
|
|
}
|
|
if w.msg != "" {
|
|
a.Draw(screen, w.msg, 8, ScreenH-26, colKnown)
|
|
}
|
|
a.Draw(screen, a.T("words.hint"), 8, ScreenH-13, colDim)
|
|
}
|