From d251a96929b4948042097c4a5fea114eb5f2d06c Mon Sep 17 00:00:00 2001 From: Zykatious <30608121+Zykatious@users.noreply.github.com> Date: Mon, 18 Dec 2017 18:48:32 +0000 Subject: [PATCH] Updated neighbor count code Also added the ability to click toggle cells and all edges wrap. --- examples/games/life/main.go | 200 ++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 examples/games/life/main.go diff --git a/examples/games/life/main.go b/examples/games/life/main.go new file mode 100644 index 0000000..91e35c1 --- /dev/null +++ b/examples/games/life/main.go @@ -0,0 +1,200 @@ +package main + +import ( + "math/rand" + "time" + + "github.com/gen2brain/raylib-go/raylib" +) + +const ( + squareSize = 8 +) + +// Cell type +type Cell struct { + Position raylib.Vector2 + Size raylib.Vector2 + Alive bool + Next bool + Visited bool +} + +// Game type +type Game struct { + ScreenWidth int32 + ScreenHeight int32 + Cols int32 + Rows int32 + FramesCounter int32 + Playing bool + Cells [][]*Cell +} + +func main() { + rand.Seed(time.Now().UnixNano()) + + game := Game{} + game.Init(false) + + raylib.InitWindow(game.ScreenWidth, game.ScreenHeight, "Conway's Game of Life") + raylib.SetTargetFPS(20) + + for !raylib.WindowShouldClose() { + if game.Playing { + game.Update() + } + + game.Input() + + game.Draw() + } + + raylib.CloseWindow() +} + +// Init - Initialize game +func (g *Game) Init(clear bool) { + g.ScreenWidth = 1920 + g.ScreenHeight = 1100 + g.FramesCounter = 0 + + g.Cols = g.ScreenWidth / squareSize + g.Rows = g.ScreenHeight / squareSize + + g.Cells = make([][]*Cell, g.Cols+1) + for i := int32(0); i <= g.Cols; i++ { + g.Cells[i] = make([]*Cell, g.Rows+1) + } + + for x := int32(0); x <= g.Cols; x++ { + for y := int32(0); y <= g.Rows; y++ { + g.Cells[x][y] = &Cell{} + g.Cells[x][y].Position = raylib.NewVector2((float32(x) * squareSize), (float32(y)*squareSize)+1) + g.Cells[x][y].Size = raylib.NewVector2(squareSize-1, squareSize-1) + if rand.Float64() < 0.1 && clear == false { + g.Cells[x][y].Alive = true + } + } + } +} + +// Input - Game input +func (g *Game) Input() { + // control + if raylib.IsKeyPressed(raylib.KeyR) { + g.Init(false) + } + if raylib.IsKeyPressed(raylib.KeyC) { + g.Init(true) + } + if raylib.IsKeyDown(raylib.KeyRight) && !g.Playing { + g.Update() + } + if raylib.IsMouseButtonPressed(raylib.MouseLeftButton) { + g.Click(raylib.GetMouseX(), raylib.GetMouseY()) + } + if raylib.IsKeyPressed(raylib.KeySpace) { + g.Playing = !g.Playing + } + + g.FramesCounter++ +} + +// Click - Toggle if a cell is alive or dead on click +func (g *Game) Click(x, y int32) { + for i := int32(0); i <= g.Cols; i++ { + for j := int32(0); j <= g.Rows; j++ { + cell := g.Cells[i][j].Position + if int32(cell.X) < x && int32(cell.X)+squareSize > x && int32(cell.Y) < y && int32(cell.Y)+squareSize > y { + g.Cells[i][j].Alive = !g.Cells[i][j].Alive + g.Cells[i][j].Next = g.Cells[i][j].Alive + } + } + } +} + +// Update - Update game +func (g *Game) Update() { + for i := int32(0); i <= g.Cols; i++ { + for j := int32(0); j <= g.Rows; j++ { + NeighborCount := g.CountNeighbors(i, j) + if g.Cells[i][j].Alive { + if NeighborCount < 2 { + g.Cells[i][j].Next = false + } else if NeighborCount > 3 { + g.Cells[i][j].Next = false + } else { + g.Cells[i][j].Next = true + } + } else { + if NeighborCount == 3 { + g.Cells[i][j].Next = true + g.Cells[i][j].Visited = true + } + } + } + } + for i := int32(0); i <= g.Cols; i++ { + for j := int32(0); j < g.Rows; j++ { + g.Cells[i][j].Alive = g.Cells[i][j].Next + } + } +} + +// CountNeighbors - Counts how many neighbous a cell has +func (g *Game) CountNeighbors(x, y int32) int { + count := 0 + + for i := int32(-1); i < 2; i++ { + for j := int32(-1); j < 2; j++ { + col := (x + i + (g.Cols)) % (g.Cols) + row := (y + j + (g.Rows)) % (g.Rows) + if g.Cells[col][row].Alive { + count++ + } + } + } + + if g.Cells[x][y].Alive { + count-- + } + + return count +} + +// Draw - Draw game +func (g *Game) Draw() { + raylib.BeginDrawing() + raylib.ClearBackground(raylib.RayWhite) + + // Draw cells + for x := int32(0); x <= g.Cols; x++ { + for y := int32(0); y <= g.Rows; y++ { + if g.Cells[x][y].Alive { + raylib.DrawRectangleV(g.Cells[x][y].Position, g.Cells[x][y].Size, raylib.Blue) + } else if g.Cells[x][y].Visited { + raylib.DrawRectangleV(g.Cells[x][y].Position, g.Cells[x][y].Size, raylib.Color{R: 128, G: 177, B: 136, A: 255}) + } + } + } + + // Draw grid lines + for i := int32(0); i < g.Cols+1; i++ { + raylib.DrawLineV( + raylib.NewVector2(float32(squareSize*i), 0), + raylib.NewVector2(float32(squareSize*i), float32(g.ScreenHeight)), + raylib.LightGray, + ) + } + + for i := int32(0); i < g.Rows+1; i++ { + raylib.DrawLineV( + raylib.NewVector2(0, float32(squareSize*i)), + raylib.NewVector2(float32(g.ScreenWidth), float32(squareSize*i)), + raylib.LightGray, + ) + } + + raylib.EndDrawing() +}