fix game
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 6m53s
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 6m53s
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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})
|
||||
|
||||
Reference in New Issue
Block a user