diff --git a/examples/games/floppy/main.go b/examples/games/floppy/main.go new file mode 100644 index 0000000..4290946 --- /dev/null +++ b/examples/games/floppy/main.go @@ -0,0 +1,182 @@ +package main + +import ( + "fmt" + + "github.com/gen2brain/raylib-go/raylib" +) + +const ( + maxTubes = 100 + floppyRadius = 24.0 + tubesWidth = 80 +) + +type Floppy struct { + Position raylib.Vector2 + Radius float32 + Color raylib.Color +} + +type Tubes struct { + Rec raylib.Rectangle + Color raylib.Color + Active bool +} + +type Game struct { + ScreenWidth int32 + ScreenHeight int32 + + FramesCounter int32 + GameOver bool + Pause bool + Score int + HiScore int + + Floppy Floppy + Tubes []Tubes + TubesPos []raylib.Vector2 + TubesSpeedX int32 + SuperFX bool +} + +func main() { + game := Game{} + game.Init() + + raylib.InitWindow(game.ScreenWidth, game.ScreenHeight, "sample game: floppy") + + raylib.SetTargetFPS(60) + + for !raylib.WindowShouldClose() { + game.Update() + + game.Draw() + } + + raylib.CloseWindow() +} + +// Initialize game +func (g *Game) Init() { + g.ScreenWidth = 800 + g.ScreenHeight = 450 + + g.Floppy = Floppy{} + g.Floppy.Radius = floppyRadius + g.Floppy.Position = raylib.NewVector2(80, float32(g.ScreenHeight)/2-g.Floppy.Radius) + g.TubesSpeedX = 2 + + g.TubesPos = make([]raylib.Vector2, maxTubes) + + for i := 0; i < maxTubes; i++ { + g.TubesPos[i].X = float32(400 + 280*i) + g.TubesPos[i].Y = -float32(raylib.GetRandomValue(0, 120)) + } + + g.Tubes = make([]Tubes, maxTubes*2) + + for i := 0; i < maxTubes*2; i += 2 { + g.Tubes[i].Rec.X = int32(g.TubesPos[i/2].X) + g.Tubes[i].Rec.Y = int32(g.TubesPos[i/2].Y) + g.Tubes[i].Rec.Width = tubesWidth + g.Tubes[i].Rec.Height = 255 + + g.Tubes[i+1].Rec.X = int32(g.TubesPos[i/2].X) + g.Tubes[i+1].Rec.Y = int32(600 + g.TubesPos[i/2].Y - 255) + g.Tubes[i+1].Rec.Width = tubesWidth + g.Tubes[i+1].Rec.Height = 255 + + g.Tubes[i/2].Active = true + } + + g.Score = 0 + g.FramesCounter = 0 + + g.GameOver = false + g.SuperFX = false + g.Pause = false +} + +// Update game +func (g *Game) Update() { + if !g.GameOver { + if raylib.IsKeyPressed(raylib.KeyP) { + g.Pause = !g.Pause + } + + if !g.Pause { + for i := 0; i < maxTubes; i++ { + g.TubesPos[i].X -= float32(g.TubesSpeedX) + } + + for i := 0; i < maxTubes*2; i += 2 { + g.Tubes[i].Rec.X = int32(g.TubesPos[i/2].X) + g.Tubes[i+1].Rec.X = int32(g.TubesPos[i/2].X) + } + + if raylib.IsKeyDown(raylib.KeySpace) && !g.GameOver { + g.Floppy.Position.Y -= 3 + } else { + g.Floppy.Position.Y += 1 + } + + // Check Collisions + for i := 0; i < maxTubes*2; i++ { + if raylib.CheckCollisionCircleRec(g.Floppy.Position, g.Floppy.Radius, g.Tubes[i].Rec) { + g.GameOver = true + g.Pause = false + } else if (g.TubesPos[i/2].X < g.Floppy.Position.X) && g.Tubes[i/2].Active && !g.GameOver { + g.Score += 100 + g.Tubes[i/2].Active = false + + g.SuperFX = true + + if g.Score > g.HiScore { + g.HiScore = g.Score + } + } + } + } + } else { + if raylib.IsKeyPressed(raylib.KeyEnter) { + g.Init() + g.GameOver = false + } + } +} + +// Draw game +func (g *Game) Draw() { + raylib.BeginDrawing() + + raylib.ClearBackground(raylib.RayWhite) + + if !g.GameOver { + raylib.DrawCircle(int32(g.Floppy.Position.X), int32(g.Floppy.Position.Y), g.Floppy.Radius, raylib.DarkGray) + + // Draw tubes + for i := 0; i < maxTubes; i++ { + raylib.DrawRectangle(g.Tubes[i*2].Rec.X, g.Tubes[i*2].Rec.Y, g.Tubes[i*2].Rec.Width, g.Tubes[i*2].Rec.Height, raylib.Gray) + raylib.DrawRectangle(g.Tubes[i*2+1].Rec.X, g.Tubes[i*2+1].Rec.Y, g.Tubes[i*2+1].Rec.Width, g.Tubes[i*2+1].Rec.Height, raylib.Gray) + } + + // Draw flashing fx (one frame only) + if g.SuperFX { + raylib.DrawRectangle(0, 0, g.ScreenWidth, g.ScreenHeight, raylib.White) + g.SuperFX = false + } + + raylib.DrawText(fmt.Sprintf("%04d", g.Score), 20, 20, 40, raylib.Gray) + raylib.DrawText(fmt.Sprintf("HI-SCORE: %04d", g.HiScore), 20, 70, 20, raylib.LightGray) + + if g.Pause { + raylib.DrawText("GAME PAUSED", g.ScreenWidth/2-raylib.MeasureText("GAME PAUSED", 40)/2, g.ScreenHeight/2-40, 40, raylib.Gray) + } + } else { + raylib.DrawText("PRESS [ENTER] TO PLAY AGAIN", raylib.GetScreenWidth()/2-raylib.MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, raylib.GetScreenHeight()/2-50, 20, raylib.Gray) + } + + raylib.EndDrawing() +} diff --git a/examples/games/snake/main.go b/examples/games/snake/main.go new file mode 100644 index 0000000..45948f1 --- /dev/null +++ b/examples/games/snake/main.go @@ -0,0 +1,235 @@ +package main + +import ( + "github.com/gen2brain/raylib-go/raylib" +) + +const ( + snakeLength = 256 + squareSize = 31 +) + +type Snake struct { + Position raylib.Vector2 + Size raylib.Vector2 + Speed raylib.Vector2 + Color raylib.Color +} + +type Food struct { + Position raylib.Vector2 + Size raylib.Vector2 + Active bool + Color raylib.Color +} + +type Game struct { + ScreenWidth int32 + ScreenHeight int32 + + FramesCounter int32 + GameOver bool + Pause bool + + Fruit Food + Snake []Snake + SnakePosition []raylib.Vector2 + AllowMove bool + Offset raylib.Vector2 + CounterTail int +} + +func main() { + game := Game{} + game.Init() + + raylib.InitWindow(game.ScreenWidth, game.ScreenHeight, "sample game: snake") + + raylib.SetTargetFPS(60) + + for !raylib.WindowShouldClose() { + game.Update() + + game.Draw() + } + + raylib.CloseWindow() +} + +// Initialize game +func (g *Game) Init() { + g.ScreenWidth = 800 + g.ScreenHeight = 450 + + g.FramesCounter = 0 + g.GameOver = false + g.Pause = false + + g.CounterTail = 1 + g.AllowMove = false + + g.Offset = raylib.Vector2{} + g.Offset.X = float32(g.ScreenWidth % squareSize) + g.Offset.Y = float32(g.ScreenHeight % squareSize) + + g.Snake = make([]Snake, snakeLength) + + for i := 0; i < snakeLength; i++ { + g.Snake[i].Position = raylib.NewVector2(g.Offset.X/2, g.Offset.Y/2) + g.Snake[i].Size = raylib.NewVector2(squareSize, squareSize) + g.Snake[i].Speed = raylib.NewVector2(squareSize, 0) + + if i == 0 { + g.Snake[i].Color = raylib.DarkBlue + } else { + g.Snake[i].Color = raylib.Blue + } + } + + g.SnakePosition = make([]raylib.Vector2, snakeLength) + + for i := 0; i < snakeLength; i++ { + g.SnakePosition[i] = raylib.NewVector2(0.0, 0.0) + } + + g.Fruit.Size = raylib.NewVector2(squareSize, squareSize) + g.Fruit.Color = raylib.SkyBlue + g.Fruit.Active = false +} + +// Update game +func (g *Game) Update() { + if !g.GameOver { + if raylib.IsKeyPressed('P') { + g.Pause = !g.Pause + } + + if !g.Pause { + // control + if raylib.IsKeyPressed(raylib.KeyRight) && g.Snake[0].Speed.X == 0 && g.AllowMove { + g.Snake[0].Speed = raylib.NewVector2(squareSize, 0) + g.AllowMove = false + } + if raylib.IsKeyPressed(raylib.KeyLeft) && g.Snake[0].Speed.X == 0 && g.AllowMove { + g.Snake[0].Speed = raylib.NewVector2(-squareSize, 0) + g.AllowMove = false + } + if raylib.IsKeyPressed(raylib.KeyUp) && g.Snake[0].Speed.Y == 0 && g.AllowMove { + g.Snake[0].Speed = raylib.NewVector2(0, -squareSize) + g.AllowMove = false + } + if raylib.IsKeyPressed(raylib.KeyDown) && g.Snake[0].Speed.Y == 0 && g.AllowMove { + g.Snake[0].Speed = raylib.NewVector2(0, squareSize) + g.AllowMove = false + } + + // movement + for i := 0; i < g.CounterTail; i++ { + g.SnakePosition[i] = g.Snake[i].Position + } + + if g.FramesCounter%5 == 0 { + for i := 0; i < g.CounterTail; i++ { + if i == 0 { + g.Snake[0].Position.X += g.Snake[0].Speed.X + g.Snake[0].Position.Y += g.Snake[0].Speed.Y + g.AllowMove = true + } else { + g.Snake[i].Position = g.SnakePosition[i-1] + } + } + } + + // wall behaviour + if ((g.Snake[0].Position.X) > (float32(g.ScreenWidth) - g.Offset.X)) || + ((g.Snake[0].Position.Y) > (float32(g.ScreenHeight) - g.Offset.Y)) || + (g.Snake[0].Position.X < 0) || (g.Snake[0].Position.Y < 0) { + g.GameOver = true + } + + // collision with yourself + for i := 1; i < g.CounterTail; i++ { + if (g.Snake[0].Position.X == g.Snake[i].Position.X) && (g.Snake[0].Position.Y == g.Snake[i].Position.Y) { + g.GameOver = true + } + } + + if !g.Fruit.Active { + g.Fruit.Active = true + g.Fruit.Position = raylib.NewVector2( + float32(raylib.GetRandomValue(0, (g.ScreenWidth/squareSize)-1)*squareSize+int32(g.Offset.X)/2), + float32(raylib.GetRandomValue(0, (g.ScreenHeight/squareSize)-1)*squareSize+int32(g.Offset.Y)/2), + ) + + for i := 0; i < g.CounterTail; i++ { + for (g.Fruit.Position.X == g.Snake[i].Position.X) && (g.Fruit.Position.Y == g.Snake[i].Position.Y) { + g.Fruit.Position = raylib.NewVector2( + float32(raylib.GetRandomValue(0, (g.ScreenWidth/squareSize)-1)*squareSize), + float32(raylib.GetRandomValue(0, (g.ScreenHeight/squareSize)-1)*squareSize), + ) + i = 0 + } + } + } + + // collision + if raylib.CheckCollisionRecs( + raylib.NewRectangle(int32(g.Snake[0].Position.X), int32(g.Snake[0].Position.Y), int32(g.Snake[0].Size.X), int32(g.Snake[0].Size.Y)), + raylib.NewRectangle(int32(g.Fruit.Position.X), int32(g.Fruit.Position.Y), int32(g.Fruit.Size.X), int32(g.Fruit.Size.Y)), + ) { + g.Snake[g.CounterTail].Position = g.SnakePosition[g.CounterTail-1] + g.CounterTail += 1 + g.Fruit.Active = false + } + + g.FramesCounter++ + } + } else { + if raylib.IsKeyPressed(raylib.KeyEnter) { + g.Init() + g.GameOver = false + } + } +} + +// Draw game +func (g *Game) Draw() { + raylib.BeginDrawing() + + raylib.ClearBackground(raylib.RayWhite) + + if !g.GameOver { + // Draw grid lines + for i := int32(0); i < g.ScreenWidth/squareSize+1; i++ { + raylib.DrawLineV( + raylib.NewVector2(float32(squareSize*i)+g.Offset.X/2, g.Offset.Y/2), + raylib.NewVector2(float32(squareSize*i)+g.Offset.X/2, float32(g.ScreenHeight)-g.Offset.Y/2), + raylib.LightGray, + ) + } + + for i := int32(0); i < g.ScreenHeight/squareSize+1; i++ { + raylib.DrawLineV( + raylib.NewVector2(g.Offset.X/2, float32(squareSize*i)+g.Offset.Y/2), + raylib.NewVector2(float32(g.ScreenWidth)-g.Offset.X/2, float32(squareSize*i)+g.Offset.Y/2), + raylib.LightGray, + ) + } + + // Draw snake + for i := 0; i < g.CounterTail; i++ { + raylib.DrawRectangleV(g.Snake[i].Position, g.Snake[i].Size, g.Snake[i].Color) + } + + // Draw fruit to pick + raylib.DrawRectangleV(g.Fruit.Position, g.Fruit.Size, g.Fruit.Color) + + if g.Pause { + raylib.DrawText("GAME PAUSED", g.ScreenWidth/2-raylib.MeasureText("GAME PAUSED", 40)/2, g.ScreenHeight/2-40, 40, raylib.Gray) + } + } else { + raylib.DrawText("PRESS [ENTER] TO PLAY AGAIN", raylib.GetScreenWidth()/2-raylib.MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, raylib.GetScreenHeight()/2-50, 20, raylib.Gray) + } + + raylib.EndDrawing() +}