added options -p and -n, using images not draw rects anymore

This commit is contained in:
2024-05-22 14:06:33 +02:00
parent 39d9eeeba9
commit c3b6139e19
3 changed files with 82 additions and 34 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
gameoflife
bak

View File

@@ -15,7 +15,6 @@ You'll need the golang toolchain.
The game has a couple of commandline options:
```default
Usage of ./gameoflife:
-c, --cellsize int cell size in pixels (default 8)
-d, --debug show debug info
@@ -23,6 +22,8 @@ Usage of ./gameoflife:
-e, --empty start with an empty screen
-H, --height int grid height in cells (default 40)
-i, --invert invert colors (dead cell: black)
-n, --nogrid do not draw grid lines
-p, --paused do not start simulation (use space to start)
-r, --rule string game rule (default "B3/S23")
-s, --show-evolution show evolution tracks
-t, --tps int game speed in ticks per second (default 60)
@@ -35,6 +36,7 @@ While it runs, there are a couple of commands you can use:
* left mouse click: set a cell to alife
* right mouse click: set a cell to dead
* space: pause or resume the game
* while game is paused: press n to forward one step
* q: quit
* up arrow: speed up
* down arrow: slow down

91
main.go
View File

@@ -27,6 +27,10 @@ type Grid struct {
Data [][]int
}
type Images struct {
Black, White, Beige *ebiten.Image
}
type Game struct {
Grids []*Grid // 2 grids: one current, one next
History *Grid
@@ -36,8 +40,10 @@ type Game struct {
Generations int
Black, White, Grey, Beige color.RGBA
Speed int
Debug, Paused, Empty, Invert, ShowEvolution bool
Debug, Paused, Empty, Invert bool
ShowEvolution, NoGrid, RunOneStep bool
Rule *Rule
Tiles Images
}
func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
@@ -101,6 +107,10 @@ func (game *Game) UpdateCells() {
// global counter
game.Generations++
if game.RunOneStep {
game.RunOneStep = false
}
}
// a GOL rule
@@ -198,30 +208,24 @@ func (game *Game) CheckInput() {
ebiten.SetTPS(game.Speed)
}
}
if game.Paused {
if inpututil.IsKeyJustPressed(ebiten.KeyN) {
game.RunOneStep = true
}
}
}
func (game *Game) Update() error {
game.CheckInput()
if !game.Paused {
if !game.Paused || game.RunOneStep {
game.UpdateCells()
}
return nil
}
// fill a cell with the given color
func FillCell(screen *ebiten.Image, x, y, cellsize int, col color.RGBA) {
vector.DrawFilledRect(
screen,
float32(x*cellsize+1),
float32(y*cellsize+1),
float32(cellsize-1),
float32(cellsize-1),
col, false,
)
}
// set a cell to alive or dead
func ToggleCell(game *Game, alive int) {
xPX, yPX := ebiten.CursorPosition()
@@ -239,18 +243,27 @@ func (game *Game) Draw(screen *ebiten.Image) {
// we fill the whole screen with a background color, the cells
// themselfes will be 1px smaller as their nominal size, producing
// a nice grey grid with grid lines
op := &ebiten.DrawImageOptions{}
if game.NoGrid {
screen.Fill(game.White)
} else {
screen.Fill(game.Grey)
}
for y := 0; y < game.Height; y++ {
for x := 0; x < game.Width; x++ {
op.GeoM.Reset()
op.GeoM.Translate(float64(x*game.Cellsize), float64(y*game.Cellsize))
switch game.Grids[game.Index].Data[y][x] {
case 1:
FillCell(screen, x, y, game.Cellsize, game.Black)
screen.DrawImage(game.Tiles.Black, op)
case 0:
if game.History.Data[y][x] == 1 && game.ShowEvolution {
FillCell(screen, x, y, game.Cellsize, game.Beige)
screen.DrawImage(game.Tiles.Beige, op)
} else {
FillCell(screen, x, y, game.Cellsize, game.White)
screen.DrawImage(game.Tiles.White, op)
}
}
}
@@ -270,11 +283,7 @@ func (game *Game) Draw(screen *ebiten.Image) {
}
}
func (game *Game) Init() {
// setup the game
game.ScreenWidth = game.Cellsize * game.Width
game.ScreenHeight = game.Cellsize * game.Height
func (game *Game) InitGrid() {
grid := &Grid{Data: make([][]int, game.Height)}
gridb := &Grid{Data: make([][]int, game.Height)}
history := &Grid{Data: make([][]int, game.Height)}
@@ -299,7 +308,22 @@ func (game *Game) Init() {
}
game.History = history
}
// fill a cell with the given color
func FillCell(tile *ebiten.Image, cellsize int, col color.RGBA) {
vector.DrawFilledRect(
tile,
float32(1),
float32(1),
float32(cellsize-1),
float32(cellsize-1),
col, false,
)
}
// prepare tile images
func (game *Game) InitTiles() {
game.Black = color.RGBA{0, 0, 0, 0xff}
game.White = color.RGBA{200, 200, 200, 0xff}
game.Grey = color.RGBA{128, 128, 128, 0xff}
@@ -308,9 +332,28 @@ func (game *Game) Init() {
if game.Invert {
game.White = color.RGBA{0, 0, 0, 0xff}
game.Black = color.RGBA{200, 200, 200, 0xff}
game.Beige = color.RGBA{0x8b, 0x1a, 0x1a, 0xff}
//game.Beige = color.RGBA{0x8b, 0x1a, 0x1a, 0xff}
game.Beige = color.RGBA{0x30, 0x1c, 0x11, 0xff}
}
game.Tiles.Beige = ebiten.NewImage(game.Cellsize, game.Cellsize)
game.Tiles.Black = ebiten.NewImage(game.Cellsize, game.Cellsize)
game.Tiles.White = ebiten.NewImage(game.Cellsize, game.Cellsize)
cellsize := game.ScreenWidth / game.Cellsize
FillCell(game.Tiles.Beige, cellsize, game.Beige)
FillCell(game.Tiles.Black, cellsize, game.Black)
FillCell(game.Tiles.White, cellsize, game.White)
}
func (game *Game) Init() {
// setup the game
game.ScreenWidth = game.Cellsize * game.Width
game.ScreenHeight = game.Cellsize * game.Height
game.InitGrid()
game.InitTiles()
game.Index = 0
}
@@ -347,7 +390,9 @@ func main() {
pflag.IntVarP(&game.Density, "density", "D", 10, "density of random cells")
pflag.StringVarP(&rule, "rule", "r", "B3/S23", "game rule")
pflag.BoolVarP(&showversion, "version", "v", false, "show version")
pflag.BoolVarP(&game.Paused, "paused", "p", false, "do not start simulation (use space to start)")
pflag.BoolVarP(&game.Debug, "debug", "d", false, "show debug info")
pflag.BoolVarP(&game.NoGrid, "nogrid", "n", false, "do not draw grid lines")
pflag.BoolVarP(&game.Empty, "empty", "e", false, "start with an empty screen")
pflag.BoolVarP(&game.Invert, "invert", "i", false, "invert colors (dead cell: black)")
pflag.BoolVarP(&game.ShowEvolution, "show-evolution", "s", false, "show evolution tracks")