game.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package game
  2. import (
  3. "battlecamp-go-server/board"
  4. "battlecamp-go-server/player"
  5. "battlecamp-go-server/stomp"
  6. "log"
  7. "math/rand"
  8. "sync"
  9. "time"
  10. )
  11. type Game struct {
  12. Id int64 `json:"id"`
  13. StartTime int64 `json:"startTime"`
  14. EndTime int64 `json:"endTime"`
  15. Board *board.Board `json:"board"`
  16. Players []*player.Player `json:"-"`
  17. mutex sync.Mutex
  18. Winner *player.Player `json:"winner,omitempty"`
  19. }
  20. func NewGame(cols, rows int) *Game {
  21. createTime := time.Now().Unix()
  22. game := &Game{
  23. StartTime: createTime,
  24. Board: board.NewRemote(cols, rows),
  25. Players: make([]*player.Player, 0),
  26. }
  27. return game
  28. }
  29. func (g *Game) Join(p *player.Player) {
  30. g.mutex.Lock()
  31. g.placePlayer(p)
  32. g.Players = append(g.Players, p)
  33. g.mutex.Unlock()
  34. }
  35. func (g *Game) placePlayer(p *player.Player) {
  36. xRange := g.Board.Width / 5
  37. yRange := g.Board.Height
  38. for {
  39. x := rand.Intn(xRange)
  40. y := rand.Intn(yRange)
  41. if g.isValidPlayerPos(x, y) {
  42. p.Pos.X = x
  43. p.Pos.Y = y
  44. return
  45. }
  46. }
  47. }
  48. type updatePlayers struct {
  49. GameId int64 `json:"gameId"`
  50. Players []*player.Player `json:"players"`
  51. }
  52. type stompGameEnd struct {
  53. Type string `json:"type"`
  54. GameId int64 `json:"gameId"`
  55. Payload string `json:"payload"`
  56. }
  57. func (g *Game) Move(p *player.Player, direction string) bool {
  58. if !(direction == "N" || direction == "W" || direction == "S" || direction == "E") {
  59. log.Printf("Illigal direction %v", direction)
  60. return false
  61. }
  62. newX := p.Pos.X
  63. newY := p.Pos.Y
  64. switch direction {
  65. case "N":
  66. newY--
  67. case "W":
  68. newX--
  69. case "S":
  70. newY++
  71. case "E":
  72. newX++
  73. }
  74. //TODO make thread safe
  75. if !g.isValidPlayerPos(newX, newY) {
  76. log.Printf("Illigal player pos oldX %v oldY %v newX %v newY %v dir %v ", p.Pos.X, p.Pos.Y, newX, newY, direction)
  77. return false
  78. }
  79. p.Pos.X = newX
  80. p.Pos.Y = newY
  81. // END TODO make tread safe
  82. up := updatePlayers{
  83. GameId: g.Id,
  84. Players: g.Players,
  85. }
  86. stomp.SendJson("update", up)
  87. if g.isWinner(p) {
  88. g.EndTime = time.Now().Unix()
  89. g.Winner = p
  90. ge := stompGameEnd{
  91. Type: "GAME_END",
  92. GameId: g.Id,
  93. Payload: g.Winner.Id,
  94. }
  95. stomp.SendJson("game", ge)
  96. }
  97. return true
  98. }
  99. func (g *Game) isWinner(p *player.Player) bool {
  100. return g.Board.Finish.X == p.Pos.X && g.Board.Finish.Y == p.Pos.Y
  101. }
  102. func (g *Game) isValidPlayerPos(x, y int) bool {
  103. if x < 0 || y < 0 || x >= g.Board.Width || y >= g.Board.Height {
  104. return false
  105. }
  106. t := g.Board.Get(x, y)
  107. if t == board.Rock {
  108. return false
  109. }
  110. return g.getPlayerAt(x, y) == nil
  111. }
  112. func (g *Game) getPlayerAt(x, y int) *player.Player {
  113. for _, p := range g.Players {
  114. if p.Pos.X == x && p.Pos.Y == y {
  115. return p
  116. }
  117. }
  118. return nil
  119. }
  120. func (g *Game) GetPlayer(playerId string) *player.Player {
  121. for _, p := range g.Players {
  122. if p.Id == playerId {
  123. return p
  124. }
  125. }
  126. return nil
  127. }