Compare commits
No commits in common. "master" and "refactor/less-complexity" have entirely different histories.
master
...
refactor/l
283
game/game.go
283
game/game.go
@ -23,6 +23,16 @@ type Game struct {
|
|||||||
quitChan chan struct{}
|
quitChan chan struct{}
|
||||||
cleanupOnce sync.Once
|
cleanupOnce sync.Once
|
||||||
frameCounter int // For periodic logging
|
frameCounter int // For periodic logging
|
||||||
|
|
||||||
|
// Legacy fields for backward compatibility
|
||||||
|
Player *types.Player // Use PlayerManager.LocalPlayer instead
|
||||||
|
OtherPlayers map[int32]*types.Player // Use PlayerManager.OtherPlayers instead
|
||||||
|
Models []types.ModelAsset // Use AssetManager.Models instead
|
||||||
|
Music rl.Music // Use AssetManager.Music instead
|
||||||
|
Chat *Chat // Use UIManager.Chat instead
|
||||||
|
MenuOpen bool // Use UIManager.MenuOpen instead
|
||||||
|
loginScreen *LoginScreen // Use UIManager.LoginScreen instead
|
||||||
|
isLoggedIn bool // Use UIManager.IsLoggedIn instead
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Game {
|
func New() *Game {
|
||||||
@ -43,10 +53,22 @@ func New() *Game {
|
|||||||
Projection: rl.CameraPerspective,
|
Projection: rl.CameraPerspective,
|
||||||
},
|
},
|
||||||
quitChan: make(chan struct{}),
|
quitChan: make(chan struct{}),
|
||||||
|
// Initialize empty maps to avoid nil references
|
||||||
|
OtherPlayers: make(map[int32]*types.Player),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize legacy fields (for backward compatibility)
|
||||||
|
g.Player = g.PlayerManager.LocalPlayer
|
||||||
|
g.OtherPlayers = g.PlayerManager.OtherPlayers
|
||||||
|
g.Models = g.AssetManager.Models
|
||||||
|
g.Music = g.AssetManager.Music
|
||||||
|
g.Chat = g.UIManager.Chat
|
||||||
|
g.MenuOpen = g.UIManager.MenuOpen
|
||||||
|
g.loginScreen = g.UIManager.LoginScreen
|
||||||
|
g.isLoggedIn = g.UIManager.IsLoggedIn
|
||||||
|
|
||||||
// Set up inter-component references
|
// Set up inter-component references
|
||||||
g.UIManager.Chat.userData = g // Pass game instance to chat for callbacks
|
g.Chat.userData = g // Pass game instance to chat for callbacks
|
||||||
|
|
||||||
// Initialize world
|
// Initialize world
|
||||||
InitWorld()
|
InitWorld()
|
||||||
@ -64,12 +86,17 @@ func (g *Game) LoadAssets() error {
|
|||||||
}
|
}
|
||||||
g.AssetManager.Models = models
|
g.AssetManager.Models = models
|
||||||
|
|
||||||
|
// Update legacy field
|
||||||
|
g.Models = models
|
||||||
|
|
||||||
// Try to load music
|
// Try to load music
|
||||||
music, err := assets.LoadMusic("resources/audio/GoonScape1.mp3")
|
music, err := assets.LoadMusic("resources/audio/music.mp3")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Warning: Failed to load music: %v", err)
|
log.Printf("Warning: Failed to load music: %v", err)
|
||||||
} else {
|
} else {
|
||||||
g.AssetManager.Music = music
|
g.AssetManager.Music = music
|
||||||
|
// Update legacy field
|
||||||
|
g.Music = music
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -77,10 +104,12 @@ func (g *Game) LoadAssets() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Update(deltaTime float32) {
|
func (g *Game) Update(deltaTime float32) {
|
||||||
// Handle login screen if not logged in
|
// Legacy code to maintain compatibility
|
||||||
if !g.UIManager.IsLoggedIn {
|
if !g.UIManager.IsLoggedIn {
|
||||||
// Handle login
|
// Handle login
|
||||||
username, password, isRegistering, doAuth := g.UIManager.LoginScreen.Update()
|
username, password, isRegistering, doAuth := g.UIManager.LoginScreen.Update()
|
||||||
|
// Update legacy fields
|
||||||
|
g.isLoggedIn = g.UIManager.IsLoggedIn
|
||||||
|
|
||||||
if doAuth {
|
if doAuth {
|
||||||
conn, playerID, err := network.ConnectToServer(username, password, isRegistering)
|
conn, playerID, err := network.ConnectToServer(username, password, isRegistering)
|
||||||
@ -98,6 +127,9 @@ func (g *Game) Update(deltaTime float32) {
|
|||||||
}
|
}
|
||||||
g.AssignModelToPlayer(g.PlayerManager.LocalPlayer)
|
g.AssignModelToPlayer(g.PlayerManager.LocalPlayer)
|
||||||
|
|
||||||
|
// Update the legacy Player field
|
||||||
|
g.Player = g.PlayerManager.LocalPlayer
|
||||||
|
|
||||||
// Set user data to allow chat message handling
|
// Set user data to allow chat message handling
|
||||||
g.PlayerManager.LocalPlayer.UserData = g
|
g.PlayerManager.LocalPlayer.UserData = g
|
||||||
|
|
||||||
@ -149,13 +181,8 @@ func (g *Game) Update(deltaTime float32) {
|
|||||||
rl.TraceLog(rl.LogInfo, "There are %d other players", len(g.PlayerManager.OtherPlayers))
|
rl.TraceLog(rl.LogInfo, "There are %d other players", len(g.PlayerManager.OtherPlayers))
|
||||||
for id, other := range g.PlayerManager.OtherPlayers {
|
for id, other := range g.PlayerManager.OtherPlayers {
|
||||||
if other != nil {
|
if other != nil {
|
||||||
// Calculate tile coordinates from absolute position
|
rl.TraceLog(rl.LogInfo, "Other player ID: %d, Position: (%f, %f, %f), Has model: %v",
|
||||||
tileX := int(other.PosActual.X / float32(types.TileSize))
|
id, other.PosActual.X, other.PosActual.Y, other.PosActual.Z, other.Model.Meshes != nil)
|
||||||
tileY := int(other.PosActual.Z / float32(types.TileSize))
|
|
||||||
|
|
||||||
rl.TraceLog(rl.LogInfo, "Other player ID: %d, Position: (%f, %f, %f), Tile: (%d, %d), Has model: %v",
|
|
||||||
id, other.PosActual.X, other.PosActual.Y, other.PosActual.Z,
|
|
||||||
tileX, tileY, other.Model.Meshes != nil)
|
|
||||||
} else {
|
} else {
|
||||||
rl.TraceLog(rl.LogInfo, "Other player ID: %d is nil", id)
|
rl.TraceLog(rl.LogInfo, "Other player ID: %d is nil", id)
|
||||||
}
|
}
|
||||||
@ -186,6 +213,13 @@ func (g *Game) Update(deltaTime float32) {
|
|||||||
if g.AssetManager.Music.Stream.Buffer != nil {
|
if g.AssetManager.Music.Stream.Buffer != nil {
|
||||||
rl.UpdateMusicStream(g.AssetManager.Music)
|
rl.UpdateMusicStream(g.AssetManager.Music)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update legacy fields
|
||||||
|
g.Player = g.PlayerManager.LocalPlayer
|
||||||
|
g.OtherPlayers = g.PlayerManager.OtherPlayers
|
||||||
|
g.Models = g.AssetManager.Models
|
||||||
|
g.Music = g.AssetManager.Music
|
||||||
|
g.MenuOpen = g.UIManager.MenuOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) DrawMap() {
|
func (g *Game) DrawMap() {
|
||||||
@ -217,84 +251,94 @@ func (g *Game) DrawMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
|
func (g *Game) DrawPlayer(player *types.Player, model rl.Model) {
|
||||||
if player == nil {
|
// No need for lock in rendering, we'll use a "take snapshot" approach
|
||||||
|
// This avoids potential deadlocks and makes the rendering more consistent
|
||||||
|
|
||||||
|
// Check for invalid model
|
||||||
|
if model.Meshes == nil || model.Meshes.VertexCount <= 0 {
|
||||||
|
// Don't try to draw invalid models
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get necessary data
|
grid := GetMapGrid()
|
||||||
modelIndex := int(player.ID) % len(g.AssetManager.Models)
|
modelIndex := int(player.ID) % len(g.Models)
|
||||||
if modelIndex < 0 || modelIndex >= len(g.AssetManager.Models) {
|
if modelIndex < 0 || modelIndex >= len(g.Models) {
|
||||||
|
// Prevent out of bounds access
|
||||||
modelIndex = 0
|
modelIndex = 0
|
||||||
}
|
}
|
||||||
modelAsset := g.AssetManager.Models[modelIndex]
|
modelAsset := g.Models[modelIndex]
|
||||||
|
|
||||||
// Calculate position
|
const defaultHeight = 8.0 // Default height above tile, fine tune per model in types.ModelAsset
|
||||||
const defaultHeight = 8.0
|
|
||||||
playerPos := rl.Vector3{
|
playerPos := rl.Vector3{
|
||||||
X: player.PosActual.X,
|
X: player.PosActual.X,
|
||||||
Y: player.PosActual.Y + defaultHeight + modelAsset.YOffset,
|
Y: grid[player.PosTile.X][player.PosTile.Y].Height*types.TileHeight + defaultHeight + modelAsset.YOffset,
|
||||||
Z: player.PosActual.Z,
|
Z: player.PosActual.Z,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple drawing with scale parameter
|
// Check if model has animations
|
||||||
|
if modelAsset.Animations.Idle != nil || modelAsset.Animations.Walk != nil {
|
||||||
|
if player.IsMoving && len(modelAsset.Animations.Walk) > 0 {
|
||||||
|
anim := modelAsset.Animations.Walk[0] // Use first walk animation
|
||||||
|
if anim.FrameCount > 0 {
|
||||||
|
currentFrame := player.AnimationFrame % anim.FrameCount
|
||||||
|
rl.UpdateModelAnimation(model, anim, currentFrame)
|
||||||
|
}
|
||||||
|
} else if len(modelAsset.Animations.Idle) > 0 {
|
||||||
|
anim := modelAsset.Animations.Idle[0] // Use first idle animation
|
||||||
|
if anim.FrameCount > 0 {
|
||||||
|
currentFrame := player.AnimationFrame % anim.FrameCount
|
||||||
|
rl.UpdateModelAnimation(model, anim, currentFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use placeholder color if it's set, otherwise use white
|
||||||
var drawColor rl.Color = rl.White
|
var drawColor rl.Color = rl.White
|
||||||
if player.PlaceholderColor.A > 0 {
|
if player.PlaceholderColor.A > 0 {
|
||||||
drawColor = player.PlaceholderColor
|
drawColor = player.PlaceholderColor
|
||||||
}
|
}
|
||||||
|
rl.DrawModel(model, playerPos, 16, drawColor)
|
||||||
|
|
||||||
// Draw the model at normal scale (16.0)
|
// Draw floating messages and path indicators
|
||||||
rl.DrawModel(model, playerPos, 16.0, drawColor)
|
|
||||||
|
|
||||||
// Update floating message position
|
|
||||||
if player.FloatingMessage != nil {
|
if player.FloatingMessage != nil {
|
||||||
worldPos := rl.Vector3{
|
screenPos := rl.GetWorldToScreen(rl.Vector3{
|
||||||
X: playerPos.X,
|
X: playerPos.X,
|
||||||
Y: playerPos.Y + 24.0, // Position above head
|
Y: playerPos.Y + 24.0,
|
||||||
Z: playerPos.Z,
|
Z: playerPos.Z,
|
||||||
}
|
}, g.Camera)
|
||||||
player.FloatingMessage.ScreenPos = rl.GetWorldToScreen(worldPos, g.Camera)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Game) DrawFloatingMessages() {
|
player.FloatingMessage.ScreenPos = screenPos
|
||||||
var drawFloatingMessage = func(msg *types.FloatingMessage) {
|
|
||||||
if msg == nil || time.Now().After(msg.ExpireTime) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the message with RuneScape-style coloring (black outline with yellow text)
|
if len(player.TargetPath) > 0 {
|
||||||
text := msg.Content
|
targetTile := player.TargetPath[len(player.TargetPath)-1]
|
||||||
textWidth := rl.MeasureText(text, 20)
|
targetPos := rl.Vector3{
|
||||||
|
X: float32(targetTile.X * types.TileSize),
|
||||||
|
Y: grid[targetTile.X][targetTile.Y].Height * types.TileHeight,
|
||||||
|
Z: float32(targetTile.Y * types.TileSize),
|
||||||
|
}
|
||||||
|
rl.DrawCubeWires(targetPos, types.TileSize, types.TileHeight, types.TileSize, rl.Green)
|
||||||
|
|
||||||
// Draw black outline by offsetting the text slightly in all directions
|
nextTile := player.TargetPath[0]
|
||||||
for offsetX := -2; offsetX <= 2; offsetX++ {
|
nextPos := rl.Vector3{
|
||||||
for offsetY := -2; offsetY <= 2; offsetY++ {
|
X: float32(nextTile.X * types.TileSize),
|
||||||
rl.DrawText(text,
|
Y: grid[nextTile.X][nextTile.Y].Height * types.TileHeight,
|
||||||
int32(msg.ScreenPos.X)-textWidth/2+int32(offsetX),
|
Z: float32(nextTile.Y * types.TileSize),
|
||||||
int32(msg.ScreenPos.Y)+int32(offsetY),
|
|
||||||
20,
|
|
||||||
rl.Black)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the yellow text on top
|
|
||||||
rl.DrawText(text, int32(msg.ScreenPos.X)-textWidth/2, int32(msg.ScreenPos.Y), 20, rl.Yellow)
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.PlayerManager.LocalPlayer != nil && g.PlayerManager.LocalPlayer.FloatingMessage != nil {
|
|
||||||
drawFloatingMessage(g.PlayerManager.LocalPlayer.FloatingMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, other := range g.PlayerManager.OtherPlayers {
|
|
||||||
if other != nil && other.FloatingMessage != nil {
|
|
||||||
drawFloatingMessage(other.FloatingMessage)
|
|
||||||
}
|
}
|
||||||
|
rl.DrawCubeWires(nextPos, types.TileSize, types.TileHeight, types.TileSize, rl.Yellow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Render() {
|
func (g *Game) Render() {
|
||||||
rl.BeginDrawing()
|
rl.BeginDrawing()
|
||||||
defer rl.EndDrawing()
|
defer func() {
|
||||||
|
// This defer will catch any panics that might occur during rendering
|
||||||
|
// and ensure EndDrawing gets called to maintain proper graphics state
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
rl.TraceLog(rl.LogError, "Panic during rendering: %v", r)
|
||||||
|
}
|
||||||
|
rl.EndDrawing()
|
||||||
|
}()
|
||||||
|
|
||||||
rl.ClearBackground(rl.RayWhite)
|
rl.ClearBackground(rl.RayWhite)
|
||||||
|
|
||||||
@ -303,7 +347,6 @@ func (g *Game) Render() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw 3D elements
|
|
||||||
rl.BeginMode3D(g.Camera)
|
rl.BeginMode3D(g.Camera)
|
||||||
g.DrawMap()
|
g.DrawMap()
|
||||||
|
|
||||||
@ -318,14 +361,48 @@ func (g *Game) Render() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if other.Model.Meshes != nil {
|
// Make sure model is assigned
|
||||||
g.DrawPlayer(other, other.Model)
|
if other.Model.Meshes == nil {
|
||||||
|
g.AssignModelToPlayer(other)
|
||||||
|
// Skip this frame if assignment failed
|
||||||
|
if other.Model.Meshes == nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g.DrawPlayer(other, other.Model)
|
||||||
|
}
|
||||||
rl.EndMode3D()
|
rl.EndMode3D()
|
||||||
|
|
||||||
// Draw floating messages with RuneScape style
|
// Draw floating messages
|
||||||
g.DrawFloatingMessages()
|
drawFloatingMessage := func(msg *types.FloatingMessage) {
|
||||||
|
if msg == nil || time.Now().After(msg.ExpireTime) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pos := msg.ScreenPos
|
||||||
|
text := msg.Content
|
||||||
|
textWidth := rl.MeasureText(text, 20)
|
||||||
|
|
||||||
|
for offsetX := -2; offsetX <= 2; offsetX++ {
|
||||||
|
for offsetY := -2; offsetY <= 2; offsetY++ {
|
||||||
|
rl.DrawText(text,
|
||||||
|
int32(pos.X)-textWidth/2+int32(offsetX),
|
||||||
|
int32(pos.Y)+int32(offsetY),
|
||||||
|
20,
|
||||||
|
rl.Black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rl.DrawText(text, int32(pos.X)-textWidth/2, int32(pos.Y), 20, rl.Yellow)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.PlayerManager.LocalPlayer != nil && g.PlayerManager.LocalPlayer.FloatingMessage != nil {
|
||||||
|
drawFloatingMessage(g.PlayerManager.LocalPlayer.FloatingMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, other := range g.PlayerManager.OtherPlayers {
|
||||||
|
if other != nil && other.FloatingMessage != nil {
|
||||||
|
drawFloatingMessage(other.FloatingMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw menu if open
|
// Draw menu if open
|
||||||
if g.UIManager.MenuOpen {
|
if g.UIManager.MenuOpen {
|
||||||
@ -337,7 +414,6 @@ func (g *Game) Render() {
|
|||||||
g.UIManager.Chat.Draw(int32(rl.GetScreenWidth()), int32(rl.GetScreenHeight()))
|
g.UIManager.Chat.Draw(int32(rl.GetScreenWidth()), int32(rl.GetScreenHeight()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw FPS counter
|
|
||||||
rl.DrawFPS(10, 10)
|
rl.DrawFPS(10, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,45 +464,63 @@ func (g *Game) DrawMenu() {
|
|||||||
screenWidth := float32(rl.GetScreenWidth())
|
screenWidth := float32(rl.GetScreenWidth())
|
||||||
screenHeight := float32(rl.GetScreenHeight())
|
screenHeight := float32(rl.GetScreenHeight())
|
||||||
|
|
||||||
// Draw semi-transparent background
|
// Semi-transparent background
|
||||||
rl.DrawRectangle(0, 0, int32(screenWidth), int32(screenHeight), rl.ColorAlpha(rl.Black, 0.7))
|
rl.DrawRectangle(0, 0, int32(screenWidth), int32(screenHeight), rl.ColorAlpha(rl.Black, 0.7))
|
||||||
|
|
||||||
// Draw menu items
|
// Menu title
|
||||||
menuItems := []string{"Resume", "Settings", "Quit"}
|
title := "Menu"
|
||||||
menuY := screenHeight/2 - float32(len(menuItems)*40)/2
|
titleSize := int32(40)
|
||||||
|
titleWidth := rl.MeasureText(title, titleSize)
|
||||||
|
rl.DrawText(title, int32(screenWidth/2)-titleWidth/2, 100, titleSize, rl.White)
|
||||||
|
|
||||||
for i, item := range menuItems {
|
// Menu buttons
|
||||||
itemY := menuY + float32(i*40)
|
buttonWidth := float32(200)
|
||||||
mousePoint := rl.GetMousePosition()
|
buttonHeight := float32(40)
|
||||||
itemRect := rl.Rectangle{X: screenWidth/2 - 100, Y: itemY, Width: 200, Height: 36}
|
buttonY := float32(200)
|
||||||
|
buttonSpacing := float32(60)
|
||||||
|
|
||||||
// Check for hover
|
menuItems := []string{"Resume", "Settings", "Exit Game"}
|
||||||
isHover := rl.CheckCollisionPointRec(mousePoint, itemRect)
|
for _, item := range menuItems {
|
||||||
|
buttonRect := rl.Rectangle{
|
||||||
// Draw button background
|
X: screenWidth/2 - buttonWidth/2,
|
||||||
if isHover {
|
Y: buttonY,
|
||||||
rl.DrawRectangleRec(itemRect, rl.ColorAlpha(rl.White, 0.3))
|
Width: buttonWidth,
|
||||||
} else {
|
Height: buttonHeight,
|
||||||
rl.DrawRectangleRec(itemRect, rl.ColorAlpha(rl.White, 0.1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw button text
|
// Check mouse hover
|
||||||
textWidth := rl.MeasureText(item, 20)
|
mousePoint := rl.GetMousePosition()
|
||||||
rl.DrawText(item, int32(itemRect.X+(itemRect.Width-float32(textWidth))/2), int32(itemRect.Y+8), 20, rl.White)
|
mouseHover := rl.CheckCollisionPointRec(mousePoint, buttonRect)
|
||||||
|
|
||||||
// Handle click
|
// Draw button
|
||||||
if isHover && rl.IsMouseButtonReleased(rl.MouseLeftButton) {
|
if mouseHover {
|
||||||
|
rl.DrawRectangleRec(buttonRect, rl.ColorAlpha(rl.White, 0.3))
|
||||||
|
if rl.IsMouseButtonPressed(rl.MouseLeftButton) {
|
||||||
switch item {
|
switch item {
|
||||||
case "Resume":
|
case "Resume":
|
||||||
g.UIManager.MenuOpen = false
|
g.UIManager.MenuOpen = false
|
||||||
case "Settings":
|
case "Settings":
|
||||||
// TODO: Implement settings
|
// TODO: Implement settings
|
||||||
case "Quit":
|
case "Exit Game":
|
||||||
g.Shutdown()
|
g.Shutdown()
|
||||||
rl.CloseWindow()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw button text
|
||||||
|
textSize := int32(20)
|
||||||
|
textWidth := rl.MeasureText(item, textSize)
|
||||||
|
textX := int32(buttonRect.X+buttonRect.Width/2) - textWidth/2
|
||||||
|
textY := int32(buttonRect.Y + buttonRect.Height/2 - float32(textSize)/2)
|
||||||
|
rl.DrawText(item, textX, textY, textSize, rl.White)
|
||||||
|
|
||||||
|
buttonY += buttonSpacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Shutdown() {
|
||||||
|
// Use the cleanup method which has channel-closing safety
|
||||||
|
g.Cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) HandleServerMessages(messages []*pb.ChatMessage) {
|
func (g *Game) HandleServerMessages(messages []*pb.ChatMessage) {
|
||||||
@ -438,15 +532,6 @@ func (g *Game) HandleServerMessages(messages []*pb.ChatMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) QuitChan() <-chan struct{} {
|
|
||||||
return g.quitChan
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Game) Shutdown() {
|
|
||||||
// Use the cleanup method which has channel-closing safety
|
|
||||||
g.Cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Game) AssignModelToPlayer(player *types.Player) {
|
func (g *Game) AssignModelToPlayer(player *types.Player) {
|
||||||
if player == nil {
|
if player == nil {
|
||||||
return
|
return
|
||||||
@ -465,3 +550,7 @@ func (g *Game) AssignModelToPlayer(player *types.Player) {
|
|||||||
player.InitializeAnimations(modelAsset.Animations)
|
player.InitializeAnimations(modelAsset.Animations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Game) QuitChan() <-chan struct{} {
|
||||||
|
return g.quitChan
|
||||||
|
}
|
||||||
|
10
main.go
10
main.go
@ -101,9 +101,9 @@ func main() {
|
|||||||
rl.SetTargetFPS(60)
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
// Play music if available
|
// Play music if available
|
||||||
if gameInstance.AssetManager.Music.Stream.Buffer != nil {
|
if gameInstance.Music.Stream.Buffer != nil {
|
||||||
rl.PlayMusicStream(gameInstance.AssetManager.Music)
|
rl.PlayMusicStream(gameInstance.Music)
|
||||||
rl.SetMusicVolume(gameInstance.AssetManager.Music, 0.5)
|
rl.SetMusicVolume(gameInstance.Music, 0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle OS signals for clean shutdown
|
// Handle OS signals for clean shutdown
|
||||||
@ -121,8 +121,8 @@ func main() {
|
|||||||
deltaTime := rl.GetFrameTime()
|
deltaTime := rl.GetFrameTime()
|
||||||
|
|
||||||
// Update music if available
|
// Update music if available
|
||||||
if gameInstance.AssetManager.Music.Stream.Buffer != nil {
|
if gameInstance.Music.Stream.Buffer != nil {
|
||||||
rl.UpdateMusicStream(gameInstance.AssetManager.Music)
|
rl.UpdateMusicStream(gameInstance.Music)
|
||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user