All checks were successful
release / build-release (push) Successful in 1m33s
Folk på stationen (NPC:er som vandrar, kliver av tåg och går mot utgången, blockerar spelaren men inte varandra), vänster-/högerfiler som bromsar på fel sida, bredare gångar, reklamaffischer (clutter), japanskt sorl i loop (noise), vagnval med kvinnovagn (stort avdrag med man i sällskapet, tidsstyrd), kömarkeringar på perrongen, trängsel per vagn (bonus för tom vagn, svettig-debuff och svårare resa i full vagn, släpp förbi passagerare) och att folk kliver av innan man får gå på. Ny bana 005 Ueno. Skärmdumpsverktyget kan filtrera på bana/skript. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
61 lines
1.6 KiB
Go
61 lines
1.6 KiB
Go
package minigame
|
|
|
|
import "gitea.brasse-pc.eu/brasse/metro-puzzle-jp/internal/rng"
|
|
|
|
// Crowd är "få plats på det fulla tåget": en markör pendlar över en stapel,
|
|
// tryck Enter när den är i den gröna zonen. Två försök, sedan går tåget.
|
|
type Crowd struct {
|
|
base
|
|
Pos float64 // markörens läge 0..1
|
|
dir float64
|
|
Speed float64 // enheter per sekund
|
|
ZoneLo float64
|
|
ZoneHi float64
|
|
Attempts int
|
|
MaxTries int
|
|
}
|
|
|
|
const crowdZoneWidth = 0.22
|
|
|
|
// NewCrowd seedar zonens läge och markörens fart. luck (1 = normalt) gör
|
|
// zonen bredare eller smalare, och crowdLevel (0 lite, 1 mellan, 2 mycket
|
|
// folk i vagnen) smalare ju fler som trängs.
|
|
func NewCrowd(seed rng.Seed, tries int, luck float64, crowdLevel int) *Crowd {
|
|
r := newRand(seed, "crowd")
|
|
level := 1.3 - 0.4*float64(max(0, min(2, crowdLevel)))
|
|
width := min(0.6, max(0.1, crowdZoneWidth*max(0.5, min(2, luck))*level))
|
|
lo := r.between(0.1, 0.9-width)
|
|
return &Crowd{dir: 1, Speed: r.between(0.9, 1.5), ZoneLo: lo, ZoneHi: lo + width, MaxTries: max(1, tries)}
|
|
}
|
|
|
|
// InZone rapporterar om markören är i zonen just nu.
|
|
func (g *Crowd) InZone() bool { return g.Pos >= g.ZoneLo && g.Pos <= g.ZoneHi }
|
|
|
|
// Update pendlar markören och tar emot försök.
|
|
func (g *Crowd) Update(in Input, dt float64) {
|
|
if g.done {
|
|
return
|
|
}
|
|
if in.Cancel {
|
|
g.done = true
|
|
return
|
|
}
|
|
g.Pos += g.dir * g.Speed * dt
|
|
for g.Pos < 0 || g.Pos > 1 {
|
|
if g.Pos < 0 {
|
|
g.Pos = -g.Pos
|
|
} else {
|
|
g.Pos = 2 - g.Pos
|
|
}
|
|
g.dir = -g.dir
|
|
}
|
|
if in.Confirm {
|
|
g.Attempts++
|
|
if g.InZone() {
|
|
g.done, g.success = true, true
|
|
} else if g.Attempts >= g.MaxTries {
|
|
g.done = true
|
|
}
|
|
}
|
|
}
|