Skip to content

Commit b22b39c

Browse files
committed
v0.2
- Replace `finished` event with `finished_players` - Add `in_progress` event - Use player ID as origin in more cases
1 parent 02827aa commit b22b39c

File tree

6 files changed

+110
-54
lines changed

6 files changed

+110
-54
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ Prerequisites:
2929

3030
```sh
3131
# Download image
32-
docker pull codegameproject/hoverrace:0.1
32+
docker pull codegameproject/hoverrace:0.2
3333

3434
# Run container
35-
docker run -d -p <port-on-host-machine>:8080 --name hoverrace codegameproject/hoverrace:0.1
35+
docker run -d -p <port-on-host-machine>:8080 --name hoverrace codegameproject/hoverrace:0.2
3636
```
3737

3838
## Event Flow
@@ -45,7 +45,7 @@ docker run -d -p <port-on-host-machine>:8080 --name hoverrace codegameproject/ho
4545
6. Send a `throttle` event to begin moving.
4646
7. The `hovercrafts` event is sent repeatedly to all players to update them on the state of all hovercrafts.
4747
8. The `checkpoints` event is sent again when you cross a checkpoint.
48-
9. The `finished` event is sent to all players when a player crosses the finish line. The game keeps going until all players have finished.
48+
9. The `finished_players` event is sent to all players when a player crosses the finish line. It contains all of the players that have finished the race. The game keeps going until all players have finished.
4949
10. Send a `ready` event if you want to play again.
5050

5151
## Building

events.cge

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ version 0.3
55
// The game begins once at least 2 players have joined and all players have sent the `ready` event.
66
event start {}
77

