added workaround for clearscreen problem, fixed grid line option

This commit is contained in:
2024-05-31 14:19:30 +02:00
parent 73be8b93f4
commit 320c666af9
7 changed files with 90 additions and 39 deletions

View File

@@ -77,7 +77,8 @@ While it runs, there are a couple of commands you can use:
* page down: slow down * page down: slow down
* Mouse wheel: zoom in or out * Mouse wheel: zoom in or out
* move mouse while middle mouse button pressed: move canvas * move mouse while middle mouse button pressed: move canvas
* escape: reset to 1:1 zoom * r: reset to 1:1 zoom
* escape: open menu
* s: save game state to file (can be loaded with -l) * s: save game state to file (can be loaded with -l)
* c: enter copy mode. Mark a rectangle with the mouse, when you * c: enter copy mode. Mark a rectangle with the mouse, when you
release the mous button it is being saved to an RLE file release the mous button it is being saved to an RLE file

View File

@@ -1,2 +1,5 @@
- gird lines option has no effect
- add all other options like size etc - add all other options like size etc
- clear screen disabled leads to zoom artifacts when zooming out and
canvas is smaller than screen workaround: using screen copy in
game.Screen. Play copies screen to it and Menu draws it to screen
before drawing the menus

View File

@@ -19,7 +19,7 @@ type Config struct {
ScreenWidth, ScreenHeight int ScreenWidth, ScreenHeight int
TPG int // ticks per generation/game speed, 1==max TPG int // ticks per generation/game speed, 1==max
Debug, Empty, Invert, Paused, Markmode bool // game modi Debug, Empty, Invert, Paused, Markmode bool // game modi
ShowEvolution, NoGrid, RunOneStep bool // flags ShowEvolution, ShowGrid, RunOneStep bool // flags
Rule *Rule // which rule to use, default: B3/S23 Rule *Rule // which rule to use, default: B3/S23
RLE *rle.RLE // loaded GOL pattern from RLE file RLE *rle.RLE // loaded GOL pattern from RLE file
Statefile string // load game state from it if non-nil Statefile string // load game state from it if non-nil
@@ -27,8 +27,9 @@ type Config struct {
Wrap bool // wether wraparound mode is in place or not Wrap bool // wether wraparound mode is in place or not
ShowVersion bool ShowVersion bool
UseShader bool // to use a shader to render alife cells UseShader bool // to use a shader to render alife cells
Restart bool Restart, RestartGrid, RestartCache bool
StartWithMenu bool StartWithMenu bool
Zoomfactor int
// for internal profiling // for internal profiling
ProfileFile string ProfileFile string
@@ -40,6 +41,12 @@ const (
VERSION = "v0.0.7" VERSION = "v0.0.7"
Alive = 1 Alive = 1
Dead = 0 Dead = 0
DEFAULT_WIDTH = 600
DEFAULT_HEIGHT = 400
DEFAULT_CELLSIZE = 4
DEFAULT_ZOOMFACTOR = 150 // FIXME, doesn't work?
DEFAULT_GEOM = "640x384"
) )
// parse given window geometry and adjust game settings according to it // parse given window geometry and adjust game settings according to it
@@ -47,6 +54,7 @@ func (config *Config) ParseGeom(geom string) error {
if geom == "" { if geom == "" {
config.ScreenWidth = config.Cellsize * config.Width config.ScreenWidth = config.Cellsize * config.Width
config.ScreenHeight = config.Cellsize * config.Height config.ScreenHeight = config.Cellsize * config.Height
config.Zoomfactor = 0
return nil return nil
} }
@@ -66,16 +74,23 @@ func (config *Config) ParseGeom(geom string) error {
return errors.New("failed to parse height, expecting integer") return errors.New("failed to parse height, expecting integer")
} }
// adjust dimensions, account for grid width+height so that cells /*
// fit into window // adjust dimensions, account for grid width+height so that cells
config.ScreenWidth = width - (width % config.Width) // fit into window
config.ScreenHeight = height - (height % config.Height) config.ScreenWidth = width - (width % config.Width)
config.ScreenHeight = height - (height % config.Height)
if config.ScreenWidth == 0 || config.ScreenHeight == 0 { if config.ScreenWidth == 0 || config.ScreenHeight == 0 {
return errors.New("the number of requested cells don't fit into the requested window size") return errors.New("the number of requested cells don't fit into the requested window size")
} }
*/
config.Cellsize = config.ScreenWidth / config.Width config.ScreenWidth = width
config.ScreenHeight = height
//config.Cellsize = config.ScreenWidth / config.Width
config.Cellsize = DEFAULT_CELLSIZE
config.Zoomfactor = DEFAULT_ZOOMFACTOR
repr.Println(config) repr.Println(config)
return nil return nil
@@ -160,10 +175,10 @@ func ParseCommandline() (*Config, error) {
) )
// commandline params, most configure directly config flags // commandline params, most configure directly config flags
pflag.IntVarP(&config.Width, "width", "W", 40, "grid width in cells") pflag.IntVarP(&config.Width, "width", "W", DEFAULT_WIDTH, "grid width in cells")
pflag.IntVarP(&config.Height, "height", "H", 40, "grid height in cells") pflag.IntVarP(&config.Height, "height", "H", DEFAULT_HEIGHT, "grid height in cells")
pflag.IntVarP(&config.Cellsize, "cellsize", "c", 8, "cell size in pixels") pflag.IntVarP(&config.Cellsize, "cellsize", "c", 8, "cell size in pixels")
pflag.StringVarP(&geom, "geom", "g", "", "window geometry in WxH in pixels, overturns -c") pflag.StringVarP(&geom, "geom", "G", DEFAULT_GEOM, "window geometry in WxH in pixels, overturns -c")
pflag.IntVarP(&config.Density, "density", "D", 10, "density of random cells") pflag.IntVarP(&config.Density, "density", "D", 10, "density of random cells")
pflag.IntVarP(&config.TPG, "ticks-per-generation", "t", 10, pflag.IntVarP(&config.TPG, "ticks-per-generation", "t", 10,
@@ -176,7 +191,7 @@ func ParseCommandline() (*Config, error) {
pflag.BoolVarP(&config.ShowVersion, "version", "v", false, "show version") pflag.BoolVarP(&config.ShowVersion, "version", "v", false, "show version")
pflag.BoolVarP(&config.Paused, "paused", "p", false, "do not start simulation (use space to start)") pflag.BoolVarP(&config.Paused, "paused", "p", false, "do not start simulation (use space to start)")
pflag.BoolVarP(&config.Debug, "debug", "d", false, "show debug info") pflag.BoolVarP(&config.Debug, "debug", "d", false, "show debug info")
pflag.BoolVarP(&config.NoGrid, "nogrid", "n", false, "do not draw grid lines") pflag.BoolVarP(&config.ShowGrid, "show-grid", "g", true, "draw grid lines")
pflag.BoolVarP(&config.Empty, "empty", "e", false, "start with an empty screen") pflag.BoolVarP(&config.Empty, "empty", "e", false, "start with an empty screen")
pflag.BoolVarP(&config.Invert, "invert", "i", false, "invert colors (dead cell: black)") pflag.BoolVarP(&config.Invert, "invert", "i", false, "invert colors (dead cell: black)")
pflag.BoolVarP(&config.ShowEvolution, "show-evolution", "s", false, "show evolution traces") pflag.BoolVarP(&config.ShowEvolution, "show-evolution", "s", false, "show evolution traces")
@@ -219,8 +234,10 @@ func (config *Config) ToggleDebugging() {
func (config *Config) ToggleInvert() { func (config *Config) ToggleInvert() {
config.Invert = !config.Invert config.Invert = !config.Invert
config.RestartCache = true
} }
func (config *Config) ToggleGridlines() { func (config *Config) ToggleGridlines() {
config.NoGrid = !config.NoGrid config.ShowGrid = !config.ShowGrid
config.RestartCache = true
} }

View File

@@ -10,6 +10,7 @@ type Game struct {
CurrentScene SceneName CurrentScene SceneName
Config *Config Config *Config
Scale float32 Scale float32
Screen *ebiten.Image
} }
func NewGame(config *Config, startscene SceneName) *Game { func NewGame(config *Config, startscene SceneName) *Game {
@@ -30,7 +31,8 @@ func NewGame(config *Config, startscene SceneName) *Game {
ebiten.SetWindowSize(game.ScreenWidth, game.ScreenHeight) ebiten.SetWindowSize(game.ScreenWidth, game.ScreenHeight)
ebiten.SetWindowTitle("golsky - conway's game of life") ebiten.SetWindowTitle("golsky - conway's game of life")
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
ebiten.SetScreenClearedEveryFrame(false)
game.Screen = ebiten.NewImage(game.ScreenWidth, game.ScreenHeight)
return game return game
} }
@@ -48,6 +50,8 @@ func (game *Game) Update() error {
scene := game.GetCurrentScene() scene := game.GetCurrentScene()
scene.Update() scene.Update()
//ebiten.SetScreenClearedEveryFrame(scene.Clearscreen())
next := scene.GetNext() next := scene.GetNext()
if next != game.CurrentScene { if next != game.CurrentScene {
@@ -63,5 +67,6 @@ func (game *Game) Update() error {
func (game *Game) Draw(screen *ebiten.Image) { func (game *Game) Draw(screen *ebiten.Image) {
scene := game.GetCurrentScene() scene := game.GetCurrentScene()
ebiten.SetScreenClearedEveryFrame(scene.Clearscreen())
scene.Draw(screen) scene.Draw(screen)
} }

View File

@@ -62,6 +62,12 @@ func (scene *SceneMenu) Update() error {
} }
func (scene *SceneMenu) Draw(screen *ebiten.Image) { func (scene *SceneMenu) Draw(screen *ebiten.Image) {
op := &ebiten.DrawImageOptions{}
op.GeoM.Reset()
op.GeoM.Translate(0, 0)
screen.DrawImage(scene.Game.Screen, op)
scene.Ui.Draw(screen) scene.Ui.Draw(screen)
} }
@@ -95,13 +101,14 @@ func (scene *SceneMenu) Init() {
separator1 := NewSeparator() separator1 := NewSeparator()
separator2 := NewSeparator() separator2 := NewSeparator()
separator3 := NewSeparator()
cancel := NewMenuButton("Close", cancel := NewMenuButton("Close Window",
func(args *widget.ButtonClickedEventArgs) { func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Play) scene.SetNext(Play)
}) })
quit := NewMenuButton("Quit", quit := NewMenuButton("Exit Golsky",
func(args *widget.ButtonClickedEventArgs) { func(args *widget.ButtonClickedEventArgs) {
os.Exit(0) os.Exit(0)
}) })
@@ -113,6 +120,7 @@ func (scene *SceneMenu) Init() {
rowContainer.AddChild(copy) rowContainer.AddChild(copy)
rowContainer.AddChild(separator2) rowContainer.AddChild(separator2)
rowContainer.AddChild(cancel) rowContainer.AddChild(cancel)
rowContainer.AddChild(separator3)
rowContainer.AddChild(quit) rowContainer.AddChild(quit)
scene.Ui = &ebitenui.UI{ scene.Ui = &ebitenui.UI{

View File

@@ -63,6 +63,17 @@ func (scene *SceneOptions) Draw(screen *ebiten.Image) {
scene.Ui.Draw(screen) scene.Ui.Draw(screen)
} }
func (scene *SceneOptions) SetInitialValue(w *widget.LabeledCheckbox, value bool) {
var intval int
if value {
intval = 1
}
w.SetState(
widget.WidgetState(intval),
)
}
func (scene *SceneOptions) Init() { func (scene *SceneOptions) Init() {
rowContainer := NewRowContainer("Options") rowContainer := NewRowContainer("Options")
@@ -75,23 +86,19 @@ func (scene *SceneOptions) Init() {
func(args *widget.CheckboxChangedEventArgs) { func(args *widget.CheckboxChangedEventArgs) {
scene.Config.ToggleDebugging() scene.Config.ToggleDebugging()
}) })
var debug int scene.SetInitialValue(debugging, scene.Config.Debug)
if scene.Config.Debug {
debug = 1
}
debugging.SetState(
widget.WidgetState(debug),
)
invert := NewCheckbox("Invert", invert := NewCheckbox("Invert",
func(args *widget.CheckboxChangedEventArgs) { func(args *widget.CheckboxChangedEventArgs) {
scene.Config.Invert = true scene.Config.Invert = true
}) })
scene.SetInitialValue(invert, scene.Config.Invert)
gridlines := NewCheckbox("Show grid lines", gridlines := NewCheckbox("Show grid lines",
func(args *widget.CheckboxChangedEventArgs) { func(args *widget.CheckboxChangedEventArgs) {
scene.Config.ToggleGridlines() scene.Config.ToggleGridlines()
}) })
scene.SetInitialValue(gridlines, scene.Config.ShowGrid)
separator := NewSeparator() separator := NewSeparator()

View File

@@ -200,10 +200,6 @@ func (scene *ScenePlay) CheckInput() {
scene.SaveState() scene.SaveState()
} }
if inpututil.IsKeyJustPressed(ebiten.KeyR) {
scene.Reset()
}
if inpututil.IsKeyJustPressed(ebiten.KeyD) { if inpututil.IsKeyJustPressed(ebiten.KeyD) {
scene.Config.Debug = !scene.Config.Debug scene.Config.Debug = !scene.Config.Debug
} }
@@ -267,7 +263,7 @@ func (scene *ScenePlay) CheckDraggingInput() {
scene.Camera.ZoomFactor += (int(dy) * 5) scene.Camera.ZoomFactor += (int(dy) * 5)
} }
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { if inpututil.IsKeyJustPressed(ebiten.KeyR) {
scene.Camera.Reset() scene.Camera.Reset()
} }
@@ -372,6 +368,13 @@ func (scene *ScenePlay) Update() error {
return nil return nil
} }
if scene.Config.RestartCache {
scene.Config.RestartCache = false
scene.InitTiles()
scene.InitCache()
return nil
}
scene.CheckInput() scene.CheckInput()
scene.CheckDraggingInput() scene.CheckDraggingInput()
scene.CheckMarkInput() scene.CheckMarkInput()
@@ -390,8 +393,6 @@ func (scene *ScenePlay) ToggleCellOnCursorPos(alive int64) {
x := int(worldX) / scene.Config.Cellsize x := int(worldX) / scene.Config.Cellsize
y := int(worldY) / scene.Config.Cellsize y := int(worldY) / scene.Config.Cellsize
//fmt.Printf("cell at %d,%d\n", x, y)
if x > -1 && y > -1 { if x > -1 && y > -1 {
scene.Grids[scene.Index].Data[y][x] = alive scene.Grids[scene.Index].Data[y][x] = alive
scene.History.Data[y][x] = 1 scene.History.Data[y][x] = 1
@@ -451,6 +452,11 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) {
scene.Camera.Render(scene.World, screen) scene.Camera.Render(scene.World, screen)
scene.DrawDebug(screen) scene.DrawDebug(screen)
op.GeoM.Reset()
op.GeoM.Translate(0, 0)
scene.Game.Screen.DrawImage(screen, op)
} }
func (scene *ScenePlay) DrawMark(screen *ebiten.Image) { func (scene *ScenePlay) DrawMark(screen *ebiten.Image) {
@@ -477,9 +483,9 @@ func (scene *ScenePlay) DrawDebug(screen *ebiten.Image) {
} }
debug := fmt.Sprintf( debug := fmt.Sprintf(
"FPS: %0.2f, TPG: %d, Mem: %0.2fMB, Gen: %d, Scale: %.02f %s", "FPS: %0.2f, TPG: %d, Mem: %0.2fMB, Gen: %d, Scale: %.02f, Z: %d %s",
ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations, ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations,
scene.Game.Scale, paused) scene.Game.Scale, scene.Camera.ZoomFactor, paused)
FontRenderer.Renderer.SetSizePx(10 + int(scene.Game.Scale*10)) FontRenderer.Renderer.SetSizePx(10 + int(scene.Game.Scale*10))
FontRenderer.Renderer.SetTarget(screen) FontRenderer.Renderer.SetTarget(screen)
@@ -504,10 +510,10 @@ func (scene *ScenePlay) InitPattern() {
func (scene *ScenePlay) InitCache() { func (scene *ScenePlay) InitCache() {
op := &ebiten.DrawImageOptions{} op := &ebiten.DrawImageOptions{}
if scene.Config.NoGrid { if scene.Config.ShowGrid {
scene.Cache.Fill(scene.White)
} else {
scene.Cache.Fill(scene.Grey) scene.Cache.Fill(scene.Grey)
} else {
scene.Cache.Fill(scene.White)
} }
for y := 0; y < scene.Config.Height; y++ { for y := 0; y < scene.Config.Height; y++ {
@@ -621,6 +627,10 @@ func (scene *ScenePlay) Init() {
scene.TicksElapsed = 0 scene.TicksElapsed = 0
scene.LastCursorPos = make([]int, 2) scene.LastCursorPos = make([]int, 2)
if scene.Config.Zoomfactor < 0 || scene.Config.Zoomfactor > 0 {
scene.Camera.ZoomFactor = scene.Config.Zoomfactor
}
} }
// count the living neighbors of a cell // count the living neighbors of a cell