128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/config"
|
|
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game"
|
|
)
|
|
|
|
// startOfflineGame initialisiert eine lokale Spielrunde ohne Server
|
|
func (g *Game) startOfflineGame() {
|
|
g.resetForNewGame()
|
|
g.isOffline = true
|
|
g.connected = false // Explizit offline
|
|
g.appState = StateGame
|
|
|
|
// Initialen GameState lokal erstellen
|
|
g.stateMutex.Lock()
|
|
g.gameState = game.GameState{
|
|
Status: "RUNNING",
|
|
RoomID: "offline_solo",
|
|
Players: make(map[string]game.PlayerState),
|
|
WorldChunks: []game.ActiveChunk{{ChunkID: "start", X: 0}},
|
|
CurrentSpeed: config.RunSpeed,
|
|
DifficultyFactor: 0,
|
|
}
|
|
|
|
// Lokalen Spieler hinzufügen
|
|
g.gameState.Players[g.playerName] = game.PlayerState{
|
|
ID: g.playerName,
|
|
Name: g.playerName,
|
|
X: 100,
|
|
Y: 200,
|
|
IsAlive: true,
|
|
}
|
|
g.stateMutex.Unlock()
|
|
|
|
// Initialer Chunk-Library Check
|
|
if len(g.world.ChunkLibrary) == 0 {
|
|
log.Println("⚠️ Warnung: Keine Chunks in Library geladen!")
|
|
}
|
|
|
|
g.roundStartTime = time.Now()
|
|
g.predictedX = 100
|
|
g.predictedY = 200
|
|
g.currentSpeed = config.RunSpeed
|
|
|
|
g.audio.PlayMusic()
|
|
g.notifyGameStarted()
|
|
log.Println("🕹️ Offline-Modus gestartet")
|
|
}
|
|
|
|
// updateOfflineLoop simuliert die Server-Logik lokal
|
|
func (g *Game) updateOfflineLoop() {
|
|
if !g.isOffline || g.gameState.Status != "RUNNING" {
|
|
return
|
|
}
|
|
|
|
g.stateMutex.Lock()
|
|
defer g.stateMutex.Unlock()
|
|
|
|
elapsed := time.Since(g.roundStartTime).Seconds()
|
|
|
|
// 1. Schwierigkeit & Speed (analog zu pkg/server/room.go)
|
|
g.gameState.DifficultyFactor = elapsed / config.MaxDifficultySeconds
|
|
if g.gameState.DifficultyFactor > 1.0 {
|
|
g.gameState.DifficultyFactor = 1.0
|
|
}
|
|
|
|
speedIncrease := g.gameState.DifficultyFactor * g.gameState.DifficultyFactor * 18.0
|
|
g.gameState.CurrentSpeed = config.RunSpeed + speedIncrease
|
|
g.currentSpeed = g.gameState.CurrentSpeed
|
|
|
|
// 2. Scrolling
|
|
g.gameState.ScrollX += g.currentSpeed
|
|
|
|
// 3. Chunks nachladen
|
|
// Wenn das Ende der Map nah am rechten Rand ist, neuen Chunk spawnen
|
|
mapEnd := 0.0
|
|
for _, c := range g.gameState.WorldChunks {
|
|
chunkDef := g.world.ChunkLibrary[c.ChunkID]
|
|
end := c.X + float64(chunkDef.Width*config.TileSize)
|
|
if end > mapEnd {
|
|
mapEnd = end
|
|
}
|
|
}
|
|
|
|
if mapEnd < g.gameState.ScrollX+2500 {
|
|
g.spawnOfflineChunk(mapEnd)
|
|
}
|
|
|
|
// 4. Entferne alte Chunks (links aus dem Bild)
|
|
if len(g.gameState.WorldChunks) > 5 {
|
|
// Behalte immer mindestens die letzten paar Chunks
|
|
if g.gameState.WorldChunks[0].X < g.gameState.ScrollX-2000 {
|
|
g.gameState.WorldChunks = g.gameState.WorldChunks[1:]
|
|
}
|
|
}
|
|
|
|
// 5. Score Update (Distanz)
|
|
p, ok := g.gameState.Players[g.playerName]
|
|
if ok && p.IsAlive {
|
|
// Grobe Score-Simulation
|
|
p.Score = int(g.gameState.ScrollX / 10)
|
|
g.gameState.Players[g.playerName] = p
|
|
}
|
|
}
|
|
|
|
func (g *Game) spawnOfflineChunk(atX float64) {
|
|
// Zufälligen Chunk wählen
|
|
var pool []string
|
|
for id := range g.world.ChunkLibrary {
|
|
if id != "start" {
|
|
pool = append(pool, id)
|
|
}
|
|
}
|
|
|
|
if len(pool) > 0 {
|
|
randomID := pool[rand.Intn(len(pool))]
|
|
g.gameState.WorldChunks = append(g.gameState.WorldChunks, game.ActiveChunk{
|
|
ChunkID: randomID,
|
|
X: atX,
|
|
})
|
|
}
|
|
}
|