Skip to content

Commit 5f60f10

Browse files
committed
Implement player movement
1 parent 923f143 commit 5f60f10

File tree

7 files changed

+261
-28
lines changed

7 files changed

+261
-28
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ docker run -d -p <port-on-host-machine>:8080 --name hoverrace codegameproject/ho
3939

4040
1. Send a `ready` event to the server when you think the game should begin.
4141
2. The `ready_players` event updates all players on the readiness of all players.
42-
3. The `checkpoints` event contains the checkpoints you have to reach.
42+
3. The `checkpoints` event contains all checkpoints and the finish line position.
4343
4. The `countdown` event counts down 5 seconds.
4444
5. The `start` event is sent to all players when the race begins.
4545
6. Send a `throttle` event to begin moving.

events.cge

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ event countdown {
1414
// The `checkpoints` event contains all of the remaining checkpoints.
1515
event checkpoints {
1616
// The positions of all the remaining checkpoints.
17-
checkpoints: list<position>
17+
checkpoints: list<vec>,
18+
// The position of the finish line.
19+
finish_line: vec
1820
}
1921

2022
// Send the `ready` event to the server when you think the game should begin.
@@ -54,17 +56,20 @@ event finished {
5456
// A hovercraft is a circle with a diameter of 1 unit.
5557
type hovercraft {
5658
// The position of the center of the hovercraft.
57-
pos: position,
58-
// The current speed of the hovercraft.
59-
speed: float,
59+
pos: vec,
60+
// The current velocity of the hovercraft.
61+
velocity: vec,
62+
// The current throttle of the hovercraft.
63+
throttle: float64,
6064
// The angle in degrees the hovercraft is facing (up = 0°).
6165
angle: float,
6266
// The amount of reached checkpoints.
6367
checkpoints: int
6468
}
6569

6670
// One unit equals the width of the hovercrafts and checkpoints.
67-
type position {
71+
// The origin is in the bottom left corner.
72+
type vec {
6873
x: float,
6974
y: float
7075
}

go.sum

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
github.com/Bananenpro/log v0.0.0-20220531131028-71d66f5df6ae h1:3soztN/rE1IKMZse/qOQm2xLIVrAv5b8rGOggMtgZdw=
22
github.com/Bananenpro/log v0.0.0-20220531131028-71d66f5df6ae/go.mod h1:deSMMVnGJzim4MopRkA5zp+QJ5I0p+Fg3iBD2edIZpU=
3-
github.com/code-game-project/go-server v0.7.1 h1:2gD2uYNMf7fMqfMuJM2AckGB8H+EZ68SFRTObUBu25I=
4-
github.com/code-game-project/go-server v0.7.1/go.mod h1:V9vz3gbpTXRlRGzcr/Wmyx47W3Ex8sZ6Odtri8pvcEs=
53
github.com/code-game-project/go-server v0.7.2 h1:+pOxZs6FYcJzU+76RldYA0nrPCC400vvaCDMAhFSMSo=
64
github.com/code-game-project/go-server v0.7.2/go.mod h1:V9vz3gbpTXRlRGzcr/Wmyx47W3Ex8sZ6Odtri8pvcEs=
75
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@@ -18,7 +16,5 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
1816
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
1917
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2018
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
21-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
22-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2319
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
2420
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

hoverrace/event_definitions.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ const CheckpointsEvent cg.EventName = "checkpoints"
2222

2323
type CheckpointsEventData struct {
2424
// The positions of all the remaining checkpoints.
25-
Checkpoints []Position `json:"checkpoints"`
25+
Checkpoints []Vec `json:"checkpoints"`
26+
// The position of the finish line.
27+
FinishLine Vec `json:"finish_line"`
2628
}
2729

2830
// Send the `ready` event to the server when you think the game should begin.
@@ -73,17 +75,20 @@ type FinishedEventData struct {
7375
// A hovercraft is a circle with a diameter of 1 unit.
7476
type Hovercraft struct {
7577
// The position of the center of the hovercraft.
76-
Pos Position `json:"pos"`
77-
// The current speed of the hovercraft.
78-
Speed float64 `json:"speed"`
78+
Pos Vec `json:"pos"`
79+
// The current velocity of the hovercraft.
80+
Velocity Vec `json:"velocity"`
81+
// The current throttle of the hovercraft.
82+
Throttle float64 `json:"throttle"`
7983
// The angle in degrees the hovercraft is facing (up = 0°).
8084
Angle float64 `json:"angle"`
8185
// The amount of reached checkpoints.
8286
Checkpoints int `json:"checkpoints"`
8387
}
8488

8589
// One unit equals the width of the hovercrafts and checkpoints.
86-
type Position struct {
90+
// The origin is in the bottom left corner.
91+
type Vec struct {
8792
X float64 `json:"x"`
8893
Y float64 `json:"y"`
8994
}

hoverrace/game.go

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import (
1010
type Game struct {
1111
cg *cg.Game
1212
players map[string]*Player
13-
checkpoints []Position
13+
hovercrafts map[string]Hovercraft
14+
checkpoints []Vec
15+
finishLine Vec
1416
finishedPlayers int
1517
running bool
1618
startTime time.Time
@@ -20,8 +22,9 @@ const targetFrameTime time.Duration = 1 * time.Second / 30
2022

2123
func NewGame(cgGame *cg.Game) *Game {
2224
game := &Game{
23-
cg: cgGame,
24-
players: make(map[string]*Player),
25+
cg: cgGame,
26+
players: make(map[string]*Player),
27+
hovercrafts: make(map[string]Hovercraft),
2528
}
2629
game.cg.OnPlayerJoined = game.onPlayerJoined
2730
game.cg.OnPlayerLeft = game.onPlayerLeft
@@ -30,6 +33,7 @@ func NewGame(cgGame *cg.Game) *Game {
3033
}
3134

3235
func (g *Game) Run() {
36+
deltaTime := targetFrameTime
3337
for g.cg.Running() {
3438
frameStart := time.Now()
3539
for {
@@ -38,9 +42,10 @@ func (g *Game) Run() {
3842
break
3943
}
4044
g.handleEvent(event.Player, event.Event)
41-
g.update()
4245
}
46+
g.update(deltaTime)
4347
time.Sleep(targetFrameTime - time.Now().Sub(frameStart))
48+
deltaTime = time.Now().Sub(frameStart)
4449
}
4550
}
4651

@@ -59,6 +64,8 @@ func (g *Game) onPlayerJoined(cgPlayer *cg.Player) {
5964
username: cgPlayer.Username,
6065
game: g,
6166
}
67+
68+
g.hovercrafts[cgPlayer.Id] = Hovercraft{}
6269
}
6370

6471
func (g *Game) onPlayerLeft(player *cg.Player) {
@@ -67,8 +74,6 @@ func (g *Game) onPlayerLeft(player *cg.Player) {
6774
return
6875
}
6976

70-
delete(g.players, player.Id)
71-
7277
if !g.running {
7378
for _, p := range g.players {
7479
if !p.ready {
@@ -92,6 +97,7 @@ func (g *Game) onPlayerSocketConnected(player *cg.Player, socket *cg.Socket) {
9297
p := g.players[player.Id]
9398
p.cg.Send("server", CheckpointsEvent, CheckpointsEventData{
9499
Checkpoints: p.checkpoints,
100+
FinishLine: g.finishLine,
95101
})
96102

97103
socket.Send("server", StartEvent, StartEventData{})
@@ -106,16 +112,27 @@ func (g *Game) onPlayerSocketConnected(player *cg.Player, socket *cg.Socket) {
106112
}
107113
}
108114

109-
func (g *Game) update() {
115+
func (g *Game) update(delta time.Duration) {
110116
if !g.running {
111117
return
112118
}
119+
120+
for _, player := range g.players {
121+
player.update(delta)
122+
}
123+
124+
g.cg.Send("server", HovercraftsEvent, HovercraftsEventData{
125+
Hovercrafts: g.hovercrafts,
126+
Time: time.Now().UnixMilli(),
127+
})
113128
}
114129

115130
func (g *Game) handleEvent(player *cg.Player, event cg.Event) {
116131
switch event.Name {
117132
case ReadyEvent:
118133
g.handleReady(player.Id)
134+
case ThrottleEvent:
135+
g.handleThrottle(player.Id, event)
119136
default:
120137
player.Send(player.Id, cg.ErrorEvent, cg.ErrorEventData{
121138
Message: fmt.Sprintf("unexpected event: %s", event.Name),
@@ -154,19 +171,38 @@ func (g *Game) handleReady(playerId string) {
154171
}
155172
}
156173

174+
func (g *Game) handleThrottle(playerId string, event cg.Event) {
175+
var data ThrottleEventData
176+
event.UnmarshalData(&data)
177+
178+
if data.Level > 1 {
179+
data.Level = 1
180+
} else if data.Level < 0 {
181+
data.Level = 0
182+
}
183+
184+
player := g.players[playerId]
185+
player.targetThrottle = data.Level
186+
player.targetAngle = data.Angle
187+
}
188+
157189
func (g *Game) start() {
158190
g.finishedPlayers = 0
159191
g.createCheckpoints()
160192

161193
for _, player := range g.players {
162-
player.checkpoints = g.checkpoints
163-
}
194+
player.checkpoints = make([]Vec, len(g.checkpoints))
195+
copy(player.checkpoints, g.checkpoints)
164196

165-
g.running = true
166-
g.startTime = time.Now()
197+
player.pos = Vec{
198+
X: 10,
199+
Y: 1,
200+
}
201+
}
167202

168203
g.cg.Send("server", CheckpointsEvent, CheckpointsEventData{
169204
Checkpoints: g.checkpoints,
205+
FinishLine: g.finishLine,
170206
})
171207

172208
for countdown := 5; countdown > 0; countdown-- {
@@ -176,6 +212,9 @@ func (g *Game) start() {
176212
time.Sleep(1 * time.Second)
177213
}
178214

215+
g.running = true
216+
g.startTime = time.Now()
217+
179218
g.cg.Send("server", StartEvent, StartEventData{})
180219
}
181220

@@ -187,5 +226,15 @@ func (g *Game) finish() {
187226
}
188227

189228
func (g *Game) createCheckpoints() {
190-
g.checkpoints = make([]Position, 5)
229+
// TODO: randomly generate checkpoint positions
230+
231+
g.checkpoints = []Vec{
232+
{X: 10, Y: 5},
233+
{X: 10, Y: 12},
234+
}
235+
236+
g.finishLine = Vec{
237+
X: 10,
238+
Y: 20,
239+
}
191240
}

hoverrace/math.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package hoverrace
2+
3+
import "math"
4+
5+
func (v Vec) Add(other Vec) Vec {
6+
return Vec{
7+
X: v.X + other.X,
8+
Y: v.Y + other.Y,
9+
}
10+
}
11+
12+
func (v Vec) Sub(other Vec) Vec {
13+
return Vec{
14+
X: v.X - other.X,
15+
Y: v.Y - other.Y,
16+
}
17+
}
18+
19+
func (v Vec) Mul(scalar float64) Vec {
20+
return Vec{
21+
X: v.X * scalar,
22+
Y: v.Y * scalar,
23+
}
24+
}
25+
26+
func (v Vec) Normalize() Vec {
27+
mag := v.Magnitude()
28+
return Vec{
29+
X: v.X / mag,
30+
Y: v.Y / mag,
31+
}
32+
}
33+
34+
func (v Vec) Magnitude() float64 {
35+
return math.Sqrt(v.MagnitudeSquared())
36+
}
37+
38+
func (v Vec) MagnitudeSquared() float64 {
39+
return v.X*v.X + v.Y*v.Y
40+
}
41+
42+
func VecFromAngle(degrees float64) Vec {
43+
radians := ToRadians(degrees + 90)
44+
return Vec{
45+
X: math.Cos(radians),
46+
Y: math.Sin(radians),
47+
}
48+
}
49+
50+
func ToRadians(degrees float64) float64 {
51+
return degrees * (math.Pi / 180)
52+
}
53+
54+
func ToDegrees(radians float64) float64 {
55+
return radians * (180 / math.Pi)
56+
}

0 commit comments

Comments
 (0)