game.go 2.6 KB

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