M8: progression, items, bankarta och sparfil
All checks were successful
release / build-release (push) Successful in 1m46s
All checks were successful
release / build-release (push) Successful in 1m46s
- internal/progress: katalog (skills.json 12 noder, items.json 25 items) med validering; XP/nivåer (150·n(n+1)/2) och skillpoäng; skillträd med krav och kostnad; items per plats med buffar, genvägar (JR Pass, kartor, powerbank) och färgton; banresultat och upplåsning (huvudbanor i ordning, sidospår efter föräldern); 33 %-regeln som test - internal/save: versionerad JSON med kunskap, plånbok, debuffar, progression och pågående bana + seed; atomisk skrivning; migrering; ~/.config/metro-puzzle-jp/save.json resp. %AppData% - sim: RunOptions får Extra/FogRadius/Landmarks/FreeGates/RevealAll/ InfiniteBattery; luck påverkar trängselzonen; Fog.RevealAll och extra landmärken - game: bankarta i spelbrädesstil ersätter menyn (⟳ återupptar med sparad seed), skillträd (T), garderob (I), butik i kiosken (B), XP/nivå/items/ upplåsningar på resultatet, spelaren tonas av skins; autospar vid banstart, efter banan och vid köp; flaggor -save/-nosave - level: kind/order/parent/rewards/shop; ny sidobana 002b Kabukicho som belönar skinnet Kimono; 001 belönar Salaryman-skinnet; butikssortiment på 002/003 - tools/shots: demo-sparfil (build/, aldrig den riktiga), bilder av karta, skills, garderob och butik; alla körningar med -nosave - docs/README/wiki uppdaterade Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
104
internal/game/shop.go
Normal file
104
internal/game/shop.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||
|
||||
"gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/progress"
|
||||
)
|
||||
|
||||
// Butiken i kiosken: banans sortiment (eller ett seedat urval), köps kontant.
|
||||
|
||||
type shop struct {
|
||||
items []progress.Item
|
||||
cursor int
|
||||
msg string
|
||||
}
|
||||
|
||||
const shopSize = 5
|
||||
|
||||
func (s *LevelScene) openShop(g *Game) {
|
||||
sh := &shop{}
|
||||
ids := s.run.Level.Shop
|
||||
if len(ids) == 0 {
|
||||
// Seedat urval ur allt köpbart, så att samma omgång ger samma butik.
|
||||
all := g.Catalog.Purchasable()
|
||||
r := s.run.Seed.Derive("shop").New()
|
||||
r.Shuffle(len(all), func(i, j int) { all[i], all[j] = all[j], all[i] })
|
||||
for _, it := range all {
|
||||
ids = append(ids, it.ID)
|
||||
if len(ids) >= shopSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, id := range ids {
|
||||
if it := g.Catalog.Item(id); it != nil {
|
||||
sh.items = append(sh.items, *it)
|
||||
}
|
||||
}
|
||||
s.shop = sh
|
||||
}
|
||||
|
||||
func (s *LevelScene) updateShop(g *Game) {
|
||||
sh := s.shop
|
||||
if backJustPressed() || shopJustPressed() {
|
||||
s.shop = nil
|
||||
return
|
||||
}
|
||||
if n := len(sh.items); n > 0 {
|
||||
sh.cursor = (sh.cursor + menuMove() + n) % n
|
||||
if confirmJustPressed() {
|
||||
it := sh.items[sh.cursor]
|
||||
switch {
|
||||
case g.Progress.Own(it.ID):
|
||||
sh.msg = g.Assets.T("shop.owned")
|
||||
case g.Progress.Buy(g.Catalog, it.ID, g.Wallet.PayCash):
|
||||
sh.msg = fmt.Sprintf(g.Assets.T("shop.bought"), it.Name.Get(UILang))
|
||||
g.Save()
|
||||
default:
|
||||
sh.msg = g.Assets.T("shop.too_expensive")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *LevelScene) drawShop(g *Game, screen *ebiten.Image) {
|
||||
a := g.Assets
|
||||
sh := s.shop
|
||||
p := image.Rect(12, 28, ScreenW-12, ScreenH-10)
|
||||
vector.DrawFilledRect(screen, float32(p.Min.X), float32(p.Min.Y), float32(p.Dx()), float32(p.Dy()), colPanel, false)
|
||||
vector.DrawFilledRect(screen, float32(p.Min.X), float32(p.Min.Y), float32(p.Dx()), 3, colKnown, false)
|
||||
x, y := p.Min.X+8, p.Min.Y+8
|
||||
a.DrawBig(screen, "売店", x, y, colKnown)
|
||||
a.Draw(screen, fmt.Sprintf("%s %s %d¥", a.T("shop.title"), a.T("hud.cash"), g.Wallet.Cash), x+36, y+2, colText)
|
||||
y += 24
|
||||
for i, it := range sh.items {
|
||||
ry := y + i*LineH
|
||||
if i == sh.cursor {
|
||||
vector.DrawFilledRect(screen, float32(x-2), float32(ry-1), float32(p.Dx()-12), LineH, colBar, false)
|
||||
}
|
||||
col := colText
|
||||
if g.Progress.Own(it.ID) {
|
||||
col = colGood
|
||||
} else if it.Price > g.Wallet.Cash {
|
||||
col = colDim
|
||||
}
|
||||
a.Draw(screen, it.Name.Get(UILang), x, ry, col)
|
||||
a.Draw(screen, effectText(a, it.Effect), x+110, ry, colDim)
|
||||
price := fmt.Sprintf("%d円", it.Price)
|
||||
if g.Progress.Own(it.ID) {
|
||||
price = a.T("items.owned_short")
|
||||
}
|
||||
a.Draw(screen, price, p.Max.X-10-a.Width(price), ry, col)
|
||||
}
|
||||
if sh.msg != "" {
|
||||
a.Draw(screen, sh.msg, x, p.Max.Y-28, colKnown)
|
||||
}
|
||||
a.Draw(screen, a.T("shop.hint"), x, p.Max.Y-16, colDim)
|
||||
_ = color.RGBA{}
|
||||
}
|
||||
Reference in New Issue
Block a user