@@ -8,14 +8,20 @@ import (
88)
99
1010type Game struct {
11- cg * cg.Game
11+ cg * cg.Game
12+ players map [string ]* Player
13+ checkpoints []Position
14+ finishedPlayers int
15+ running bool
16+ startTime time.Time
1217}
1318
1419const targetFrameTime time.Duration = 1 * time .Second / 30
1520
1621func NewGame (cgGame * cg.Game ) * Game {
1722 game := & Game {
18- cg : cgGame ,
23+ cg : cgGame ,
24+ players : make (map [string ]* Player ),
1925 }
2026 game .cg .OnPlayerJoined = game .onPlayerJoined
2127 game .cg .OnPlayerLeft = game .onPlayerLeft
@@ -32,28 +38,154 @@ func (g *Game) Run() {
3238 break
3339 }
3440 g .handleEvent (event .Player , event .Event )
41+ g .update ()
3542 }
3643 time .Sleep (targetFrameTime - time .Now ().Sub (frameStart ))
3744 }
3845}
3946
40- func (g * Game ) onPlayerJoined (player * cg.Player ) {
47+ func (g * Game ) onPlayerJoined (cgPlayer * cg.Player ) {
48+ if g .running {
49+ cgPlayer .Send ("server" , cg .ErrorEvent , cg.ErrorEventData {
50+ Message : "the game has already begun" ,
51+ })
52+ cgPlayer .Leave ()
53+ return
54+ }
4155
56+ g .players [cgPlayer .Id ] = & Player {
57+ id : cgPlayer .Id ,
58+ cg : cgPlayer ,
59+ username : cgPlayer .Username ,
60+ game : g ,
61+ }
4262}
4363
4464func (g * Game ) onPlayerLeft (player * cg.Player ) {
65+ _ , ok := g .players [player .Id ]
66+ if ! ok {
67+ return
68+ }
69+
70+ delete (g .players , player .Id )
71+
72+ if ! g .running {
73+ for _ , p := range g .players {
74+ if ! p .ready {
75+ return
76+ }
77+ }
78+ g .start ()
79+ } else {
80+ if g .finishedPlayers == len (g .players ) {
81+ g .finish ()
82+ }
83+ }
4584
4685}
4786
4887func (g * Game ) onPlayerSocketConnected (player * cg.Player , socket * cg.Socket ) {
88+ if ! g .running {
89+ return
90+ }
91+
92+ p := g .players [player .Id ]
93+ p .cg .Send ("server" , CheckpointsEvent , CheckpointsEventData {
94+ Checkpoints : p .checkpoints ,
95+ })
4996
97+ socket .Send ("server" , StartEvent , StartEventData {})
98+
99+ for _ , player := range g .players {
100+ if player .finished {
101+ socket .Send (player .id , FinishedEvent , FinishedEventData {
102+ Place : player .place ,
103+ Duration : player .duration ,
104+ })
105+ }
106+ }
107+ }
108+
109+ func (g * Game ) update () {
110+ if ! g .running {
111+ return
112+ }
50113}
51114
52115func (g * Game ) handleEvent (player * cg.Player , event cg.Event ) {
53116 switch event .Name {
117+ case ReadyEvent :
118+ g .handleReady (player .Id )
54119 default :
55120 player .Send (player .Id , cg .ErrorEvent , cg.ErrorEventData {
56121 Message : fmt .Sprintf ("unexpected event: %s" , event .Name ),
57122 })
58123 }
59124}
125+
126+ func (g * Game ) handleReady (playerId string ) {
127+ player := g .players [playerId ]
128+ if g .running {
129+ player .cg .Send (playerId , cg .ErrorEvent , cg.ErrorEventData {
130+ Message : "the game has already begun" ,
131+ })
132+ return
133+ }
134+
135+ player .ready = true
136+
137+ if len (g .players ) < 2 {
138+ return
139+ }
140+
141+ readyPlayers := make ([]string , 0 , len (g .players ))
142+ for _ , p := range g .players {
143+ if p .ready {
144+ readyPlayers = append (readyPlayers , p .id )
145+ }
146+ }
147+
148+ g .cg .Send ("server" , ReadyPlayersEvent , ReadyPlayersEventData {
149+ Players : readyPlayers ,
150+ })
151+
152+ if len (readyPlayers ) == len (g .players ) {
153+ g .start ()
154+ }
155+ }
156+
157+ func (g * Game ) start () {
158+ g .finishedPlayers = 0
159+ g .createCheckpoints ()
160+
161+ for _ , player := range g .players {
162+ player .checkpoints = g .checkpoints
163+ }
164+
165+ g .running = true
166+ g .startTime = time .Now ()
167+
168+ g .cg .Send ("server" , CheckpointsEvent , CheckpointsEventData {
169+ Checkpoints : g .checkpoints ,
170+ })
171+
172+ for countdown := 5 ; countdown > 0 ; countdown -- {
173+ g .cg .Send ("server" , CountdownEvent , CountdownEventData {
174+ Value : countdown ,
175+ })
176+ time .Sleep (1 * time .Second )
177+ }
178+
179+ g .cg .Send ("server" , StartEvent , StartEventData {})
180+ }
181+
182+ func (g * Game ) finish () {
183+ for _ , player := range g .players {
184+ player .reset ()
185+ }
186+ g .running = false
187+ }
188+
189+ func (g * Game ) createCheckpoints () {
190+ g .checkpoints = make ([]Position , 5 )
191+ }
0 commit comments