lots changes:

- renamed scene files
- fixed options back using scene.Prev
- fixed initial zooming (finally)
- fixed reset zoom (key r)
- fixed initial size, now works with state loading as well
This commit is contained in:
2024-06-03 17:44:17 +02:00
parent 6527dba219
commit 03e1101248
9 changed files with 94 additions and 48 deletions

13
TODO.md
View File

@@ -2,16 +2,3 @@
- changing options mid-game has no effect in most cases, even after a restart - changing options mid-game has no effect in most cases, even after a restart
- Statefile loading does not work correclty anymore. With larger grids
everything is empty. With square grids part of the grid is cut
off. Smaller grids load though
- Also when loading a state file, centering doesn't work anymore, I
think the geom calculation is overthrown by the parser func. So, put
this calc into its own func and always call. Or - as stated below -
put it onto camera.go and call from Init().
- Zoom 0 on reset only works when world<screen. otherwise zoom would
be negative So, on Init() memoize centered camera position or add a
Center() function to camera.go. Then on reset calculate the zoom
level so that the world fits into the screen.

View File

@@ -1,3 +1,5 @@
// this comes from the camera example but I enhanced it a little bit
package main package main
import ( import (
@@ -9,9 +11,12 @@ import (
) )
type Camera struct { type Camera struct {
ViewPort f64.Vec2 ViewPort f64.Vec2
Position f64.Vec2 Position f64.Vec2
ZoomFactor int ZoomFactor int
InitialZoomFactor int
InitialPosition f64.Vec2
ZoomOutFactor int
} }
func (c *Camera) String() string { func (c *Camera) String() string {
@@ -32,15 +37,17 @@ func (c *Camera) worldMatrix() ebiten.GeoM {
m := ebiten.GeoM{} m := ebiten.GeoM{}
m.Translate(-c.Position[0], -c.Position[1]) m.Translate(-c.Position[0], -c.Position[1])
viewportCenter := c.viewportCenter()
// We want to scale and rotate around center of image / screen // We want to scale and rotate around center of image / screen
m.Translate(-c.viewportCenter()[0], -c.viewportCenter()[1]) m.Translate(-viewportCenter[0], -viewportCenter[1])
m.Scale( m.Scale(
math.Pow(1.01, float64(c.ZoomFactor)), math.Pow(1.01, float64(c.ZoomFactor)),
math.Pow(1.01, float64(c.ZoomFactor)), math.Pow(1.01, float64(c.ZoomFactor)),
) )
m.Translate(c.viewportCenter()[0], c.viewportCenter()[1]) m.Translate(viewportCenter[0], viewportCenter[1])
return m return m
} }
@@ -61,8 +68,14 @@ func (c *Camera) ScreenToWorld(posX, posY int) (float64, float64) {
} }
} }
func (c *Camera) Reset() { func (c *Camera) Setup() {
c.Position[0] = 0 c.Position[0] = c.InitialPosition[0]
c.Position[1] = 0 c.Position[1] = c.InitialPosition[1]
c.ZoomFactor = 0 c.ZoomFactor = c.InitialZoomFactor
}
func (c *Camera) Reset() {
c.Position[0] = c.InitialPosition[0]
c.Position[1] = c.InitialPosition[1]
c.ZoomFactor = c.ZoomOutFactor
} }

View File

