mirror of
https://codeberg.org/scip/golsky.git
synced 2025-12-16 20:20:57 +01:00
added workaround for clearscreen problem, fixed grid line option
This commit is contained in:
@@ -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
|
||||||
|
|||||||
5
TODO.md
5
TODO.md
@@ -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
|
||||||
|
|||||||
47
config.go
47
config.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
7
game.go
7
game.go
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user