| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package game
- import (
- "sync"
- "time"
- "github.com/wonderivan/logger"
- )
- //房间
- type Room struct {
- Lock sync.Mutex
- ID int
- //玩家列表
- PlayerList []*Player
- //游戏开始时,会给房间中的各个玩家定义一个ID
- PlayerIds map[*Player]int
- //玩家上传的帧数据,发送出去后需要清空
- Frames []interface{}
- //是否有效,设置为false后,会被协程销毁
- IsValid bool
- //是否处于匹配阶段
- Matching bool
- //最多容纳几个玩家
- MaxPlayerCount int
- }
- var roomListLock sync.Mutex
- var roomList []*Room
- //玩家匹配并进入一个房间
- func MatchAndEnterRoom(player *Player) {
- roomListLock.Lock()
- defer roomListLock.Unlock()
- //看能否进入已有的房间
- for _, v := range roomList {
- if v.enter(player, true) {
- return
- }
- }
- //不能就进入新建的房间
- addNewRoom(false).enter(player, true)
- }
- //新增一个房间(创建房间)
- func addNewRoom(lock bool) *Room {
- if lock {
- roomListLock.Lock()
- defer roomListLock.Unlock()
- }
- room := &Room{ID: GetUuidInt("Room"), IsValid: true, Matching: true, MaxPlayerCount: 4}
- roomList = append(roomList, room)
- logger.Info("Room ID", room.ID, "Created")
- go room.autoCheckCompleteMatchingAndStartGame()
- return room
- }
- //移除一个房间(销毁房间)
- func removeRoom(room *Room) {
- roomListLock.Lock()
- defer roomListLock.Unlock()
- for k, v := range roomList {
- if v == room {
- roomList = append(roomList[:k], roomList[k+1:]...)
- logger.Info("Room ID", room.ID, "Removed")
- break
- }
- }
- }
- //让玩家进入
- func (room *Room) enter(player *Player, onlyEnterWhenMatching bool) bool {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- if onlyEnterWhenMatching && !room.Matching {
- return false
- }
- if len(room.PlayerList) < room.MaxPlayerCount {
- room.PlayerList = append(room.PlayerList, player)
- player.Room = room
- logger.Info("Room ID", room.ID, "A Player Enter, Total Member Count", len(room.PlayerList))
- if room.Matching && len(room.PlayerList) == room.MaxPlayerCount {
- room.Matching = false
- }
- return true
- }
- return false
- }
- //让玩家离开
- func (room *Room) Leave(player *Player) {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- for k, v := range room.PlayerList {
- if v == player {
- room.PlayerList = append(room.PlayerList[:k], room.PlayerList[k+1:]...)
- player.Room = nil
- if room.PlayerIds != nil {
- playerId := room.PlayerIds[player]
- delete(room.PlayerIds, player)
- room.Frames = append(room.Frames, NewSyncFrame_PlayerLeave(playerId))
- }
- logger.Info("Room ID", room.ID, "A Player Leave, Total Member Count", len(room.PlayerList))
- break
- }
- }
- if len(room.PlayerList) == 0 {
- room.IsValid = false
- removeRoom(room)
- }
- }
- //自动结束匹配(需要协程开启)
- func (room *Room) autoCheckCompleteMatchingAndStartGame() {
- //循环等待匹配结束
- checkStartTime := time.Now().UnixMilli()
- checkInterval := time.Duration(100) * time.Millisecond
- for room.Matching {
- time.Sleep(checkInterval)
- //房间最多匹配几秒
- if time.Now().UnixMilli()-checkStartTime >= 6000 {
- room.Lock.Lock()
- room.Matching = false
- room.Lock.Unlock()
- }
- }
- //结束匹配
- room.completeMatching()
- //延迟2秒
- time.Sleep(time.Duration(2) * time.Second)
- //通知玩家开始游戏
- room.startGame()
- //开启自动帧同步
- go room.autoFrameSync()
- }
- //完成匹配
- func (room *Room) completeMatching() {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- //记录玩家数据
- playerInfos := make(map[int]interface{})
- room.PlayerIds = make(map[*Player]int)
- for k, v := range room.PlayerList {
- room.PlayerIds[v] = k
- playerInfos[k] = v.userInfo
- }
- uuid := NewUUID()
- timestamp := time.Now().UnixMilli()
- for k, v := range room.PlayerList {
- v.Notify_onMatchComplete(k, playerInfos, uuid, timestamp)
- }
- logger.Info("Room ID", room.ID, "Matching Completed")
- }
- //开始游戏
- func (room *Room) startGame() {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- for _, v := range room.PlayerList {
- v.Notify_onGameStart()
- }
- logger.Info("Room ID", room.ID, "Game Start")
- }
- //自动帧同步(需要协程开启)
- func (room *Room) autoFrameSync() {
- loopInterval := time.Duration(33) * time.Millisecond
- logger.Info("Room ID", room.ID, "Frame Sync Start")
- lastHandleTime := time.Now().UnixMilli()
- currentHandleTime := lastHandleTime
- for room.IsValid {
- time.Sleep(loopInterval)
- currentHandleTime = time.Now().UnixMilli()
- room.Frames = append(room.Frames, NewSyncFrame_DeltaTime(currentHandleTime-lastHandleTime))
- lastHandleTime = currentHandleTime
- room.sendFrames()
- }
- logger.Info("Room ID", room.ID, "Frame Sync Stop")
- }
- //向房间内所有玩家发送同步帧
- func (room *Room) sendFrames() {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- if len(room.Frames) > 0 {
- for _, v := range room.PlayerList {
- v.Notify_onFrameSync(room.Frames)
- }
- room.Frames = nil
- }
- }
- //缓存玩家上传的帧数据
- func (room *Room) CacheFrames(frames []interface{}) {
- room.Lock.Lock()
- defer room.Lock.Unlock()
- room.Frames = append(room.Frames, frames...)
- }
|