diff --git a/game/chat.go b/game/chat.go index e4a163f..98f5abe 100644 --- a/game/chat.go +++ b/game/chat.go @@ -10,11 +10,12 @@ import ( ) const ( - maxMessages = 50 - chatWindowWidth = 400 - chatHeight = 200 - messageHeight = 20 - inputHeight = 30 + maxMessages = 50 + chatMargin = 10 // Margin from screen edges + chatHeight = 200 + messageHeight = 20 + inputHeight = 30 + runeLimit = 256 ) type Chat struct { @@ -29,7 +30,7 @@ type Chat struct { func NewChat() *Chat { return &Chat{ messages: make([]types.ChatMessage, 0, maxMessages), - inputBuffer: make([]rune, 0, 256), + inputBuffer: make([]rune, 0, runeLimit), } } @@ -63,6 +64,12 @@ func (c *Chat) HandleServerMessages(messages []*pb.ChatMessage) { } c.messages = append(c.messages, localMsg) + // Scroll to latest message if it's not already visible + visibleMessages := int((chatHeight - inputHeight) / messageHeight) + if len(c.messages) > visibleMessages { + c.scrollOffset = len(c.messages) - visibleMessages + } + // Add floating message to the player if game, ok := c.userData.(*Game); ok { if msg.PlayerId == game.Player.ID { @@ -86,17 +93,29 @@ func (c *Chat) HandleServerMessages(messages []*pb.ChatMessage) { } func (c *Chat) Draw(screenWidth, screenHeight int32) { + // Calculate chat window width based on screen width + chatWindowWidth := screenWidth - (chatMargin * 2) + // Draw chat window background - chatX := float32(10) - chatY := float32(screenHeight - chatHeight - 10) + chatX := float32(chatMargin) + chatY := float32(screenHeight - chatHeight - chatMargin) rl.DrawRectangle(int32(chatX), int32(chatY), chatWindowWidth, chatHeight, rl.ColorAlpha(rl.Black, 0.5)) - // Draw messages + // Draw messages from oldest to newest messageY := chatY + 5 - startIdx := len(c.messages) - 1 - c.scrollOffset - endIdx := max(0, startIdx-int((chatHeight-inputHeight)/messageHeight)) + visibleMessages := int((chatHeight - inputHeight) / messageHeight) - for i := startIdx; i >= endIdx && i >= 0; i-- { + // Auto-scroll to bottom if no manual scrolling has occurred + if c.scrollOffset == 0 { + if len(c.messages) > visibleMessages { + c.scrollOffset = len(c.messages) - visibleMessages + } + } + + startIdx := max(0, c.scrollOffset) + endIdx := min(len(c.messages), startIdx+visibleMessages) + + for i := startIdx; i < endIdx; i++ { msg := c.messages[i] text := fmt.Sprintf("[%d]: %s", msg.PlayerID, msg.Content) rl.DrawText(text, int32(chatX)+5, int32(messageY), 20, rl.White) @@ -136,19 +155,20 @@ func (c *Chat) Update() (string, bool) { key := rl.GetCharPressed() for key > 0 { - if len(c.inputBuffer) < 256 { + if len(c.inputBuffer) < runeLimit { c.inputBuffer = append(c.inputBuffer[:c.cursorPos], append([]rune{key}, c.inputBuffer[c.cursorPos:]...)...) c.cursorPos++ } key = rl.GetCharPressed() } - if rl.IsKeyPressed(rl.KeyEnter) { + if rl.IsKeyPressed(rl.KeyEnter) || rl.IsKeyPressed(rl.KeyKpEnter) { if len(c.inputBuffer) > 0 { message := string(c.inputBuffer) c.inputBuffer = c.inputBuffer[:0] c.cursorPos = 0 c.isTyping = false + return message, true } c.isTyping = false @@ -183,6 +203,13 @@ func max(a, b int) int { return b } +func min(a, b int) int { + if a < b { + return a + } + return b +} + func clamp(value, min, max int) int { if value < min { return min