<!DOCTYPE html> <meta charset="utf-8"> <meta property="og:image" itemprop="image primaryImageOfPage" content="https://hajimehoshi.github.io/ebiten/images/examples/life.png"> <meta name="description" content="Ebiten example - life"> <link rel="shortcut icon" href="../favicon.png" type="image/png" > <link rel="icon" href="../favicon.png" type="image/png" > <title>Ebiten example - life</title> <link rel="stylesheet" href="../stylesheets/bootstrap.min.css"> <link rel="stylesheet" href="../stylesheets/highlight-github.css"> <link rel="stylesheet" href="../stylesheets/ebiten.css"> <script src="../scripts/googleanalytics.js"></script> <nav class="navbar"><div class="container"> <nav class="d-flex flex-row" style="width: 100%;"> <div class="nav mr-auto"><a class="navbar-brand" href="../"><img src="../images/logo_white.svg" alt="EBITEN"></a></div> <ul class="nav"> <li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten">GitHub</a></li> <li class="nav-item"><a class="nav-link" href="https://godoc.org/github.com/hajimehoshi/ebiten">GoDoc</a></li> <li class="nav-item"><a class="nav-link" href="https://github.com/hajimehoshi/ebiten/wiki">Wiki</a> <li class="nav-item"><a class="nav-link" href="https://ebiten-playground.github.io/">Playground</a> </ul> </nav> </div></nav> <main><div class="container"> <h2>Ebiten example - life</h2> <iframe src="life.content.html" width="640" height="480"></iframe> <div class="card"><pre class="card-body"><code class="language-go">// +build example package main import ( "log" "math/rand" "time" "github.com/hajimehoshi/ebiten" ) // World represents the game state. type World struct { area [][]bool } func newArea(width, height int) [][]bool { a := make([][]bool, height) for i := 0; i < height; i++ { a[i] = make([]bool, width) } return a } // NewWorld creates a new world. func NewWorld(width, height int, maxInitLiveCells int) *World { w := &World{ area: newArea(width, height), } w.init(maxInitLiveCells) return w } func init() { rand.Seed(time.Now().UnixNano()) } // init inits world with a random state. func (w *World) init(maxLiveCells int) { height := len(w.area) width := len(w.area[0]) for i := 0; i < maxLiveCells; i++ { x := rand.Intn(width) y := rand.Intn(height) w.area[y][x] = true } } // Update game state by one tick. func (w *World) Update() { height := len(w.area) width := len(w.area[0]) next := newArea(width, height) for y := 0; y < height; y++ { for x := 0; x < width; x++ { pop := neighbourCount(w.area, x, y) switch { case pop < 2: // rule 1. Any live cell with fewer than two live neighbours // dies, as if caused by under-population. next[y][x] = false case (pop == 2 || pop == 3) && w.area[y][x]: // rule 2. Any live cell with two or three live neighbours // lives on to the next generation. next[y][x] = true case pop > 3: // rule 3. Any live cell with more than three live neighbours // dies, as if by over-population. next[y][x] = false case pop == 3: // rule 4. Any dead cell with exactly three live neighbours // becomes a live cell, as if by reproduction. next[y][x] = true } } } w.area = next } // Draw paints current game state. func (w *World) Draw(pix []byte) { height := len(w.area) width := len(w.area[0]) for y := 0; y < height; y++ { for x := 0; x < width; x++ { idx := 4*y*width + 4*x if w.area[y][x] { pix[idx] = 0xff pix[idx+1] = 0xff pix[idx+2] = 0xff pix[idx+3] = 0xff } else { pix[idx] = 0 pix[idx+1] = 0 pix[idx+2] = 0 pix[idx+3] = 0 } } } } func max(a, b int) int { if a < b { return b } return a } func min(a, b int) int { if a < b { return a } return b } // neighbourCount calculates the Moore neighborhood of (x, y). func neighbourCount(a [][]bool, x, y int) int { w := len(a[0]) h := len(a) minI := max(x-1, 0) minJ := max(y-1, 0) maxI := min(x+1, w-1) maxJ := min(y+1, h-1) c := 0 for j := minJ; j <= maxJ; j++ { for i := minI; i <= maxI; i++ { if i == x && j == y { continue } if a[j][i] { c++ } } } return c } const ( screenWidth = 320 screenHeight = 240 ) var ( world = NewWorld(screenWidth, screenHeight, int((screenWidth*screenHeight)/10)) pixels = make([]byte, screenWidth*screenHeight*4) ) func update(screen *ebiten.Image) error { world.Update() if ebiten.IsRunningSlowly() { return nil } world.Draw(pixels) screen.ReplacePixels(pixels) return nil } func main() { if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Game of Life (Ebiten Demo)"); err != nil { log.Fatal(err) } } </code></pre></div> </div></main> <footer><div class="container"> <p>© 2013 Hajime Hoshi</p> <p>Code is licensed under <a href="https://github.com/hajimehoshi/ebiten/blob/master/LICENSE">the Apache License 2.0</a>.</p> <p>The content of this page is licensed under <a href="https://creativecommons.org/licenses/by/4.0/">the Creative Commons Attribution 4.0 License</a>.</p> </div></footer> <script src="../scripts/highlight.pack.js"></script> <script>hljs.initHighlightingOnLoad();</script>