154 lines
3.4 KiB
Go
154 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"gitea.boner.be/bdnugget/goonscape/game"
|
|
"gitea.boner.be/bdnugget/goonscape/network"
|
|
rl "github.com/gen2brain/raylib-go/raylib"
|
|
)
|
|
|
|
func main() {
|
|
// Set up panic recovery at the top level
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Printf("Recovered from fatal panic in main: %v", r)
|
|
// Give the user a chance to see the error
|
|
time.Sleep(5 * time.Second)
|
|
}
|
|
}()
|
|
|
|
// Parse command line flags
|
|
verbose := flag.Bool("v", false, "Also show info logs (spammy)")
|
|
local := flag.Bool("local", false, "Connect to local server")
|
|
addr := flag.String("addr", "", "Server address (host or host:port)")
|
|
flag.Parse()
|
|
|
|
if *verbose {
|
|
rl.SetTraceLogLevel(rl.LogTrace)
|
|
} else {
|
|
rl.SetTraceLogLevel(rl.LogWarning)
|
|
}
|
|
|
|
// Set server address based on flags
|
|
if *local {
|
|
if *addr != "" {
|
|
log.Fatal("Cannot use -local and -addr together")
|
|
}
|
|
network.SetServerAddr("localhost:6969")
|
|
} else if *addr != "" {
|
|
// If port is not specified, append default port
|
|
if !strings.Contains(*addr, ":") {
|
|
*addr += ":6969"
|
|
}
|
|
network.SetServerAddr(*addr)
|
|
}
|
|
|
|
// Initialize window with error handling
|
|
rl.SetConfigFlags(rl.FlagMsaa4xHint) // Enable MSAA for smoother rendering
|
|
rl.InitWindow(1024, 768, "GoonScape")
|
|
|
|
rl.SetExitKey(0)
|
|
|
|
// Initialize audio with error handling
|
|
if !rl.IsAudioDeviceReady() {
|
|
rl.InitAudioDevice()
|
|
if !rl.IsAudioDeviceReady() {
|
|
log.Println("Warning: Failed to initialize audio device, continuing without audio")
|
|
}
|
|
}
|
|
|
|
// Use a maximum of 3 attempts to load assets
|
|
var gameInstance *game.Game
|
|
var loadErr error
|
|
maxAttempts := 3
|
|
|
|
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
|
gameInstance = game.New()
|
|
loadErr = gameInstance.LoadAssets()
|
|
if loadErr == nil {
|
|
break
|
|
}
|
|
|
|
log.Printf("Attempt %d/%d: Failed to load assets: %v", attempt, maxAttempts, loadErr)
|
|
if attempt < maxAttempts {
|
|
log.Println("Retrying...")
|
|
gameInstance.Cleanup() // Cleanup before retrying
|
|
time.Sleep(500 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
if loadErr != nil {
|
|
log.Printf("Failed to load assets after %d attempts. Starting with default assets.", maxAttempts)
|
|
}
|
|
|
|
defer func() {
|
|
if gameInstance != nil {
|
|
gameInstance.Cleanup()
|
|
}
|
|
rl.CloseWindow()
|
|
if rl.IsAudioDeviceReady() {
|
|
rl.CloseAudioDevice()
|
|
}
|
|
}()
|
|
|
|
rl.SetTargetFPS(60)
|
|
|
|
// Play music if available
|
|
if gameInstance.Music.Stream.Buffer != nil {
|
|
rl.PlayMusicStream(gameInstance.Music)
|
|
rl.SetMusicVolume(gameInstance.Music, 0.5)
|
|
}
|
|
|
|
// Handle OS signals for clean shutdown
|
|
sigChan := make(chan os.Signal, 1)
|
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
|
go func() {
|
|
<-sigChan
|
|
if gameInstance != nil {
|
|
gameInstance.Shutdown()
|
|
}
|
|
}()
|
|
|
|
// Keep game loop in main thread for Raylib
|
|
for !rl.WindowShouldClose() {
|
|
deltaTime := rl.GetFrameTime()
|
|
|
|
// Update music if available
|
|
if gameInstance.Music.Stream.Buffer != nil {
|
|
rl.UpdateMusicStream(gameInstance.Music)
|
|
}
|
|
|
|
func() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Printf("Recovered from panic in game update: %v", r)
|
|
}
|
|
}()
|
|
gameInstance.Update(deltaTime)
|
|
}()
|
|
|
|
func() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Printf("Recovered from panic in game render: %v", r)
|
|
}
|
|
}()
|
|
gameInstance.Render()
|
|
}()
|
|
|
|
// Check if game requested shutdown
|
|
select {
|
|
case <-gameInstance.QuitChan():
|
|
return
|
|
default:
|
|
}
|
|
}
|
|
}
|