Compare commits
11 Commits
3229941ab2
...
master
Author | SHA1 | Date | |
---|---|---|---|
1e0d90040a | |||
96a9ada1a9 | |||
d55585f77b | |||
d1fc577bdb | |||
937cc5deba | |||
8958c3328f | |||
dc459defc3 | |||
67809d2ecd | |||
c9d3d0c65f | |||
a3dd393b7f | |||
3779c2ada7 |
30
README.md
30
README.md
@ -1,2 +1,30 @@
|
|||||||
# autogo
|
# autogo
|
||||||
The silly Raylib cargame I made in C but in Go
|
The silly Raylib cargame I made in C but in Go for my champ
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
1. Install Go on your system if you haven't already. You can download the latest version from the [official Go website](https://golang.org/dl/).
|
||||||
|
2. Clone this repository using Git:
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.boner.be/bdnugget/autogo.git
|
||||||
|
```
|
||||||
|
3. Navigate to the project directory:
|
||||||
|
```bash
|
||||||
|
cd autogo
|
||||||
|
```
|
||||||
|
4. Run the following command to download and install the required dependencies:
|
||||||
|
```
|
||||||
|
go mod download
|
||||||
|
```
|
||||||
|
5. Build and run the game using the following command:
|
||||||
|
```
|
||||||
|
go run main.go
|
||||||
|
```
|
||||||
|
This should launch the game window, and you can start playing!
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### Note to self garage texture and other ImageMagicks
|
||||||
|
changed saturation to 10% to make Raylib tint work well enough, using ImageMagick:
|
||||||
|
```convert garage.png -resize 200x200! -channel A -evaluate multiply 0.5 +channel -modulate 100,25,100 garage_200px.png```
|
3
go.mod
3
go.mod
@ -2,9 +2,10 @@ module github.com/bdnugget/autogo.git
|
|||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
|
require github.com/gen2brain/raylib-go/raylib v0.0.0-20240826113553-b4d0c52dc927
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ebitengine/purego v0.7.1 // indirect
|
github.com/ebitengine/purego v0.7.1 // indirect
|
||||||
github.com/gen2brain/raylib-go/raylib v0.0.0-20240826113553-b4d0c52dc927 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
|
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.24.0 // indirect
|
||||||
)
|
)
|
||||||
|
331
main.go
331
main.go
@ -3,234 +3,183 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
|
||||||
|
|
||||||
rl "github.com/gen2brain/raylib-go/raylib"
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SQUARE_SIZE int32 = 200
|
screenWidth = 1300
|
||||||
FPS_TARGET int32 = 60
|
screenHeight = 800
|
||||||
GARAGE_COUNT int32 = 5
|
numLanes = 5
|
||||||
|
laneHeight = screenHeight / numLanes
|
||||||
|
garageWidth = 200
|
||||||
|
scorePosx = 10
|
||||||
|
scorePosy = 10
|
||||||
|
scoreFontSize = 32
|
||||||
|
gameOverPosx = screenWidth/2 - 150
|
||||||
|
gameOverPosy = screenHeight/2 - 20
|
||||||
|
gameOverFontSize = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
garageColors = []rl.Color{rl.Red, rl.Blue, rl.Green, rl.Yellow, rl.Purple}
|
||||||
|
autoHappy rl.Sound
|
||||||
|
autoSad rl.Sound
|
||||||
|
autoTexture rl.Texture2D
|
||||||
|
garageTexture rl.Texture2D
|
||||||
|
asphaltTexture rl.Texture2D
|
||||||
|
highScore int
|
||||||
)
|
)
|
||||||
|
|
||||||
type Car struct {
|
type Car struct {
|
||||||
position rl.Vector2
|
texture rl.Texture2D
|
||||||
size rl.Vector2
|
lane int
|
||||||
color rl.Color
|
color rl.Color
|
||||||
direction int32
|
xPos int
|
||||||
|
speed int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCar() Car {
|
||||||
|
return Car{
|
||||||
|
texture: autoTexture,
|
||||||
|
lane: rand.Intn(numLanes),
|
||||||
|
color: randomColor(),
|
||||||
|
xPos: 25,
|
||||||
|
speed: 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Garage struct {
|
type Garage struct {
|
||||||
position rl.Vector2
|
lane int
|
||||||
size rl.Vector2
|
|
||||||
color rl.Color
|
color rl.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
type GameState struct {
|
type Game struct {
|
||||||
score int32
|
|
||||||
car Car
|
car Car
|
||||||
framesCounter int32
|
garages [numLanes]Garage
|
||||||
|
score int
|
||||||
gameOver bool
|
gameOver bool
|
||||||
pause bool
|
debugMsg string
|
||||||
allowMove bool
|
|
||||||
garages []Garage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func NewGame() Game {
|
||||||
screenWidth int32 = 1600
|
game := Game{
|
||||||
screenHeight int32 = 1000
|
car: NewCar(),
|
||||||
|
score: 0,
|
||||||
|
gameOver: false,
|
||||||
|
}
|
||||||
|
|
||||||
autoTexture rl.Texture2D
|
// Initialize garages
|
||||||
autoHappy rl.Sound
|
for i := range game.garages {
|
||||||
autoSad rl.Sound
|
game.garages[i] = Garage{
|
||||||
garageColors = []rl.Color{rl.Red, rl.Green, rl.Blue, rl.Yellow, rl.Purple}
|
lane: i,
|
||||||
gameState GameState
|
color: garageColors[i],
|
||||||
offset rl.Vector2
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
rl.InitWindow(screenWidth, screenHeight, "Dikke Vette Cargame voor Milo")
|
|
||||||
rl.InitAudioDevice()
|
|
||||||
defer rl.CloseAudioDevice()
|
|
||||||
defer rl.CloseWindow()
|
|
||||||
|
|
||||||
autoHappy = rl.LoadSound("resources/auto_happy_vob.ogg")
|
|
||||||
autoSad = rl.LoadSound("resources/auto_sad_vob.ogg")
|
|
||||||
autoTexture = rl.LoadTexture("resources/car_200px.png")
|
|
||||||
defer rl.UnloadSound(autoHappy)
|
|
||||||
defer rl.UnloadSound(autoSad)
|
|
||||||
defer rl.UnloadTexture(autoTexture)
|
|
||||||
|
|
||||||
offset = rl.Vector2{X: float32(screenWidth % SQUARE_SIZE), Y: float32(screenHeight % SQUARE_SIZE)}
|
|
||||||
|
|
||||||
InitGame()
|
|
||||||
|
|
||||||
rl.SetTargetFPS(FPS_TARGET)
|
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
|
||||||
UpdateDrawFrame()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitGame() {
|
return game
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
randomIndex := rand.Intn(int(GARAGE_COUNT))
|
|
||||||
|
|
||||||
gameState.framesCounter = 0
|
|
||||||
gameState.gameOver = false
|
|
||||||
gameState.pause = false
|
|
||||||
gameState.allowMove = false
|
|
||||||
gameState.car = Car{
|
|
||||||
position: rl.Vector2{X: offset.X / 2, Y: offset.Y/2 + 2*float32(SQUARE_SIZE)},
|
|
||||||
size: rl.Vector2{X: float32(SQUARE_SIZE), Y: float32(SQUARE_SIZE)},
|
|
||||||
color: garageColors[randomIndex],
|
|
||||||
direction: 0,
|
|
||||||
}
|
}
|
||||||
gameState.garages = make([]Garage, GARAGE_COUNT)
|
func randomColor() rl.Color {
|
||||||
|
return garageColors[rand.Intn(len(garageColors))]
|
||||||
InitGarages()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateDrawFrame() {
|
func (g Game) draw() {
|
||||||
UpdateGame()
|
for i := 0; i <= screenHeight/laneHeight; i++ {
|
||||||
DrawGame()
|
for j := 0; j < screenWidth/int(asphaltTexture.Width); j++ {
|
||||||
}
|
rl.DrawTexturePro(asphaltTexture, rl.NewRectangle(0, 0, float32(asphaltTexture.Width), float32(asphaltTexture.Height)), rl.NewRectangle(float32(j)*float32(asphaltTexture.Width), float32(i*laneHeight-laneHeight/2), float32(asphaltTexture.Width), float32(asphaltTexture.Height)), rl.Vector2{}, 0, rl.White)
|
||||||
|
|
||||||
func UpdateGame() {
|
|
||||||
if !gameState.gameOver {
|
|
||||||
HandlePause()
|
|
||||||
HandleMovement()
|
|
||||||
CheckCollisions()
|
|
||||||
IncrementFrameCounter()
|
|
||||||
} else {
|
|
||||||
HandleRestart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandlePause() {
|
|
||||||
if rl.IsKeyPressed(int32('P')) {
|
|
||||||
gameState.pause = !gameState.pause
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleMovement() {
|
|
||||||
if !gameState.pause {
|
|
||||||
if rl.IsKeyPressed(rl.KeyUp) && gameState.allowMove && gameState.car.position.Y > 0 {
|
|
||||||
gameState.car.direction = -1
|
|
||||||
gameState.allowMove = false
|
|
||||||
}
|
|
||||||
if (rl.IsKeyPressed(rl.KeyDown) || rl.IsKeyPressed(rl.KeyLeft) || rl.IsKeyPressed(rl.KeyRight)) &&
|
|
||||||
gameState.allowMove &&
|
|
||||||
gameState.car.position.Y < float32(screenHeight-SQUARE_SIZE) {
|
|
||||||
gameState.car.direction = 1
|
|
||||||
gameState.allowMove = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if gameState.framesCounter%(FPS_TARGET/60) == 0 {
|
|
||||||
MoveCar()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MoveCar() {
|
|
||||||
gameState.car.position.X += float32(SQUARE_SIZE) / float32(FPS_TARGET)
|
|
||||||
gameState.car.position.Y += float32(gameState.car.direction * SQUARE_SIZE)
|
|
||||||
gameState.allowMove = true
|
|
||||||
gameState.car.direction = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckCollisions() {
|
|
||||||
for i := int32(0); i < GARAGE_COUNT; i++ {
|
|
||||||
if rl.CheckCollisionRecs(
|
|
||||||
rl.Rectangle{X: gameState.car.position.X, Y: gameState.car.position.Y, Width: gameState.car.size.X, Height: gameState.car.size.Y},
|
|
||||||
rl.Rectangle{X: gameState.garages[i].position.X, Y: gameState.garages[i].position.Y, Width: gameState.garages[i].size.X, Height: gameState.garages[i].size.Y},
|
|
||||||
) {
|
|
||||||
HandleCollision(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleCollision(index int32) {
|
|
||||||
if rl.ColorToInt(gameState.car.color) == rl.ColorToInt(gameState.garages[index].color) {
|
|
||||||
rl.PlaySound(autoHappy)
|
|
||||||
gameState.score++
|
|
||||||
InitGame()
|
|
||||||
} else {
|
|
||||||
rl.PlaySound(autoSad)
|
|
||||||
gameState.gameOver = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IncrementFrameCounter() {
|
|
||||||
gameState.framesCounter++
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleRestart() {
|
|
||||||
if rl.IsKeyPressed(rl.KeyEnter) {
|
|
||||||
gameState.score = 0
|
|
||||||
InitGame()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func DrawGame() {
|
|
||||||
rl.BeginDrawing()
|
|
||||||
|
|
||||||
rl.ClearBackground(rl.DarkGray)
|
|
||||||
|
|
||||||
if !gameState.gameOver {
|
|
||||||
for i := int32(1); i < screenHeight/SQUARE_SIZE+1; i++ {
|
|
||||||
for j := int32(0); j < screenWidth/(SQUARE_SIZE/2); j += 2 {
|
|
||||||
rl.DrawRectangle(
|
|
||||||
int32(j)*((SQUARE_SIZE/2)+int32(offset.X)/2),
|
|
||||||
int32(i*SQUARE_SIZE+int32(offset.Y)/2),
|
|
||||||
SQUARE_SIZE/2,
|
|
||||||
SQUARE_SIZE/8,
|
|
||||||
rl.RayWhite,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw garages
|
// Draw garages
|
||||||
for i := int32(0); i < GARAGE_COUNT; i++ {
|
for _, garage := range g.garages {
|
||||||
rl.DrawRectangleRec(
|
rl.DrawTexture(garageTexture, int32(screenWidth-garageWidth), int32(garage.lane*laneHeight), garage.color)
|
||||||
rl.Rectangle{X: gameState.garages[i].position.X, Y: gameState.garages[i].position.Y, Width: gameState.garages[i].size.X, Height: gameState.garages[i].size.Y},
|
|
||||||
gameState.garages[i].color,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.DrawTextureV(autoTexture, gameState.car.position, gameState.car.color)
|
// Draw car
|
||||||
|
rl.DrawTexture(g.car.texture, int32(g.car.xPos), int32(g.car.lane*laneHeight), g.car.color)
|
||||||
|
|
||||||
// Draw score
|
rl.DrawText(fmt.Sprintf("Score: %d\nHigh Score: %d", g.score, highScore), scorePosx, scorePosy, scoreFontSize, rl.DarkGreen)
|
||||||
rl.DrawText(fmt.Sprintf("Score: %d", gameState.score), 20, 20, 20, rl.RayWhite)
|
if g.gameOver {
|
||||||
|
rl.DrawText("You're not an WinRAR :(\nPress Enter to Restart", gameOverPosx, gameOverPosy, gameOverFontSize, rl.Red)
|
||||||
if gameState.pause {
|
|
||||||
rl.DrawText(
|
|
||||||
"GAME PAUSED",
|
|
||||||
screenWidth/2-rl.MeasureText("GAME PAUSED", 40)/2,
|
|
||||||
screenHeight/2-40,
|
|
||||||
40,
|
|
||||||
rl.Gray,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) update() {
|
||||||
|
if rl.IsKeyPressed(rl.KeyF) {
|
||||||
|
rl.ToggleFullscreen()
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.gameOver {
|
||||||
|
if rl.IsKeyPressed(rl.KeyEnter) || rl.IsKeyPressed(rl.KeyKpEnter) || rl.IsGestureDetected(rl.GestureTap) {
|
||||||
|
*g = NewGame()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g.car.xPos += g.car.speed
|
||||||
|
|
||||||
|
// Check if the car has reached the garages
|
||||||
|
if int32(g.car.xPos)+g.car.texture.Width >= screenWidth-garageWidth {
|
||||||
|
garage := g.garages[g.car.lane]
|
||||||
|
if g.car.color == garage.color {
|
||||||
|
rl.PlaySound(autoHappy)
|
||||||
|
g.score++
|
||||||
|
if g.score > highScore {
|
||||||
|
highScore = g.score
|
||||||
|
}
|
||||||
|
g.car = NewCar()
|
||||||
} else {
|
} else {
|
||||||
rl.DrawText(
|
rl.PlaySound(autoSad)
|
||||||
"A WINRAR IS NOT YOU :(\nPRESS [ENTER] TO PLAY AGAIN",
|
g.gameOver = true
|
||||||
screenWidth/2-rl.MeasureText("A WINRAR IS NOT YOU :(\nPRESS [ENTER] TO PLAY AGAIN", 20)/2,
|
|
||||||
screenHeight/2-50,
|
|
||||||
20,
|
|
||||||
rl.Gray,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g.car.speed = 3 + g.score/5
|
||||||
|
|
||||||
|
// Move car
|
||||||
|
if rl.IsGestureDetected(rl.GestureTap) {
|
||||||
|
touchY := int(rl.GetTouchY())
|
||||||
|
lane := touchY / (screenHeight / numLanes)
|
||||||
|
g.debugMsg = fmt.Sprintf("Y: %d, Lane: %d", touchY, lane)
|
||||||
|
g.car.lane = lane
|
||||||
|
}
|
||||||
|
|
||||||
|
if rl.IsKeyPressed(rl.KeyUp) && g.car.lane > 0 {
|
||||||
|
g.car.lane--
|
||||||
|
} else if (rl.IsKeyPressed(rl.KeyDown) || rl.IsKeyPressed(rl.KeyLeft) || rl.IsKeyPressed(rl.KeyRight)) && g.car.lane < numLanes-1 {
|
||||||
|
g.car.lane++
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.DrawText(g.debugMsg, 20, 100, 32, rl.Red)
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
rl.InitWindow(screenWidth, screenHeight, "Dikke Vette Cargame voor Milo")
|
||||||
|
rl.InitAudioDevice()
|
||||||
|
defer rl.CloseAudioDevice()
|
||||||
|
|
||||||
|
// Load assets
|
||||||
|
autoHappy = rl.LoadSound("resources/auto_happy_vob.ogg")
|
||||||
|
autoSad = rl.LoadSound("resources/auto_sad_vob.ogg")
|
||||||
|
autoTexture = rl.LoadTexture("resources/car_200px.png")
|
||||||
|
garageTexture = rl.LoadTexture("resources/garage_200px.png")
|
||||||
|
asphaltTexture = rl.LoadTexture("resources/asphalt.png")
|
||||||
|
defer rl.UnloadTexture(autoTexture)
|
||||||
|
defer rl.UnloadTexture(garageTexture)
|
||||||
|
defer rl.UnloadTexture(asphaltTexture)
|
||||||
|
defer rl.UnloadSound(autoHappy)
|
||||||
|
defer rl.UnloadSound(autoSad)
|
||||||
|
|
||||||
|
game := NewGame()
|
||||||
|
|
||||||
|
rl.SetTargetFPS(60)
|
||||||
|
|
||||||
|
for !rl.WindowShouldClose() {
|
||||||
|
rl.BeginDrawing()
|
||||||
|
rl.ClearBackground(rl.DarkGray)
|
||||||
|
|
||||||
|
game.update()
|
||||||
|
game.draw()
|
||||||
|
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitGarages() {
|
|
||||||
for i := int32(0); i < GARAGE_COUNT; i++ {
|
|
||||||
gameState.garages[i].size = rl.Vector2{X: float32(SQUARE_SIZE), Y: float32(SQUARE_SIZE)}
|
|
||||||
gameState.garages[i].position = rl.Vector2{X: float32(screenWidth - SQUARE_SIZE), Y: float32(i * SQUARE_SIZE)}
|
|
||||||
gameState.garages[i].color = garageColors[i]
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
BIN
resources/asphalt.png
Normal file
BIN
resources/asphalt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
resources/garage.png
Normal file
BIN
resources/garage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
resources/garage_200px.png
Normal file
BIN
resources/garage_200px.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
resources/ground_asphalt_synth_12.png
Normal file
BIN
resources/ground_asphalt_synth_12.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 633 KiB |
BIN
resources/screenshot.png
Normal file
BIN
resources/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 429 KiB |
Reference in New Issue
Block a user