84 lines
1.3 KiB
Go
84 lines
1.3 KiB
Go
package main
|
||
|
||
import (
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
type Room struct {
|
||
Players map[int64]*Player
|
||
Input chan InputMessage
|
||
mu sync.Mutex
|
||
}
|
||
|
||
func NewRoom() *Room {
|
||
return &Room{
|
||
Players: make(map[int64]*Player),
|
||
Input: make(chan InputMessage, 128),
|
||
}
|
||
}
|
||
|
||
func (r *Room) update() {
|
||
// 1️⃣ обрабатываем input
|
||
for {
|
||
select {
|
||
case input := <-r.Input:
|
||
r.mu.Lock()
|
||
p := r.Players[input.PlayerID]
|
||
if p != nil {
|
||
p.DX = input.DX
|
||
p.DY = input.DY
|
||
}
|
||
r.mu.Unlock()
|
||
default:
|
||
goto DONE
|
||
}
|
||
}
|
||
DONE:
|
||
|
||
// 2️⃣ двигаем игроков
|
||
r.mu.Lock()
|
||
for _, p := range r.Players {
|
||
p.X += p.DX * 4
|
||
p.Y += p.DY * 4
|
||
}
|
||
r.mu.Unlock()
|
||
}
|
||
|
||
func (r *Room) broadcast() {
|
||
r.mu.Lock()
|
||
|
||
state := make(map[int64]map[string]any, len(r.Players))
|
||
for id, p := range r.Players {
|
||
state[id] = map[string]any{
|
||
"x": p.X,
|
||
"y": p.Y,
|
||
"name": p.Username,
|
||
}
|
||
}
|
||
|
||
r.mu.Unlock()
|
||
|
||
msg := StateMessage{
|
||
Type: "state",
|
||
Payload: map[string]any{
|
||
"players": state,
|
||
},
|
||
}
|
||
|
||
// отправляем БЕЗ mutex — важно
|
||
for _, p := range r.Players {
|
||
_ = p.Conn.WriteJSON(msg)
|
||
}
|
||
}
|
||
|
||
func (r *Room) Run() {
|
||
ticker := time.NewTicker(time.Second / 30)
|
||
defer ticker.Stop()
|
||
|
||
for range ticker.C {
|
||
r.update()
|
||
r.broadcast()
|
||
}
|
||
}
|