Skip to content

Commit cfcfdc0

Browse files
committed
Initial commit
0 parents  commit cfcfdc0

File tree

10 files changed

+1045
-0
lines changed

10 files changed

+1045
-0
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.git/
2+
README.md

Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM golang:1.18-bullseye
2+
3+
# Set working directory for source
4+
WORKDIR /usr/src/app
5+
6+
# Pre-copy/cache go.mod for pre-downloading dependencies and only redownloading them in subsequent builds if they change
7+
COPY go.mod go.sum ./
8+
RUN go mod download && go mod verify
9+
10+
# Compile the app
11+
COPY . .
12+
RUN go build -v -o /usr/local/bin ./...
13+
14+
# Switch to a low-privileged user
15+
RUN adduser --no-create-home go --shell /bin/sh && chown -R go:go /usr/local/bin/hoverrace
16+
USER go
17+
18+
# Expose the port
19+
ENV CG_PORT="8080"
20+
EXPOSE 8080
21+
22+
# Run the app
23+
CMD [ "hoverrace" ]

LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# hoverrace
2+
![CodeGame Version](https://img.shields.io/badge/CodeGame-v0.6-orange)
3+
![CodeGame GameServer Version](https://img.shields.io/badge/GameServer-v0.1-yellow)
4+
![CGE Version](https://img.shields.io/badge/CGE-v0.3-green)
5+
6+
Race against other hovercrafts from checkpoint to checkpoint.
7+
8+
## Known instances
9+
10+
- `games.code-game.org/hoverrace`
11+
12+
## Usage
13+
14+
```sh
15+
# Run on default port 80
16+
hoverrace
17+
18+
# Specify a custom port
19+
hoverrace --port=8080
20+
21+
## Specify a custom port through an environment variable
22+
CG_PORT=8080 hoverrace
23+
```
24+
25+
### Running with Docker
26+
27+
Prerequisites:
28+
- [Docker](https://docker.com/)
29+
30+
```sh
31+
# Download image
32+
docker pull codegameproject/hoverrace:0.1
33+
34+
# Run container
35+
docker run -d -p <port-on-host-machine>:8080 --name hoverrace codegameproject/hoverrace:0.1
36+
```
37+
38+
## Event Flow
39+
40+
1. Send a `ready` event to the server when you think the game should begin.
41+
2. A `ready_players` event updates all players on the readiness of all players.
42+
3. A `start` event is sent to all players when the race begins. It includes the positions of all checkpoints.
43+
4. A `next_checkpoint` event is sent to every player to tell them where their next target is located.
44+
5. Send a `throttle` event to begin moving.
45+
6. A `hovercrafts` event is sent repeatedly to all players to update them on the state of all hovercrafts.
46+
7. A `finished` event is sent to all players when a player crosses the finish line. The game keeps going until all players have finished.
47+
8. Send a `ready` event if you want to play again.
48+
49+
## Building
50+
51+
### Prerequisites
52+
53+
- [Go](https://go.dev) 1.18+
54+
55+
```sh
56+
git clone https://github.com/code-game-project/hoverrace.git
57+
cd hoverrace
58+
go build .
59+
```
60+
## License
61+
62+
Copyright (C) 2022 Julian Hofmann
63+
64+
This program is free software: you can redistribute it and/or modify
65+
it under the terms of the GNU Affero General Public License as published
66+
by the Free Software Foundation, either version 3 of the License, or
67+
(at your option) any later version.
68+
69+
This program is distributed in the hope that it will be useful,
70+
but WITHOUT ANY WARRANTY; without even the implied warranty of
71+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72+
GNU Affero General Public License for more details.
73+
74+
You should have received a copy of the GNU Affero General Public License
75+
along with this program. If not, see <https://www.gnu.org/licenses/>.

events.cge

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name hoverrace
2+
version 0.3
3+
4+
// The `start` event is sent when the race begins.
5+
// The game begins once at least 2 players have joined and all players have sent the `ready` event.
6+
event start {
7+
// The positions of all checkpoints.
8+
checkpoints: list<position>
9+
}
10+
11+
// Send the `ready` event to the server when you think the game should begin.
12+
event ready {}
13+
14+
// The `ready_players` event contains a list of all players which are ready.
15+
event ready_players {
16+
// A list of all ready players.
17+
players: list<string>
18+
}
19+
20+
// The `throttle` event allows you to change your throttle level and direction.
21+
// **NOTE:** This values are targets. The hovercraft needs some time to reach the desired values.
22+
event throttle {
23+
// Throttle level between 0-1.
24+
level: float,
25+
// The angle in degrees the hovercraft should be facing (up = 0°).
26+
angle: float
27+
}
28+
29+
// The `hovercraft` event tells all clients where all the hovercrafts are and how they are moving.
30+
event hovercrafts {
31+
// All hovercrafts mapped to their respective player IDs.
32+
hovercrafts: map<hovercraft>,
33+
// The time in UNIX seconds when this event occured.
34+
time: int64
35+
}
36+
37+
// The `next_checkpoint` tells you the position of the next checkpoint.
38+
event next_checkpoint {
39+
// The position of the next checkpoint.
40+
pos: position
41+
}
42+
43+
// The `finished` event is sent when a player crosses the finish line.
44+
event finished {
45+
// The ID of the player who reached the finish line.
46+
player: string,
47+
// The place which the player has reached.
48+
place: int
49+
}
50+
51+
type hovercraft {
52+
// The position of the hovercraft.
53+
pos: position,
54+
// The current speed of the hovercraft.
55+
speed: float,
56+
// The angle in degrees the hovercraft is facing (up = 0°).
57+
angle: float
58+
}
59+
60+
type position {
61+
x: float,
62+
y: float
63+
}

go.mod

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module github.com/code-game-project/hoverrace
2+
3+
go 1.18
4+
5+
require (
6+
github.com/code-game-project/go-server v0.7.1
7+
github.com/spf13/pflag v1.0.5
8+
)
9+
10+
require (
11+
github.com/Bananenpro/log v0.0.0-20220531131028-71d66f5df6ae // indirect
12+
github.com/google/uuid v1.3.0 // indirect
13+
github.com/gorilla/mux v1.8.0 // indirect
14+
github.com/gorilla/websocket v1.5.0 // indirect
15+
github.com/mattn/go-colorable v0.1.12 // indirect
16+
github.com/mattn/go-isatty v0.0.14 // indirect
17+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
18+
)

go.sum

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
github.com/Bananenpro/log v0.0.0-20220531131028-71d66f5df6ae h1:3soztN/rE1IKMZse/qOQm2xLIVrAv5b8rGOggMtgZdw=
2+
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=
5+
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
6+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7+
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
8+
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
9+
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
10+
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
11+
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
12+
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
13+
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
14+
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
15+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
16+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
17+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
18+
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
19+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
20+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

hoverrace/event_definitions.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package hoverrace
2+
3+
import "github.com/code-game-project/go-server/cg"
4+
5+
// The `start` event is sent when the race begins.
6+
// The game begins once at least 2 players have joined and all players have sent the `ready` event.
7+
const StartEvent cg.EventName = "start"
8+
9+
type StartEventData struct {
10+
// The positions of all checkpoints.
11+
Checkpoints []Position `json:"checkpoints"`
12+
}
13+
14+
// Send the `ready` event to the server when you think the game should begin.
15+
const ReadyEvent cg.EventName = "ready"
16+
17+
type ReadyEventData struct {
18+
}
19+
20+
// The `ready_players` event contains a list of all players which are ready.
21+
const ReadyPlayersEvent cg.EventName = "ready_players"
22+
23+
type ReadyPlayersEventData struct {
24+
// A list of all ready players.
25+
Players []string `json:"players"`
26+
}
27+
28+
// The `throttle` event allows you to change your throttle level and direction.
29+
// **NOTE:** This values are targets. The hovercraft needs some time to reach the desired values.
30+
const ThrottleEvent cg.EventName = "throttle"
31+
32+
type ThrottleEventData struct {
33+
// Throttle level between 0-1.
34+
Level float64 `json:"level"`
35+
// The angle in degrees the hovercraft should be facing (up = 0°).
36+
Angle float64 `json:"angle"`
37+
}
38+
39+
// The `hovercraft` event tells all clients where all the hovercrafts are and how they are moving.
40+
const HovercraftsEvent cg.EventName = "hovercrafts"
41+
42+
type HovercraftsEventData struct {
43+
// All hovercrafts mapped to their respective player IDs.
44+
Hovercrafts map[string]Hovercraft `json:"hovercrafts"`
45+
// The time in UNIX seconds when this event occured.
46+
Time int64 `json:"time"`
47+
}
48+
49+
// The `next_checkpoint` tells you the position of the next checkpoint.
50+
const NextCheckpointEvent cg.EventName = "next_checkpoint"
51+
52+
type NextCheckpointEventData struct {
53+
// The position of the next checkpoint.
54+
Pos Position `json:"pos"`
55+
}
56+
57+
// The `finished` event is sent when a player crosses the finish line.
58+
const FinishedEvent cg.EventName = "finished"
59+
60+
type FinishedEventData struct {
61+
// The ID of the player who reached the finish line.
62+
Player string `json:"player"`
63+
// The place which the player has reached.
64+
Place int `json:"place"`
65+
}
66+
67+
type Hovercraft struct {
68+
// The position of the hovercraft.
69+
Pos Position `json:"pos"`
70+
// The current speed of the hovercraft.
71+
Speed float64 `json:"speed"`
72+
// The angle in degrees the hovercraft is facing (up = 0°).
73+
Angle float64 `json:"angle"`
74+
}
75+
76+
type Position struct {
77+
X float64 `json:"x"`
78+
Y float64 `json:"y"`
79+
}

hoverrace/game.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package hoverrace
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
"github.com/code-game-project/go-server/cg"
8+
)
9+
10+
type Game struct {
11+
cg *cg.Game
12+
}
13+
14+
const targetFrameTime time.Duration = 1 * time.Second / 30
15+
16+
func NewGame(cgGame *cg.Game) *Game {
17+
game := &Game{
18+
cg: cgGame,
19+
}
20+
game.cg.OnPlayerJoined = game.onPlayerJoined
21+
game.cg.OnPlayerLeft = game.onPlayerLeft
22+
game.cg.OnPlayerSocketConnected = game.onPlayerSocketConnected
23+
return game
24+
}
25+
26+
func (g *Game) Run() {
27+
for g.cg.Running() {
28+
frameStart := time.Now()
29+
for {
30+
event, ok := g.cg.NextEvent()
31+
if !ok {
32+
break
33+
}
34+
g.handleEvent(event.Player, event.Event)
35+
}
36+
time.Sleep(targetFrameTime - time.Now().Sub(frameStart))
37+
}
38+
}
39+
40+
func (g *Game) onPlayerJoined(player *cg.Player) {
41+
42+
}
43+
44+
func (g *Game) onPlayerLeft(player *cg.Player) {
45+
46+
}
47+
48+
func (g *Game) onPlayerSocketConnected(player *cg.Player, socket *cg.Socket) {
49+
50+
}
51+
52+
func (g *Game) handleEvent(player *cg.Player, event cg.Event) {
53+
switch event.Name {
54+
default:
55+
player.Send(player.Id, cg.ErrorEvent, cg.ErrorEventData{
56+
Message: fmt.Sprintf("unexpected event: %s", event.Name),
57+
})
58+
}
59+
}

main.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"strconv"
6+
"time"
7+
8+
"github.com/code-game-project/go-server/cg"
9+
"github.com/code-game-project/hoverrace/hoverrace"
10+
"github.com/spf13/pflag"
11+
)
12+
13+
func main() {
14+
var port int
15+
pflag.IntVarP(&port, "port", "p", 0, "The network port of the game server.")
16+
pflag.Parse()
17+
18+
if port == 0 {
19+
portStr, ok := os.LookupEnv("CG_PORT")
20+
if ok {
21+
port, _ = strconv.Atoi(portStr)
22+
}
23+
}
24+
25+
if port == 0 {
26+
port = 80
27+
}
28+
29+
server := cg.NewServer("hoverrace", cg.ServerConfig{
30+
DisplayName: "Hover Race",
31+
Description: "Race against other hovercrafts from checkpoint to checkpoint.",
32+
Version: "0.1",
33+
RepositoryURL: "https://github.com/code-game-project/hoverrace",
34+
WebsocketTimeout: 1 * time.Minute,
35+
MaxPlayersPerGame: 10,
36+
Port: port,
37+
CGEFilepath: "events.cge",
38+
DeleteInactiveGameDelay: 30 * time.Minute,
39+
KickInactivePlayerDelay: 1 * time.Minute,
40+
})
41+
42+
server.Run(func(cgGame *cg.Game) {
43+
hoverrace.NewGame(cgGame).Run()
44+
})
45+
}

0 commit comments

Comments
 (0)