@@ -30,6 +30,7 @@ type Config struct {
Restart, RestartGrid, RestartCache bool Restart, RestartGrid, RestartCache bool
StartWithMenu bool StartWithMenu bool
Zoomfactor int Zoomfactor int
ZoomOutFactor int
InitialCamPos []float64 InitialCamPos []float64
DelayedStart bool // if true game, we wait. like pause but program induced DelayedStart bool // if true game, we wait. like pause but program induced
@@ -51,6 +52,40 @@ const (
DEFAULT_GEOM = "640x384" DEFAULT_GEOM = "640x384"
) )
func (config *Config) SetupCamera() {
config.Zoomfactor = DEFAULT_ZOOMFACTOR
// calculate the initial cam pos. It is negative if the total grid
// size is smaller than the screen in a centered position, but
// it's zero if it's equal or larger than the screen.
config.InitialCamPos = make([]float64, 2)
config.InitialCamPos[0] = float64(((config.ScreenWidth - (config.Width * config.Cellsize)) / 2) * -1)
if config.Width*config.Cellsize >= config.ScreenWidth {
// must be positive if world wider than screen
config.InitialCamPos[0] = math.Abs(config.InitialCamPos[0])
}
// for Y we need only positive (really?)
if config.Height*config.Cellsize > config.ScreenHeight {
config.InitialCamPos[1] = math.Abs(
float64(((config.ScreenHeight - (config.Height * config.Cellsize)) / 2)))
}
// Calculate zoom out factor, which shows 100% of the world. We
// need to reverse math.Pow(1.01, $zoomfactor) to get the correct
// percentage of the world to show. I.e: with a ScreenHeight of
// 384px and a world of 800px the factor to show 100% of the world
// is -75: math.Log(384/800) / math.Log(1.01). The 1.01 constant
// is being used in camera.go:worldMatrix().
// FIXME: determine if the diff is larger on width, then calc with
// widh instead of height
config.ZoomOutFactor = int(
math.Log(float64(config.ScreenHeight)/(float64(config.Height)*float64(config.Cellsize))) /
math.Log(1.01))
}
// parse given window geometry and adjust game settings according to it // parse given window geometry and adjust game settings according to it
func (config *Config) ParseGeom(geom string) error { func (config *Config) ParseGeom(geom string) error {
// force a geom // force a geom
@@ -73,22 +108,6 @@ func (config *Config) ParseGeom(geom string) error {
config.ScreenHeight = height config.ScreenHeight = height
config.Cellsize = DEFAULT_CELLSIZE config.Cellsize = DEFAULT_CELLSIZE
config.Zoomfactor = DEFAULT_ZOOMFACTOR
// calculate the initial cam pos. It is negative if the total grid
// size is smaller than the screen in a centered position, but
// it's zero if it's equal or larger than the screen.
config.InitialCamPos = make([]float64, 2)
config.InitialCamPos[0] = float64(((config.ScreenWidth - (config.Width * config.Cellsize)) / 2) * -1)
if config.Width*config.Cellsize >= config.ScreenWidth {
// must be positive if world wider than screen
config.InitialCamPos[0] = math.Abs(config.InitialCamPos[0])
}
if config.Height*config.Cellsize > config.ScreenHeight {
config.InitialCamPos[1] = math.Abs(float64(((config.ScreenHeight - (config.Height * config.Cellsize)) / 2)))
}
return nil return nil
} }
@@ -145,7 +164,6 @@ func (config *Config) ParseStatefile() error {
config.Width = grid.Width config.Width = grid.Width
config.Height = grid.Height config.Height = grid.Height
config.Cellsize = config.ScreenWidth / config.Width
config.StateGrid = grid config.StateGrid = grid
return nil return nil
@@ -225,6 +243,8 @@ func ParseCommandline() (*Config, error) {
config.Rule = ParseGameRule(rule) config.Rule = ParseGameRule(rule)
} }
config.SetupCamera()
//repr.Println(config) //repr.Println(config)
return &config, nil return &config, nil
} }

View File

@@ -53,6 +53,7 @@ func (game *Game) Update() error {
next := scene.GetNext() next := scene.GetNext()
if next != game.CurrentScene { if next != game.CurrentScene {
game.Scenes[next].SetPrevious(game.CurrentScene)
scene.ResetNext() scene.ResetNext()
game.CurrentScene = next game.CurrentScene = next
} }

View File

@@ -14,6 +14,7 @@ type SceneMenu struct {
Game *Game Game *Game
Config *Config Config *Config
Next SceneName Next SceneName
Prev SceneName
Whoami SceneName Whoami SceneName
Ui *ebitenui.UI Ui *ebitenui.UI
FontColor color.RGBA FontColor color.RGBA
@@ -38,6 +39,10 @@ func (scene *SceneMenu) GetNext() SceneName {
return scene.Next return scene.Next
} }
func (scene *SceneMenu) SetPrevious(prev SceneName) {
scene.Prev = prev
}
func (scene *SceneMenu) ResetNext() { func (scene *SceneMenu) ResetNext() {
scene.Next = scene.Whoami scene.Next = scene.Whoami
} }
@@ -99,9 +104,9 @@ func (scene *SceneMenu) Init() {
scene.SetNext(Options) scene.SetNext(Options)
}) })
separator1 := NewSeparator() separator1 := NewSeparator(3)
separator2 := NewSeparator() separator2 := NewSeparator(3)
separator3 := NewSeparator() separator3 := NewSeparator(10)
cancel := NewMenuButton("Back", cancel := NewMenuButton("Back",
func(args *widget.ButtonClickedEventArgs) { func(args *widget.ButtonClickedEventArgs) {

View File

@@ -13,6 +13,7 @@ type SceneOptions struct {
Game *Game Game *Game
Config *Config Config *Config
Next SceneName Next SceneName
Prev SceneName
Whoami SceneName Whoami SceneName
Ui *ebitenui.UI Ui *ebitenui.UI
FontColor color.RGBA FontColor color.RGBA
@@ -36,6 +37,10 @@ func (scene *SceneOptions) GetNext() SceneName {
return scene.Next return scene.Next
} }
func (scene *SceneOptions) SetPrevious(prev SceneName) {
scene.Prev = prev
}
func (scene *SceneOptions) ResetNext() { func (scene *SceneOptions) ResetNext() {
scene.Next = scene.Whoami scene.Next = scene.Whoami
} }
@@ -100,11 +105,11 @@ func (scene *SceneOptions) Init() {
}) })
scene.SetInitialValue(gridlines, scene.Config.ShowGrid) scene.SetInitialValue(gridlines, scene.Config.ShowGrid)
separator := NewSeparator() separator := NewSeparator(3)
cancel := NewMenuButton("Close", cancel := NewMenuButton("Close",
func(args *widget.ButtonClickedEventArgs) { func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Menu) scene.SetNext(scene.Prev)
}) })
rowContainer.AddChild(pause) rowContainer.AddChild(pause)

