-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.go
142 lines (130 loc) · 3.24 KB
/
player.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"log"
"math/rand"
"time"
"github.com/gorilla/websocket"
)
// Player represents a player connected to a websocket and their associated game information
type Player struct {
X int `json:"x"`
Y int `json:"y"`
Direction string `json:"direction"`
Speed int `json:"speed"`
Active bool `json:"active"`
Name string `json:"name"`
conn *websocket.Conn
ch chan string
}
// Input contains the action that a player took. It is sent to the server via the web socket.
type Input struct {
Action string `json:"action"`
}
func (p *Player) createInputChannel() {
ch := make(chan string)
go func() {
input := Input{}
for p.conn != nil {
err := p.conn.ReadJSON(&input)
if err != nil {
p.conn = nil
} else {
ch <- input.Action
}
}
log.Println("player", p.Name, "disconnected")
p.Active = false
}()
p.ch = ch
}
// ReadActionAndProcess reads an action from the player's web socket. If no action is sent within the deadline, the player drops out
func (p *Player) ReadActionAndProcess(status *GameStatus, id int, deadline time.Time, jump bool) {
if p.conn != nil {
var action string
select {
case action = <-p.ch:
case <-time.After(deadline.Sub(time.Now().UTC())):
p.Active = false
return
}
if action != "turn_left" && action != "turn_right" && action != "slow_down" && action != "speed_up" {
action = "change_nothing"
}
if action == "speed_up" {
if p.Speed != 10 {
p.Speed++
}
} else if action == "slow_down" {
if p.Speed != 1 {
p.Speed--
}
} else if action == "turn_left" {
switch p.Direction {
case "left":
p.Direction = "down"
break
case "down":
p.Direction = "right"
break
case "right":
p.Direction = "up"
break
case "up":
p.Direction = "left"
break
}
} else if action == "turn_right" {
switch p.Direction {
case "left":
p.Direction = "up"
break
case "down":
p.Direction = "left"
break
case "right":
p.Direction = "down"
break
case "up":
p.Direction = "right"
break
}
}
for i := 1; i <= p.Speed; i++ {
if p.Direction == "up" {
p.Y--
} else if p.Direction == "down" {
p.Y++
} else if p.Direction == "right" {
p.X++
} else if p.Direction == "left" {
p.X--
}
if p.X >= config.Width || p.Y >= config.Height || p.X < 0 || p.Y < 0 {
p.Active = false
break
}
if !jump || i == 1 || i == p.Speed {
// If the cell is non-empty set error bit and do not write to the cell
if status.Cells[p.Y][p.X] != 0 {
status.occupiedCells[p.Y][p.X] |= 1
} else {
status.Cells[p.Y][p.X] = id
}
status.occupiedCells[p.Y][p.X] |= (1 << id)
}
}
}
log.Println("Player coordinates: ", id, p.X, p.Y)
}
// NewPlayer creates a new player that starts at the specified coordinates, with the specified websocket connection and name
func NewPlayer(x int, y int, c *websocket.Conn, name string) *Player {
p := Player{Speed: 1, Active: true, Direction: DIRECTIONS[rand.Intn(4)], Name: name, X: x, Y: y, conn: c}
p.createInputChannel()
return &p
}
// CloseConnection closes the player's connection, if it exists
func (p *Player) CloseConnection() {
if conn := p.conn; conn != nil {
conn.Close()
}
}