8+
// The `in_progress` event is sent to sockets which connect to the game while it's running.
9+
event in_progress {}
10+
811
// The `countdown` counts down from 5. When the value reaches 0 a `start` event will be sent instead of the `countdown` event.
912
event countdown {
1013
// The current value of the countdown (5-1).
@@ -45,12 +48,10 @@ event hovercrafts {
4548
time: int64
4649
}
4750

48-
// The `finished` event is sent when a player crosses the finish line.
49-
event finished {
50-
// The place which the player has reached.
51-
place: int,
52-
// The amount of time in milliseconds the player needed to finish the race.
53-
duration: int64
51+
// The `finished_players` event contains a list of players that have finished the race.
52+
event finished_players {
53+
// A list of players that have finished the race sorted by their placement.
54+
players: list<finished_player>
5455
}
5556

5657
// A hovercraft is a circle with a diameter of 1 unit.
@@ -67,6 +68,16 @@ type hovercraft {
6768
checkpoints: int
6869
}
6970

71+
// `finished_player` represents an entry in the final ranking.
72+
type finished_player {
73+
// The ID of the player.
74+
id: string,
75+
// The place, the player has reached.
76+
place: int,
77+
// The amount of time in milliseconds the player needed to finish the race.
78+
duration: int64
79+
}
80+
7081
// One unit equals the width of the hovercrafts and checkpoints.
7182
type vec {
7283
// left to right

hoverrace/event_definitions.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ const StartEvent cg.EventName = "start"
99
type StartEventData struct {
1010
}
1111

12+
// The `in_progress` event is sent to sockets which connect to the game while it's running.
13+
const InProgressEvent cg.EventName = "in_progress"
14+
15+
type InProgressEventData struct {
16+
}
17+
1218
// The `countdown` counts down from 5. When the value reaches 0 a `start` event will be sent instead of the `countdown` event.
1319
const CountdownEvent cg.EventName = "countdown"
1420

@@ -62,14 +68,12 @@ type HovercraftsEventData struct {
6268
Time int64 `json:"time"`
6369
}
6470

65-
// The `finished` event is sent when a player crosses the finish line.
66-
const FinishedEvent cg.EventName = "finished"
71+
// The `finished_players` event contains a list of players that have finished the race.
72+
const FinishedPlayersEvent cg.EventName = "finished_players"
6773

68-
type FinishedEventData struct {
69-
// The place which the player has reached.
70-
Place int `json:"place"`
71-
// The amount of time in milliseconds the player needed to finish the race.
72-
Duration int64 `json:"duration"`
74+
type FinishedPlayersEventData struct {
75+
// A list of players that have finished the race sorted by their placement.
76+
Players []FinishedPlayer `json:"players"`
7377
}
7478

7579
// A hovercraft is a circle with a diameter of 1 unit.
@@ -86,6 +90,16 @@ type Hovercraft struct {
8690
Checkpoints int `json:"checkpoints"`
8791
}
8892

93+
// `finished_player` represents an entry in the final ranking.
94+
type FinishedPlayer struct {
95+
// The ID of the player.
96+
Id string `json:"id"`
97+
// The place, the player has reached.
98+
Place int `json:"place"`
99+
// The amount of time in milliseconds the player needed to finish the race.
100+
Duration int64 `json:"duration"`
101+
}
102+
89103
// One unit equals the width of the hovercrafts and checkpoints.
90104
type Vec struct {
91105
// left to right

hoverrace/game.go

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type Game struct {
1414
hovercrafts map[string]Hovercraft
1515
checkpoints []Vec
1616
finishLine Vec
17-
finishedPlayers int
17+
finishedPlayers []FinishedPlayer
1818
running bool
1919
startTime time.Time
2020
}
@@ -23,9 +23,11 @@ const targetFrameTime time.Duration = 1 * time.Second / 30
2323

2424
func NewGame(cgGame *cg.Game) *Game {
2525
game := &Game{
26-
cg: cgGame,
27-
players: make(map[string]*Player),
28-
hovercrafts: make(map[string]Hovercraft),
26+
cg: cgGame,
27+
players: make(map[string]*Player),
28+
hovercrafts: make(map[string]Hovercraft),
29+
finishedPlayers: make([]FinishedPlayer, 0),
30+
checkpoints: make([]Vec, 0, 10),
2931
}
3032
game.cg.OnPlayerJoined = game.onPlayerJoined
3133
game.cg.OnPlayerLeft = game.onPlayerLeft
@@ -76,6 +78,18 @@ func (g *Game) onPlayerJoined(cgPlayer *cg.Player) {
7678
g.hovercrafts[cgPlayer.Id] = Hovercraft{}
7779

7880
g.positionHovercrafts()
81+
82+
readyPlayers := make([]string, 0, len(g.players))
83+
for _, p := range g.players {
84+
if p.ready {
85+
readyPlayers = append(readyPlayers, p.id)
86+
}
87+
}
88+
if len(readyPlayers) > 0 {
89+
cgPlayer.Send("server", ReadyPlayersEvent, ReadyPlayersEventData{
90+
Players: readyPlayers,
91+
})
92+
}
7993
}
8094

8195
func (g *Game) onPlayerLeft(player *cg.Player) {
@@ -93,7 +107,7 @@ func (g *Game) onPlayerLeft(player *cg.Player) {
93107
}
94108
g.start()
95109
} else {
96-
if g.finishedPlayers == len(g.players) {
110+
if len(g.finishedPlayers) == len(g.players) {
97111
g.finish()
98112
}
99113
}
@@ -102,37 +116,46 @@ func (g *Game) onPlayerLeft(player *cg.Player) {
102116

103117
func (g *Game) onPlayerSocketConnected(player *cg.Player, socket *cg.Socket) {
104118
if len(g.checkpoints) > 0 {
105-
g.cg.Send("server", HovercraftsEvent, HovercraftsEventData{
119+
socket.Send("server", HovercraftsEvent, HovercraftsEventData{
106120
Hovercrafts: g.hovercrafts,
107121
Time: time.Now().UnixMilli(),
108122
})
109123

110124
p := g.players[player.Id]
111-
p.cg.Send("server", CheckpointsEvent, CheckpointsEventData{
125+
socket.Send("server", CheckpointsEvent, CheckpointsEventData{
112126
Checkpoints: p.checkpoints,
113127
FinishLine: g.finishLine,
114128
})
115129
}
116130

131+
readyPlayers := make([]string, 0, len(g.players))
132+
for _, p := range g.players {
133+
if p.ready {
134+
readyPlayers = append(readyPlayers, p.id)
135+
}
136+
}
137+
if len(readyPlayers) > 0 {
138+
socket.Send("server", ReadyPlayersEvent, ReadyPlayersEventData{
139+
Players: readyPlayers,
140+
})
141+
}
142+
117143
if !g.running {
118144
return
119145
}
120146

121-
socket.Send("server", StartEvent, StartEventData{})
147+
socket.Send("server", InProgressEvent, InProgressEventData{})
122148

123-
for _, player := range g.players {
124-
if player.finished {
125-
socket.Send(player.id, FinishedEvent, FinishedEventData{
126-
Place: player.place,
127-
Duration: player.duration,
128-
})
129-
}
149+
if len(g.finishedPlayers) > 0 {
150+
socket.Send("server", FinishedPlayersEvent, FinishedPlayersEventData{
151+
Players: g.finishedPlayers,
152+
})
130153
}
131154
}
132155

133156
func (g *Game) onSpectatorConnected(socket *cg.Socket) {
134157
if len(g.checkpoints) > 0 {
135-
g.cg.Send("server", HovercraftsEvent, HovercraftsEventData{
158+
socket.Send("server", HovercraftsEvent, HovercraftsEventData{
136159
Hovercrafts: g.hovercrafts,
137160
Time: time.Now().UnixMilli(),
138161
})
@@ -143,19 +166,28 @@ func (g *Game) onSpectatorConnected(socket *cg.Socket) {
143166
})
144167
}
145168

169+
readyPlayers := make([]string, 0, len(g.players))
170+
for _, p := range g.players {
171+
if p.ready {
172+
readyPlayers = append(readyPlayers, p.id)
173+
}
174+
}
175+
if len(readyPlayers) > 0 {
176+
socket.Send("server", ReadyPlayersEvent, ReadyPlayersEventData{
177+
Players: readyPlayers,
178+
})
179+
}
180+
146181
if !g.running {
147182
return
148183
}
149184

150-
socket.Send("server", StartEvent, StartEventData{})
185+
socket.Send("server", InProgressEvent, InProgressEventData{})
151186

152-
for _, player := range g.players {
153-
if player.finished {
154-
socket.Send(player.id, FinishedEvent, FinishedEventData{
155-
Place: player.place,
156-
Duration: player.duration,
157-
})
158-
}
187+
if len(g.finishedPlayers) > 0 {
188+
socket.Send("server", FinishedPlayersEvent, FinishedPlayersEventData{
189+
Players: g.finishedPlayers,
190+
})
159191
}
160192
}
161193

@@ -201,7 +233,7 @@ func (g *Game) handleReady(playerId string) {
201233
}
202234
}
203235

204-
g.cg.Send("server", ReadyPlayersEvent, ReadyPlayersEventData{
236+
g.cg.Send(playerId, ReadyPlayersEvent, ReadyPlayersEventData{
205237
Players: readyPlayers,
206238
})
207239

@@ -232,7 +264,7 @@ func (g *Game) handleThrottle(playerId string, event cg.Event) {
232264
}
233265

234266
func (g *Game) start() {
235-
g.finishedPlayers = 0
267+
g.finishedPlayers = g.finishedPlayers[:0]
236268
g.createCheckpoints()
237269

238270
for _, player := range g.players {
@@ -289,11 +321,11 @@ func (g *Game) positionHovercrafts() {
289321

290322
func (g *Game) finish() {
291323
g.running = false
324+
g.checkpoints = g.checkpoints[:0]
292325
}
293326

294327
func (g *Game) createCheckpoints() {
295-
g.checkpoints = make([]Vec, 10)
296-
328+
g.checkpoints = g.checkpoints[:cap(g.checkpoints)]
297329
for i := range g.checkpoints {
298330
g.checkpoints[i] = Vec{
299331
X: rand.Float64()*50*2 - 50,

hoverrace/player.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ type Player struct {
1919
ready bool
2020

2121
finished bool
22-
place int
23-
duration int64
2422

2523
checkpoints []Vec
2624

@@ -133,15 +131,16 @@ outer:
133131

134132
if len(p.checkpoints) == 0 && math.Abs(p.game.finishLine.Sub(p.pos).MagnitudeSquared()) <= 1 {
135133
p.finished = true
136-
p.game.finishedPlayers++
137-
p.place = p.game.finishedPlayers
138-
p.duration = time.Now().Sub(p.game.startTime).Milliseconds()
139-
p.game.cg.Send(p.id, FinishedEvent, FinishedEventData{
140-
Place: p.place,
141-
Duration: p.duration,
134+
p.game.finishedPlayers = append(p.game.finishedPlayers, FinishedPlayer{
135+
Id: p.id,
136+
Place: len(p.game.finishedPlayers) + 1,
137+
Duration: time.Now().Sub(p.game.startTime).Milliseconds(),
138+
})
139+
p.game.cg.Send(p.id, FinishedPlayersEvent, FinishedPlayersEventData{
140+
Players: p.game.finishedPlayers,
142141
})
143142

144-
if p.game.finishedPlayers == len(p.game.players) {
143+
if len(p.game.finishedPlayers) == len(p.game.players) {
145144
p.game.finish()
146145
}
147146
}

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func main() {
3131
server := cg.NewServer("hoverrace", cg.ServerConfig{
3232
DisplayName: "Hover Race",
3333
Description: "Race against other hovercrafts from checkpoint to checkpoint.",
34-
Version: "0.1",
34+
Version: "0.2",
3535
RepositoryURL: "https://github.com/code-game-project/hoverrace",
3636
WebsocketTimeout: 1 * time.Minute,
3737
MaxPlayersPerGame: 10,

0 commit comments

Comments
 (0)