room.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package game
  2. import (
  3. "sync"
  4. "time"
  5. "github.com/wonderivan/logger"
  6. )
  7. //房间
  8. type Room struct {
  9. Lock sync.Mutex
  10. ID int
  11. //玩家列表
  12. PlayerList []*Player
  13. //游戏开始时,会给房间中的各个玩家定义一个ID
  14. PlayerIds map[*Player]int
  15. //玩家上传的帧数据,发送出去后需要清空
  16. Frames []interface{}
  17. //是否有效,设置为false后,会被协程销毁
  18. IsValid bool
  19. //是否处于匹配阶段
  20. Matching bool
  21. //最多容纳几个玩家
  22. MaxPlayerCount int
  23. }
  24. var roomListLock sync.Mutex
  25. var roomList []*Room
  26. //玩家匹配并进入一个房间
  27. func MatchAndEnterRoom(player *Player) {
  28. roomListLock.Lock()
  29. defer roomListLock.Unlock()
  30. //看能否进入已有的房间
  31. for _, v := range roomList {
  32. if v.enter(player, true) {
  33. return
  34. }
  35. }
  36. //不能就进入新建的房间
  37. addNewRoom(false).enter(player, true)
  38. }
  39. //新增一个房间(创建房间)
  40. func addNewRoom(lock bool) *Room {
  41. if lock {
  42. roomListLock.Lock()
  43. defer roomListLock.Unlock()
  44. }
  45. room := &Room{ID: GetUuidInt("Room"), IsValid: true, Matching: true, MaxPlayerCount: 4}
  46. roomList = append(roomList, room)
  47. logger.Info("Room ID", room.ID, "Created")
  48. go room.autoCheckCompleteMatchingAndStartGame()
  49. return room
  50. }
  51. //移除一个房间(销毁房间)
  52. func removeRoom(room *Room) {
  53. roomListLock.Lock()
  54. defer roomListLock.Unlock()
  55. for k, v := range roomList {
  56. if v == room {
  57. roomList = append(roomList[:k], roomList[k+1:]...)
  58. logger.Info("Room ID", room.ID, "Removed")
  59. break
  60. }
  61. }
  62. }
  63. //让玩家进入
  64. func (room *Room) enter(player *Player, onlyEnterWhenMatching bool) bool {
  65. room.Lock.Lock()
  66. defer room.Lock.Unlock()
  67. if onlyEnterWhenMatching && !room.Matching {
  68. return false
  69. }
  70. if len(room.PlayerList) < room.MaxPlayerCount {
  71. room.PlayerList = append(room.PlayerList, player)
  72. player.Room = room
  73. logger.Info("Room ID", room.ID, "A Player Enter, Total Member Count", len(room.PlayerList))
  74. if room.Matching && len(room.PlayerList) == room.MaxPlayerCount {
  75. room.Matching = false
  76. }
  77. return true
  78. }
  79. return false
  80. }
  81. //让玩家离开
  82. func (room *Room) Leave(player *Player) {
  83. room.Lock.Lock()
  84. defer room.Lock.Unlock()
  85. for k, v := range room.PlayerList {
  86. if v == player {
  87. room.PlayerList = append(room.PlayerList[:k], room.PlayerList[k+1:]...)
  88. player.Room = nil
  89. if room.PlayerIds != nil {
  90. playerId := room.PlayerIds[player]
  91. delete(room.PlayerIds, player)
  92. room.Frames = append(room.Frames, NewSyncFrame_PlayerLeave(playerId))
  93. }
  94. logger.Info("Room ID", room.ID, "A Player Leave, Total Member Count", len(room.PlayerList))
  95. break
  96. }
  97. }
  98. if len(room.PlayerList) == 0 {
  99. room.IsValid = false
  100. removeRoom(room)
  101. }
  102. }
  103. //自动结束匹配(需要协程开启)
  104. func (room *Room) autoCheckCompleteMatchingAndStartGame() {
  105. //循环等待匹配结束
  106. checkStartTime := time.Now().UnixMilli()
  107. checkInterval := time.Duration(100) * time.Millisecond
  108. for room.Matching {
  109. time.Sleep(checkInterval)
  110. //房间最多匹配几秒
  111. if time.Now().UnixMilli()-checkStartTime >= 6000 {
  112. room.Lock.Lock()
  113. room.Matching = false
  114. room.Lock.Unlock()
  115. }
  116. }
  117. //结束匹配
  118. room.completeMatching()
  119. //延迟2秒
  120. time.Sleep(time.Duration(2) * time.Second)
  121. //通知玩家开始游戏
  122. room.startGame()
  123. //开启自动帧同步
  124. go room.autoFrameSync()
  125. }
  126. //完成匹配
  127. func (room *Room) completeMatching() {
  128. room.Lock.Lock()
  129. defer room.Lock.Unlock()
  130. //记录玩家数据
  131. playerInfos := make(map[int]interface{})
  132. room.PlayerIds = make(map[*Player]int)
  133. for k, v := range room.PlayerList {
  134. room.PlayerIds[v] = k
  135. playerInfos[k] = v.userInfo
  136. }
  137. uuid := NewUUID()
  138. timestamp := time.Now().UnixMilli()
  139. for k, v := range room.PlayerList {
  140. v.Notify_onMatchComplete(k, playerInfos, uuid, timestamp)
  141. }
  142. logger.Info("Room ID", room.ID, "Matching Completed")
  143. }
  144. //开始游戏
  145. func (room *Room) startGame() {
  146. room.Lock.Lock()
  147. defer room.Lock.Unlock()
  148. for _, v := range room.PlayerList {
  149. v.Notify_onGameStart()
  150. }
  151. logger.Info("Room ID", room.ID, "Game Start")
  152. }
  153. //自动帧同步(需要协程开启)
  154. func (room *Room) autoFrameSync() {
  155. loopInterval := time.Duration(33) * time.Millisecond
  156. logger.Info("Room ID", room.ID, "Frame Sync Start")
  157. lastHandleTime := time.Now().UnixMilli()
  158. currentHandleTime := lastHandleTime
  159. for room.IsValid {
  160. time.Sleep(loopInterval)
  161. currentHandleTime = time.Now().UnixMilli()
  162. room.Frames = append(room.Frames, NewSyncFrame_DeltaTime(currentHandleTime-lastHandleTime))
  163. lastHandleTime = currentHandleTime
  164. room.sendFrames()
  165. }
  166. logger.Info("Room ID", room.ID, "Frame Sync Stop")
  167. }
  168. //向房间内所有玩家发送同步帧
  169. func (room *Room) sendFrames() {
  170. room.Lock.Lock()
  171. defer room.Lock.Unlock()
  172. if len(room.Frames) > 0 {
  173. for _, v := range room.PlayerList {
  174. v.Notify_onFrameSync(room.Frames)
  175. }
  176. room.Frames = nil
  177. }
  178. }
  179. //缓存玩家上传的帧数据
  180. func (room *Room) CacheFrames(frames []interface{}) {
  181. room.Lock.Lock()
  182. defer room.Lock.Unlock()
  183. room.Frames = append(room.Frames, frames...)
  184. }