View File

@@ -26,6 +26,7 @@ type ScenePlay struct {
Game *Game Game *Game
Config *Config Config *Config
Next SceneName Next SceneName
Prev SceneName
Whoami SceneName Whoami SceneName
Clear bool Clear bool
@@ -73,6 +74,10 @@ func (scene *ScenePlay) GetNext() SceneName {
return scene.Next return scene.Next
} }
func (scene *ScenePlay) SetPrevious(prev SceneName) {
scene.Prev = prev
}
func (scene *ScenePlay) ResetNext() { func (scene *ScenePlay) ResetNext() {
scene.Next = scene.Whoami scene.Next = scene.Whoami
} }
@@ -166,6 +171,10 @@ func (scene *ScenePlay) CheckInput() {
scene.SetNext(Menu) scene.SetNext(Menu)
} }
if inpututil.IsKeyJustPressed(ebiten.KeyO) {
scene.SetNext(Options)
}
if inpututil.IsKeyJustPressed(ebiten.KeyC) { if inpututil.IsKeyJustPressed(ebiten.KeyC) {
fmt.Println("mark mode on") fmt.Println("mark mode on")
scene.Config.Markmode = true scene.Config.Markmode = true
@@ -625,6 +634,12 @@ func (scene *ScenePlay) Init() {
float64(scene.Config.ScreenWidth), float64(scene.Config.ScreenWidth),
float64(scene.Config.ScreenHeight), float64(scene.Config.ScreenHeight),
}, },
InitialZoomFactor: scene.Config.Zoomfactor,
InitialPosition: f64.Vec2{
scene.Config.InitialCamPos[0],
scene.Config.InitialCamPos[1],
},
ZoomOutFactor: scene.Config.ZoomOutFactor,
} }
scene.World = ebiten.NewImage( scene.World = ebiten.NewImage(
@@ -659,8 +674,7 @@ func (scene *ScenePlay) Init() {
scene.Camera.ZoomFactor = scene.Config.Zoomfactor scene.Camera.ZoomFactor = scene.Config.Zoomfactor
} }
scene.Camera.Position[0] = scene.Config.InitialCamPos[0] scene.Camera.Setup()
scene.Camera.Position[1] = scene.Config.InitialCamPos[1]
} }
// count the living neighbors of a cell // count the living neighbors of a cell

View File

@@ -13,6 +13,7 @@ type SceneName int
type Scene interface { type Scene interface {
SetNext(SceneName) SetNext(SceneName)
GetNext() SceneName GetNext() SceneName
SetPrevious(SceneName)
ResetNext() ResetNext()
Update() error Update() error
Draw(screen *ebiten.Image) Draw(screen *ebiten.Image)

View File

@@ -64,12 +64,12 @@ func NewCheckbox(
) )
} }
func NewSeparator() widget.PreferredSizeLocateableWidget { func NewSeparator(padding int) widget.PreferredSizeLocateableWidget {
c := widget.NewContainer( c := widget.NewContainer(
widget.ContainerOpts.Layout(widget.NewRowLayout( widget.ContainerOpts.Layout(widget.NewRowLayout(
widget.RowLayoutOpts.Direction(widget.DirectionVertical), widget.RowLayoutOpts.Direction(widget.DirectionVertical),
widget.RowLayoutOpts.Padding(widget.Insets{ widget.RowLayoutOpts.Padding(widget.Insets{
Top: 3, Top: padding,
Bottom: 0, Bottom: 0,
}))), }))),
widget.ContainerOpts.WidgetOpts( widget.ContainerOpts.WidgetOpts(