fix game
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 7m3s
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 7m3s
This commit is contained in:
@@ -15,12 +15,16 @@ const (
|
||||
TileSize = 64
|
||||
|
||||
// Player Movement (bei 20 TPS)
|
||||
RunSpeed = 21.0 // Basis-Scroll-Geschwindigkeit
|
||||
PlayerSpeed = 33.0 // Links/Rechts Bewegung relativ zu Scroll (war 11.0 * 3)
|
||||
JumpVelocity = 24.0 // Sprunghöhe (reduziert für besseres Gefühl)
|
||||
FastFall = 45.0 // Schnell-Fall nach unten
|
||||
WallSlideMax = 9.0 // Maximale Rutsch-Geschwindigkeit an Wand
|
||||
WallClimbSpeed = 15.0 // Kletter-Geschwindigkeit
|
||||
RunSpeed = 21.0 // Basis-Scroll-Geschwindigkeit
|
||||
PlayerSpeed = 33.0 // Links/Rechts Bewegung relativ zu Scroll (war 11.0 * 3)
|
||||
AirControlFactor = 0.4 // In der Luft: nur 40% der normalen Horizontalkontrolle (Basis)
|
||||
AirControlMin = 0.15 // Minimale Air-Control bei maximaler Schwierigkeit
|
||||
JumpVelocity = 24.0 // Sprunghöhe (reduziert für besseres Gefühl)
|
||||
FastFall = 45.0 // Schnell-Fall nach unten
|
||||
WallSlideMax = 9.0 // Maximale Rutsch-Geschwindigkeit an Wand
|
||||
WallClimbSpeed = 15.0 // Kletter-Geschwindigkeit
|
||||
GravityMax = 2.8 // Maximale Gravitation (bei DifficultyFactor=1.0)
|
||||
MaxDifficultySeconds = 180.0 // Sekunden bis maximale Schwierigkeit erreicht ist
|
||||
|
||||
// Gameplay
|
||||
StartTime = 5 // Sekunden Countdown
|
||||
|
||||
@@ -123,6 +123,7 @@ type GameState struct {
|
||||
MovingPlatforms []MovingPlatformSync `json:"moving_platforms"` // Bewegende Plattformen
|
||||
Sequence uint32 `json:"sequence"` // Sequenznummer für Out-of-Order-Erkennung
|
||||
CurrentSpeed float64 `json:"current_speed"` // Aktuelle Scroll-Geschwindigkeit (für Client-Prediction)
|
||||
DifficultyFactor float64 `json:"difficulty_factor"` // 0.0 (Anfang) bis 1.0 (Maximum) – skaliert Gravitation & Air-Control
|
||||
}
|
||||
|
||||
// MovingPlatformSync: Synchronisiert die Position einer bewegenden Plattform
|
||||
|
||||
@@ -56,11 +56,23 @@ func ApplyPhysics(
|
||||
state *PlayerPhysicsState,
|
||||
input PhysicsInput,
|
||||
currentSpeed float64,
|
||||
difficultyFactor float64,
|
||||
collisionChecker CollisionChecker,
|
||||
playerConst PlayerConstants,
|
||||
) {
|
||||
// Schwierigkeits-skalierte Parameter
|
||||
// Air Control sinkt von AirControlFactor (0.4) auf AirControlMin (0.15)
|
||||
effectiveAirControl := config.AirControlFactor - (config.AirControlFactor-config.AirControlMin)*difficultyFactor
|
||||
// Gravitation steigt von Gravity (1.5) auf GravityMax (2.8)
|
||||
effectiveGravity := config.Gravity + (config.GravityMax-config.Gravity)*difficultyFactor
|
||||
|
||||
// --- HORIZONTALE BEWEGUNG MIT KOLLISION ---
|
||||
playerMovement := input.InputX * config.PlayerSpeed
|
||||
// In der Luft: reduzierte Horizontalkontrolle (skaliert mit Schwierigkeit)
|
||||
airControl := 1.0
|
||||
if !state.OnGround && !state.OnWall {
|
||||
airControl = effectiveAirControl
|
||||
}
|
||||
playerMovement := input.InputX * config.PlayerSpeed * airControl
|
||||
speed := currentSpeed + playerMovement
|
||||
nextX := state.X + speed
|
||||
|
||||
@@ -96,8 +108,8 @@ func ApplyPhysics(
|
||||
state.VY = -config.WallClimbSpeed
|
||||
}
|
||||
} else {
|
||||
// Normal: Volle Gravität
|
||||
state.VY += config.Gravity
|
||||
// Normal: Schwierigkeit-skalierte Gravität
|
||||
state.VY += effectiveGravity
|
||||
if state.VY > config.MaxFall {
|
||||
state.VY = config.MaxFall
|
||||
}
|
||||
|
||||
@@ -106,6 +106,52 @@ func (lb *Leaderboard) AddScore(name, code string, score int) (bool, string) {
|
||||
return true, proofCode
|
||||
}
|
||||
|
||||
// AdminLeaderboardEntry ist ein LeaderboardEntry mit zusätzlichem Key und Validierungsstatus
|
||||
type AdminLeaderboardEntry struct {
|
||||
game.LeaderboardEntry
|
||||
Key string `json:"key"`
|
||||
Valid bool `json:"valid"`
|
||||
}
|
||||
|
||||
// GetAll gibt alle Leaderboard-Einträge zurück (für Admin-Panel)
|
||||
func (lb *Leaderboard) GetAll() []AdminLeaderboardEntry {
|
||||
raw, err := lb.rdb.HGetAll(lb.ctx, "leaderboard:entries").Result()
|
||||
if err != nil {
|
||||
log.Printf("⚠️ Fehler beim Abrufen aller Einträge: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
entries := make([]AdminLeaderboardEntry, 0, len(raw))
|
||||
for key, dataStr := range raw {
|
||||
var e game.LeaderboardEntry
|
||||
if err := json.Unmarshal([]byte(dataStr), &e); err != nil {
|
||||
continue
|
||||
}
|
||||
expected := GenerateProofCode(e.PlayerCode, e.Score, e.Timestamp)
|
||||
entries = append(entries, AdminLeaderboardEntry{
|
||||
LeaderboardEntry: e,
|
||||
Key: key,
|
||||
Valid: e.ProofCode == expected,
|
||||
})
|
||||
}
|
||||
|
||||
// Absteigend nach Score sortieren
|
||||
for i := 0; i < len(entries); i++ {
|
||||
for j := i + 1; j < len(entries); j++ {
|
||||
if entries[j].Score > entries[i].Score {
|
||||
entries[i], entries[j] = entries[j], entries[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
// DeleteEntry löscht einen Eintrag aus Leaderboard (Hash + Sorted Set)
|
||||
func (lb *Leaderboard) DeleteEntry(key string) error {
|
||||
lb.rdb.ZRem(lb.ctx, leaderboardKey, key)
|
||||
return lb.rdb.HDel(lb.ctx, "leaderboard:entries", key).Err()
|
||||
}
|
||||
|
||||
func (lb *Leaderboard) GetTop10() []game.LeaderboardEntry {
|
||||
// Hole Top 10 (höchste Scores zuerst)
|
||||
uniqueKeys, err := lb.rdb.ZRevRange(lb.ctx, leaderboardKey, 0, 9).Result()
|
||||
|
||||
@@ -79,6 +79,7 @@ type Room struct {
|
||||
CollectedPowerups map[string]bool // Key: "chunkID_objectIndex"
|
||||
ScoreAccum float64 // Akkumulator für Distanz-Score
|
||||
CurrentSpeed float64 // Aktuelle Geschwindigkeit (steigt mit der Zeit)
|
||||
DifficultyFactor float64 // 0.0 (Start) bis 1.0 (Maximum) – skaliert Schwierigkeit
|
||||
GameStartTime time.Time // Wann das Spiel gestartet wurde
|
||||
|
||||
// Chunk-Pool für fairen Random-Spawn
|
||||
@@ -368,12 +369,17 @@ func (r *Room) Update() {
|
||||
r.CurrentSpeed = config.RunSpeed
|
||||
}
|
||||
} else if r.Status == "RUNNING" {
|
||||
// Geschwindigkeit erhöhen: +0.5 pro 10 Sekunden (max +5.0 nach 100 Sekunden)
|
||||
elapsed := time.Since(r.GameStartTime).Seconds()
|
||||
speedIncrease := (elapsed / 10.0) * 0.5
|
||||
if speedIncrease > 5.0 {
|
||||
speedIncrease = 5.0
|
||||
|
||||
// DifficultyFactor: 0.0 am Start, 1.0 nach MaxDifficultySeconds (180s)
|
||||
r.DifficultyFactor = elapsed / config.MaxDifficultySeconds
|
||||
if r.DifficultyFactor > 1.0 {
|
||||
r.DifficultyFactor = 1.0
|
||||
}
|
||||
|
||||
// Geschwindigkeit: quadratische Kurve → am Anfang langsam, dann immer schneller
|
||||
// Bei MaxDifficultySeconds: +18 auf RunSpeed (39 total)
|
||||
speedIncrease := r.DifficultyFactor * r.DifficultyFactor * 18.0
|
||||
r.CurrentSpeed = config.RunSpeed + speedIncrease
|
||||
|
||||
r.GlobalScrollX += r.CurrentSpeed
|
||||
@@ -429,7 +435,7 @@ func (r *Room) Update() {
|
||||
}
|
||||
|
||||
// Gemeinsame Physik anwenden (1:1 wie Client!)
|
||||
physics.ApplyPhysics(&state, physicsInput, r.CurrentSpeed, collisionChecker, physics.DefaultPlayerConstants())
|
||||
physics.ApplyPhysics(&state, physicsInput, r.CurrentSpeed, r.DifficultyFactor, collisionChecker, physics.DefaultPlayerConstants())
|
||||
|
||||
// Ergebnis zurückschreiben
|
||||
p.X = state.X
|
||||
@@ -829,6 +835,7 @@ func (r *Room) Broadcast() {
|
||||
MovingPlatforms: make([]game.MovingPlatformSync, 0, len(r.MovingPlatforms)),
|
||||
Sequence: r.sequence,
|
||||
CurrentSpeed: r.CurrentSpeed,
|
||||
DifficultyFactor: r.DifficultyFactor,
|
||||
}
|
||||
|
||||
for id, p := range r.Players {
|
||||
|
||||
Reference in New Issue
Block a user