Private
Public Access
1
0

fix game
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 6m53s

This commit is contained in:
Sebastian Unterschütz
2026-03-22 17:43:51 +01:00
parent 0aa81a2edc
commit ced5011718
2 changed files with 430 additions and 475 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@ import (
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/hajimehoshi/ebiten/v2/text"
"github.com/hajimehoshi/ebiten/v2/vector"
"github.com/nats-io/nats.go"
"golang.org/x/image/font/basicfont"
"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game"
@@ -30,14 +29,12 @@ const (
StateLobby = 1
StateGame = 2
StateLeaderboard = 3
RefFloorY = 540 // Server-Welt Boden-Position (unveränderlich)
RefFloorYMobile = 270 // Nicht mehr verwendet
RefFloorY = 540 // Server-Welt Boden-Position (unveränderlich)
)
var (
ColText = color.White
ColBtnNormal = color.RGBA{40, 44, 52, 255}
ColBtnHover = color.RGBA{60, 66, 78, 255}
ColSky = color.RGBA{135, 206, 235, 255}
ColGrass = color.RGBA{34, 139, 34, 255}
ColDirt = color.RGBA{101, 67, 33, 255}
@@ -55,8 +52,7 @@ type InputState struct {
// --- GAME STRUCT ---
type Game struct {
appState int
conn *nats.EncodedConn
appState int
wsConn *wsConn // WebSocket für WASM
connGeneration int // Erhöht bei jedem Disconnect; macht alte WS-Handler ungültig
isConnecting bool // Guard gegen mehrfaches connectAndStart()
@@ -227,63 +223,42 @@ func (g *Game) Update() error {
g.pendingInputCount = len(g.pendingInputs)
g.predictionMutex.Unlock()
// Aktuellen Status einmalig (thread-safe) lesen
g.stateMutex.Lock()
currentStatus := g.gameState.Status
g.stateMutex.Unlock()
// Game Over Handling
if g.appState == StateGame && g.gameState.Status == "GAMEOVER" {
// Back Button (oben links) - Touch Support
if g.appState == StateGame && currentStatus == "GAMEOVER" {
backBtnW, backBtnH := 120, 40
backBtnX, backBtnY := 20, 20
if isHit(backBtnX, backBtnY, backBtnW, backBtnH) {
g.appState = StateMenu
g.connected = false
g.scoreSubmitted = false
g.teamName = ""
g.activeField = ""
if g.conn != nil {
g.conn.Drain()
g.conn.Close()
}
g.gameState = game.GameState{Players: make(map[string]game.PlayerState)}
if isHit(20, 20, backBtnW, backBtnH) {
g.returnToMenu()
log.Println("🔙 Zurück zum Menü (Back Button)")
return nil
}
// ESC zurück zum Menü
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
g.appState = StateMenu
g.connected = false
g.scoreSubmitted = false
g.teamName = ""
g.activeField = ""
if g.conn != nil {
g.conn.Drain()
g.conn.Close()
}
g.gameState = game.GameState{Players: make(map[string]game.PlayerState)}
g.returnToMenu()
log.Println("🔙 Zurück zum Menü (ESC)")
return nil
}
// Host: Team-Name Eingabe
if g.isHost {
g.handleGameOverInput()
}
}
// COUNTDOWN/RUNNING-Übergang: AppState auf StateGame setzen + JS benachrichtigen
newStatus := g.gameState.Status
if (newStatus == "COUNTDOWN" || newStatus == "RUNNING") && g.appState != StateGame {
log.Printf("🎮 Spiel startet! Status: %s -> %s", g.lastStatus, newStatus)
if (currentStatus == "COUNTDOWN" || currentStatus == "RUNNING") && g.appState != StateGame {
log.Printf("🎮 Spiel startet! Status: %s -> %s", g.lastStatus, currentStatus)
g.appState = StateGame
g.notifyGameStarted()
}
if newStatus == "RUNNING" && g.lastStatus != "RUNNING" {
if currentStatus == "RUNNING" && g.lastStatus != "RUNNING" {
g.audio.PlayMusic()
}
// Musik stoppen wenn Game Over
if g.gameState.Status == "GAMEOVER" && g.lastStatus == "RUNNING" {
if currentStatus == "GAMEOVER" && g.lastStatus == "RUNNING" {
g.audio.StopMusic()
}
g.lastStatus = g.gameState.Status
g.lastStatus = currentStatus
switch g.appState {
case StateMenu:
@@ -418,14 +393,13 @@ func (g *Game) updateLobby() {
}
// Zurück Button
backW, backH := 100, 40
if isHit(50, 50, backW, backH) {
if g.conn != nil {
g.conn.Close()
}
if isHit(50, 50, 100, 40) {
g.disconnectFromServer()
g.appState = StateMenu
g.connected = false
g.stateMutex.Lock()
g.gameState = game.GameState{Players: make(map[string]game.PlayerState)}
g.stateMutex.Unlock()
}
// Lobby State Change Detection (für HTML-Updates)
@@ -692,12 +666,6 @@ func GetFloorYFromHeight(screenHeight int) float64 {
return floorY
}
// GetFloorY - Wrapper der versucht die Höhe zu bekommen (deprecated, benutze GetFloorYFromHeight)
func GetFloorY() float64 {
_, h := ebiten.WindowSize()
return GetFloorYFromHeight(h)
}
// GetScale gibt den Scale-Faktor zurück um die Spielwelt an den Bildschirm anzupassen
// Auf Mobile: Scale < 1.0 (rauszoomen, damit mehr sichtbar ist)
// Auf Desktop: Scale = 1.0 (normale Größe)
@@ -748,15 +716,6 @@ func WorldToScreenYWithHeight(worldY float64, screenHeight int) float64 {
return worldY + yOffset
}
// WorldToScreenY - Legacy wrapper (versucht WindowSize zu verwenden, funktioniert nicht in WASM!)
func WorldToScreenY(worldY float64) float64 {
_, h := ebiten.WindowSize()
if h == 0 {
h = ScreenHeight // Fallback
}
return WorldToScreenYWithHeight(worldY, h)
}
func isHit(x, y, w, h int) bool {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
mx, my := ebiten.CursorPosition()
@@ -854,6 +813,19 @@ func (g *Game) handleGameOverInput() {
}
}
// returnToMenu trennt die Verbindung und setzt den App-State zurück auf das Hauptmenü.
func (g *Game) returnToMenu() {
g.disconnectFromServer()
g.appState = StateMenu
g.connected = false
g.scoreSubmitted = false
g.teamName = ""
g.activeField = ""
g.stateMutex.Lock()
g.gameState = game.GameState{Players: make(map[string]game.PlayerState)}
g.stateMutex.Unlock()
}
func generateRoomCode() string {
mrand.Seed(time.Now().UnixNano())
chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -1006,14 +978,17 @@ func (g *Game) DrawLeaderboard(screen *ebiten.Image) {
// Titel
text.Draw(screen, "=== TOP 10 LEADERBOARD ===", basicfont.Face7x13, ScreenWidth/2-100, 80, color.RGBA{255, 215, 0, 255})
// Leaderboard abrufen wenn leer
// Leaderboard abrufen wenn leer (prüfen ohne Lock, dann ggf. nachladen)
g.leaderboardMutex.Lock()
if len(g.leaderboard) == 0 && g.connected {
g.leaderboardMutex.Unlock()
empty := len(g.leaderboard) == 0
g.leaderboardMutex.Unlock()
if empty && g.connected {
g.requestLeaderboard()
g.leaderboardMutex.Lock()
}
g.leaderboardMutex.Lock()
y := 150
if len(g.leaderboard) == 0 {
text.Draw(screen, "Noch keine Einträge...", basicfont.Face7x13, ScreenWidth/2-80, y, color.Gray{150})