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()
|
|
}
|
|
}
|