diff --git a/main.go b/main.go index 4fc4807..abcfd31 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,6 @@ import ( "log" "os" "runtime/pprof" - "time" _ "net/http/pprof" @@ -26,7 +25,8 @@ func main() { game := NewGame(config, Play) if config.ProfileFile != "" { - // enable cpu profiling and use fake game loop + // enable cpu profiling. Do NOT use q to stop the game but + // close the window to get a profile fd, err := os.Create(config.ProfileFile) if err != nil { log.Fatal(err) @@ -35,13 +35,6 @@ func main() { pprof.StartCPUProfile(fd) defer pprof.StopCPUProfile() - - Ebitfake(game) - - pprof.StopCPUProfile() - fd.Close() - - os.Exit(0) } // main loop @@ -49,32 +42,3 @@ func main() { log.Fatal(err) } } - -// fake game loop, required to be able to profile the program using -// pprof. Otherwise any kind of program exit leads to an empty profile -// file. -func Ebitfake(game *Game) { - screen := ebiten.NewImage(game.ScreenWidth, game.ScreenHeight) - - var loops int64 - - for { - err := game.Update() - if err != nil { - log.Fatal(err) - } - - if game.Config.ProfileDraw { - game.Draw(screen) - } - - fmt.Print(".") - time.Sleep(16 * time.Millisecond) // around 60 TPS - - if loops >= game.Config.ProfileMaxLoops { - break - } - - loops++ - } -} diff --git a/scene-play.go b/scene-play.go index 1034170..cea0f8a 100644 --- a/scene-play.go +++ b/scene-play.go @@ -35,7 +35,7 @@ type ScenePlay struct { TicksElapsed int // tick counter for game speed Tiles Images // pre-computed tiles for dead and alife cells Camera Camera // for zoom+move - World *ebiten.Image // actual image we render to + World, Cache *ebiten.Image // actual image we render to WheelTurned bool // when user turns wheel multiple times, zoom faster Dragging bool // middle mouse is pressed, move canvas LastCursorPos []int // used to check if the user is dragging @@ -411,11 +411,8 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { // a nice grey grid with grid lines op := &ebiten.DrawImageOptions{} - if scene.Config.NoGrid { - scene.World.Fill(scene.White) - } else { - scene.World.Fill(scene.Grey) - } + op.GeoM.Translate(0, 0) + scene.World.DrawImage(scene.Cache, op) for y := 0; y < scene.Config.Height; y++ { for x := 0; x < scene.Config.Width; x++ { @@ -443,8 +440,6 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { default: scene.World.DrawImage(scene.Tiles.Age4, op) } - } else { - scene.World.DrawImage(scene.Tiles.White, op) } } } @@ -475,11 +470,11 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) { paused = "-- paused --" } - ebitenutil.DebugPrint( - screen, - 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.2f MB, Generations: %d %s", + ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations, paused) + + ebitenutil.DebugPrint(screen, debug) + fmt.Println(debug) } } @@ -505,6 +500,25 @@ func (scene *ScenePlay) InitPattern() { } } +func (scene *ScenePlay) InitCache() { + op := &ebiten.DrawImageOptions{} + + if scene.Config.NoGrid { + scene.Cache.Fill(scene.White) + } else { + scene.Cache.Fill(scene.Grey) + } + + 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)) + + scene.Cache.DrawImage(scene.Tiles.White, op) + } + } +} + func (scene *ScenePlay) InitGrid(grid *Grid) { if grid != nil { // use pre-loaded grid @@ -599,10 +613,12 @@ func (scene *ScenePlay) Init() { } scene.World = ebiten.NewImage(scene.Config.ScreenWidth, scene.Config.ScreenHeight) + scene.Cache = ebiten.NewImage(scene.Config.ScreenWidth, scene.Config.ScreenHeight) + scene.InitTiles() + scene.InitCache() scene.InitGrid(grid) scene.InitPattern() - scene.InitTiles() scene.Index = 0 scene.TicksElapsed = 0