From 1ec4b9e257cb2e66a332bd49ff82bf5c81629fcc Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Thu, 30 May 2024 10:11:44 +0200 Subject: [PATCH] refactored grid stuff, fixed font size calculation --- game.go | 13 ++++++----- grid.go | 52 ++++++++++++++++++++++++++++++++--------- scene-play.go | 65 ++++++++++++++++++++++++--------------------------- 3 files changed, 78 insertions(+), 52 deletions(-) diff --git a/game.go b/game.go index 6df9bea..4bd7842 100644 --- a/game.go +++ b/game.go @@ -5,11 +5,11 @@ import ( ) type Game struct { - ScreenWidth, ScreenHeight, Cellsize int - Scenes map[SceneName]Scene - CurrentScene SceneName - Config *Config - Scale int + ScreenWidth, ScreenHeight, ReadlWidth, Cellsize int + Scenes map[SceneName]Scene + CurrentScene SceneName + Config *Config + Scale float32 } func NewGame(config *Config, startscene SceneName) *Game { @@ -37,7 +37,8 @@ func (game *Game) GetCurrentScene() Scene { } func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) { - game.Scale = outsideWidth / 100 + game.ReadlWidth = outsideWidth + game.Scale = float32(game.ScreenWidth) / float32(outsideWidth) return game.ScreenWidth, game.ScreenHeight } diff --git a/grid.go b/grid.go index 5d3eede..b1a080a 100644 --- a/grid.go +++ b/grid.go @@ -9,6 +9,8 @@ import ( "strconv" "strings" "time" + + "github.com/tlinden/golsky/rle" ) type Grid struct { @@ -34,6 +36,7 @@ func NewGrid(width, height, density int, empty bool) *Grid { return grid } +// Create a 1:1 copy func (grid *Grid) Clone() *Grid { newgrid := &Grid{} @@ -44,6 +47,7 @@ func (grid *Grid) Clone() *Grid { return newgrid } +// delete all contents func (grid *Grid) Clear() { for y := range grid.Data { for x := range grid.Data[y] { @@ -52,6 +56,7 @@ func (grid *Grid) Clear() { } } +// initialize with random life cells using the given density func (grid *Grid) FillRandom(game *ScenePlay) { if !grid.Empty { for y := range grid.Data { @@ -64,16 +69,28 @@ func (grid *Grid) FillRandom(game *ScenePlay) { } } -func GetFilename(generations int64) string { - now := time.Now() - return fmt.Sprintf("dump-%s-%d.gol", now.Format("20060102150405"), generations) -} - -func GetFilenameRLE(generations int64) string { - now := time.Now() - return fmt.Sprintf("rect-%s-%d.rle", now.Format("20060102150405"), generations) +// initialize using a given RLE pattern +func (grid *Grid) LoadRLE(pattern *rle.RLE) { + if pattern != nil { + startX := (grid.Width / 2) - (pattern.Width / 2) + startY := (grid.Height / 2) - (pattern.Height / 2) + var y, x int + + for rowIndex, patternRow := range pattern.Pattern { + for colIndex := range patternRow { + if pattern.Pattern[rowIndex][colIndex] > 0 { + x = colIndex + startX + y = rowIndex + startY + + grid.Data[y][x] = 1 + } + } + } + } } +// save the contents of the whole grid as a simple mcell alike +// file. One line per row, 0 for dead and 1 for life cell. func (grid *Grid) SaveState(filename string) error { file, err := os.Create(filename) if err != nil { @@ -81,7 +98,7 @@ func (grid *Grid) SaveState(filename string) error { } defer file.Close() - for y, _ := range grid.Data { + for y := range grid.Data { for _, cell := range grid.Data[y] { _, err := file.WriteString(strconv.FormatInt(cell, 10)) if err != nil { @@ -94,6 +111,7 @@ func (grid *Grid) SaveState(filename string) error { return nil } +// the reverse of the above, load a mcell file func LoadState(filename string) (*Grid, error) { fd, err := os.Open(filename) if err != nil { @@ -139,8 +157,9 @@ func LoadState(filename string) (*Grid, error) { } if explen != length { - return nil, fmt.Errorf(fmt.Sprintf("all rows must be in the same length, got: %d, expected: %d", - length, explen)) + return nil, fmt.Errorf( + fmt.Sprintf("all rows must be in the same length, got: %d, expected: %d", + length, explen)) } rows++ @@ -151,3 +170,14 @@ func LoadState(filename string) (*Grid, error) { return grid, nil } + +// generate filenames for dumps +func GetFilename(generations int64) string { + now := time.Now() + return fmt.Sprintf("dump-%s-%d.gol", now.Format("20060102150405"), generations) +} + +func GetFilenameRLE(generations int64) string { + now := time.Now() + return fmt.Sprintf("rect-%s-%d.rle", now.Format("20060102150405"), generations) +} diff --git a/scene-play.go b/scene-play.go index 72cf16e..6bd6002 100644 --- a/scene-play.go +++ b/scene-play.go @@ -26,7 +26,7 @@ type ScenePlay struct { Whoami SceneName Grids []*Grid // 2 grids: one current, one next - History *Grid // holds state of past dead cells for evolution tracks + History *Grid // holds state of past dead cells for evolution traces Index int // points to current grid Generations int64 // Stats Black, White, Grey, Old color.RGBA @@ -125,7 +125,7 @@ func (scene *ScenePlay) UpdateCells() { // set history to current generation so we can infer the // age of the cell's state during rendering and use it to - // deduce the color to use if evolution tracking is enabled + // deduce the color to use if evolution tracing is enabled if state != nextstate { scene.History.Data[y][x] = scene.Generations } @@ -401,22 +401,28 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { op.GeoM.Translate(0, 0) scene.World.DrawImage(scene.Cache, op) + var age int64 + for y := 0; y < scene.Config.Height; y++ { for x := 0; x < scene.Config.Width; x++ { op.GeoM.Reset() - op.GeoM.Translate(float64(x*scene.Config.Cellsize), float64(y*scene.Config.Cellsize)) + op.GeoM.Translate( + float64(x*scene.Config.Cellsize), + float64(y*scene.Config.Cellsize), + ) - age := scene.Generations - scene.History.Data[y][x] + age = scene.Generations - scene.History.Data[y][x] switch scene.Grids[scene.Index].Data[y][x] { - case 1: + case Alive: if age > 50 && scene.Config.ShowEvolution { scene.World.DrawImage(scene.Tiles.Old, op) } else { scene.World.DrawImage(scene.Tiles.Black, op) } - case 0: + case Dead: + // only draw dead cells in case evolution trace is enabled if scene.History.Data[y][x] > 1 && scene.Config.ShowEvolution { switch { case age < 10: @@ -433,15 +439,20 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { } } + scene.DrawMark(scene.World) + + scene.Camera.Render(scene.World, screen) + + scene.DrawDebug(screen) +} + +func (scene *ScenePlay) DrawMark(screen *ebiten.Image) { if scene.Markmode && scene.MarkTaken { x := float32(scene.Mark.X * scene.Config.Cellsize) y := float32(scene.Mark.Y * scene.Config.Cellsize) w := float32((scene.Point.X - scene.Mark.X) * scene.Config.Cellsize) h := float32((scene.Point.Y - scene.Mark.Y) * scene.Config.Cellsize) - // fmt.Printf("%d,%d=>%0.0f,%0.0f to %d,%d=>%0.0f,%0.0f\n", - // scene.Mark.X, scene.Mark.Y, x, y, scene.Point.X, scene.Point.Y, w, h) - vector.StrokeRect( scene.World, x+1, y+1, @@ -449,20 +460,21 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { 1.0, scene.Old, false, ) } +} - scene.Camera.Render(scene.World, screen) - +func (scene *ScenePlay) DrawDebug(screen *ebiten.Image) { if scene.Config.Debug { - paused := "" if scene.Paused { paused = "-- paused --" } - debug := fmt.Sprintf("FPS: %0.2f, TPG: %d, Mem: %0.2f MB, Generations: %d %s", - ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations, paused) + debug := fmt.Sprintf( + "FPS: %0.2f, TPG: %d, Mem: %0.2fMB, Gen: %d, Scale: %.02f %s", + ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations, + scene.Game.Scale, paused) - FontRenderer.Renderer.SetSizePx(10 + scene.Game.Scale/2) + FontRenderer.Renderer.SetSizePx(10 + int(scene.Game.Scale*10)) FontRenderer.Renderer.SetTarget(screen) FontRenderer.Renderer.SetColor(scene.Black) @@ -471,31 +483,14 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { FontRenderer.Renderer.SetColor(scene.Old) FontRenderer.Renderer.Draw(debug, 30, 30) - //ebitenutil.DebugPrint(screen, debug) - fmt.Println(debug, scene.Game.Scale) + fmt.Println(debug) } } -// FIXME: move these into Grid // load a pre-computed pattern from RLE file func (scene *ScenePlay) InitPattern() { - if scene.Config.RLE != nil { - startX := (scene.Config.Width / 2) - (scene.Config.RLE.Width / 2) - startY := (scene.Config.Height / 2) - (scene.Config.RLE.Height / 2) - var y, x int - - for rowIndex, patternRow := range scene.Config.RLE.Pattern { - for colIndex := range patternRow { - if scene.Config.RLE.Pattern[rowIndex][colIndex] > 0 { - x = colIndex + startX - y = rowIndex + startY - - scene.History.Data[y][x] = 1 - scene.Grids[0].Data[y][x] = 1 - } - } - } - } + scene.Grids[0].LoadRLE(scene.Config.RLE) + scene.History.LoadRLE(scene.Config.RLE) } func (scene *ScenePlay) InitCache() {