fixed clear screen problem, menus are now shown correctly. lots new

bugs though
This commit is contained in:
2024-06-01 20:22:28 +02:00
parent 9f1bdfd2af
commit 37fb0d637f
10 changed files with 115 additions and 83 deletions

24
TODO.md
View File

@@ -1,16 +1,18 @@
- add all other options like size etc
- Clear screen problem:
- it works when hitting the K key, immediately
- its being turned off correctly when entering menu and on when leaving it
- but regardless of the setting, after turning it off, the engine
seems to run a couple of ticks with the old setting before switching
scenes
- looks like a race condition
- obviously with K there are more loops before actually switching
scenes, which doesn't happen with ESC
- if grid lines is disabled, they appear anyway in the first frame (then disappear)
- changing options mid-game has no effect in most cases, even after a restart
- RLE file loading works but pattern is barely visible
- 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
- Same thing with RLE files: with smaller grid size, RLE file shows,
but with larger (or default) grid size, its invisible
- gridlines vanish if starting in menu mode, after starting a
game. They are there in all manual modes and on startup before
leaving the menu

View File

@@ -8,7 +8,6 @@ import (
"strconv"
"strings"
"github.com/alecthomas/repr"
"github.com/spf13/pflag"
"github.com/tlinden/golsky/rle"
)
@@ -30,6 +29,7 @@ type Config struct {
Restart, RestartGrid, RestartCache bool
StartWithMenu bool
Zoomfactor int
DelayedStart bool // if true game, we wait. like pause but program induced
// for internal profiling
ProfileFile string
@@ -38,25 +38,27 @@ type Config struct {
}
const (
VERSION = "v0.0.7"
VERSION = "v0.0.8"
Alive = 1
Dead = 0
DEFAULT_WIDTH = 600
DEFAULT_HEIGHT = 400
DEFAULT_CELLSIZE = 4
DEFAULT_ZOOMFACTOR = 150 // FIXME, doesn't work?
DEFAULT_GEOM = "640x384"
DEFAULT_GRID_WIDTH = 600
DEFAULT_GRID_HEIGHT = 400
DEFAULT_CELLSIZE = 4
DEFAULT_ZOOMFACTOR = 150
DEFAULT_GEOM = "640x384"
)
// parse given window geometry and adjust game settings according to it
func (config *Config) ParseGeom(geom string) error {
if geom == "" {
config.ScreenWidth = config.Cellsize * config.Width
config.ScreenHeight = config.Cellsize * config.Height
config.Zoomfactor = 0
return nil
}
// if geom == "" {
// // config.ScreenWidth = config.Cellsize * config.Width
// // config.ScreenHeight = config.Cellsize * config.Height
// config.ScreenWidth = DEFAULT_WIDTH
// config.ScreenHeight = DEFAULT_HEIGHT
// config.Zoomfactor = 0
// return nil
// }
// force a geom
geometry := strings.Split(geom, "x")
@@ -80,19 +82,15 @@ func (config *Config) ParseGeom(geom string) error {
config.ScreenWidth = width - (width % config.Width)
config.ScreenHeight = height - (height % config.Height)
if config.ScreenWidth == 0 || config.ScreenHeight == 0 {
return errors.New("the number of requested cells don't fit into the requested window size")
}
*/
config.ScreenWidth = width
config.ScreenHeight = height
//config.Cellsize = config.ScreenWidth / config.Width
config.Cellsize = DEFAULT_CELLSIZE
config.Zoomfactor = DEFAULT_ZOOMFACTOR
repr.Println(config)
return nil
}
@@ -121,6 +119,9 @@ func (config *Config) ParseRLE(rlefile string) error {
config.Cellsize = config.ScreenWidth / config.Width
}
fmt.Printf("width: %d, screenwidth: %d, rlewidth: %d, cellsize: %d\n",
config.Width, config.ScreenWidth, config.RLE.Width, config.Cellsize)
// RLE needs an empty grid
config.Empty = true
@@ -133,7 +134,7 @@ func (config *Config) ParseRLE(rlefile string) error {
}
// parse a state file, if given, and adjust game settings accordingly
func (config *Config) ParseStatefile(statefile string) error {
func (config *Config) ParseStatefile() error {
if config.Statefile == "" {
return nil
}
@@ -175,8 +176,8 @@ func ParseCommandline() (*Config, error) {
)
// commandline params, most configure directly config flags
pflag.IntVarP(&config.Width, "width", "W", DEFAULT_WIDTH, "grid width in cells")
pflag.IntVarP(&config.Height, "height", "H", DEFAULT_HEIGHT, "grid height in cells")
pflag.IntVarP(&config.Width, "width", "W", DEFAULT_GRID_WIDTH, "grid width in cells")
pflag.IntVarP(&config.Height, "height", "H", DEFAULT_GRID_HEIGHT, "grid height in cells")
pflag.IntVarP(&config.Cellsize, "cellsize", "c", 8, "cell size in pixels")
pflag.StringVarP(&geom, "geom", "G", DEFAULT_GEOM, "window geometry in WxH in pixels, overturns -c")
@@ -214,12 +215,18 @@ func ParseCommandline() (*Config, error) {
return nil, err
}
err = config.ParseStatefile()
if err != nil {
return nil, err
}
// load rule from commandline when no rule came from RLE file,
// default is B3/S23, aka conways game of life
if config.Rule == nil {
config.Rule = ParseGameRule(rule)
}
//repr.Println(config)
return &config, nil
}

35
game.go
View File

@@ -1,8 +1,6 @@
package main
import (
"fmt"
"github.com/hajimehoshi/ebiten/v2"
)
@@ -53,26 +51,29 @@ func (game *Game) Update() error {
scene := game.GetCurrentScene()
scene.Update()
fmt.Printf("Clear Screen: %t\n", ebiten.IsScreenClearedEveryFrame())
next := scene.GetNext()
if next != game.CurrentScene {
scene.ResetNext()
game.CurrentScene = next
}
return nil
}
func (game *Game) Draw(screen *ebiten.Image) {
var nextscene Scene
// first draw primary scene[s], although there are only 1
for current, scene := range game.Scenes {
if scene.IsPrimary() {
// primary scenes always draw
scene.Draw(screen)
if current == game.CurrentScene {
// avoid to redraw it in the next step
return
}
}
}
scene := game.GetCurrentScene()
next := scene.GetNext()
if next != game.CurrentScene {
scene.ResetNext()
game.CurrentScene = next
nextscene = game.GetCurrentScene()
ebiten.SetScreenClearedEveryFrame(nextscene.Clearscreen())
}
scene.Draw(screen)
if nextscene != nil {
nextscene.Draw(screen)
}
}

15
grid.go
View File

@@ -78,6 +78,19 @@ func (grid *Grid) FillRandom() {
}
}
func (grid *Grid) Dump() {
for y := 0; y < grid.Height; y++ {
for x := 0; x < grid.Width; x++ {
if grid.Data[y][x] == 1 {
fmt.Print("XX")
} else {
fmt.Print(" ")
}
}
fmt.Println()
}
}
// initialize using a given RLE pattern
func (grid *Grid) LoadRLE(pattern *rle.RLE) {
if pattern != nil {
@@ -95,6 +108,8 @@ func (grid *Grid) LoadRLE(pattern *rle.RLE) {
}
}
}
//grid.Dump()
}
}

View File

@@ -12,11 +12,12 @@ import (
)
func main() {
dau := true
var directstart bool
if len(os.Args) > 1 {
dau = false
directstart = true
}
config, err := ParseCommandline()
if err != nil {
log.Fatal(err)
@@ -28,8 +29,9 @@ func main() {
}
start := Play
if dau {
if !directstart {
start = Menu
config.DelayedStart = true
}
game := NewGame(config, SceneName(start))

View File

@@ -46,14 +46,11 @@ func (scene *SceneMenu) SetNext(next SceneName) {
scene.Next = next
}
func (scene *SceneMenu) Clearscreen() bool {
return false
}
func (scene *SceneMenu) Update() error {
scene.Ui.Update()
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) || inpututil.IsKeyJustPressed(ebiten.KeyQ) {
scene.Config.DelayedStart = false
scene.Leave()
}
@@ -61,6 +58,10 @@ func (scene *SceneMenu) Update() error {
}
func (scene *SceneMenu) IsPrimary() bool {
return false
}
func (scene *SceneMenu) Draw(screen *ebiten.Image) {
scene.Ui.Draw(screen)
}
@@ -102,7 +103,7 @@ func (scene *SceneMenu) Init() {
separator2 := NewSeparator()
separator3 := NewSeparator()
cancel := NewMenuButton("Close Window",
cancel := NewMenuButton("Back",
func(args *widget.ButtonClickedEventArgs) {
scene.Leave()
})

View File

@@ -44,7 +44,7 @@ func (scene *SceneOptions) SetNext(next SceneName) {
scene.Next = next
}
func (scene *SceneOptions) Clearscreen() bool {
func (scene *SceneOptions) IsPrimary() bool {
return false
}

View File

@@ -61,6 +61,10 @@ func NewPlayScene(game *Game, config *Config) Scene {
return scene
}
func (scene *ScenePlay) IsPrimary() bool {
return true
}
func (scene *ScenePlay) GetNext() SceneName {
return scene.Next
}
@@ -73,10 +77,6 @@ func (scene *ScenePlay) SetNext(next SceneName) {
scene.Next = next
}
func (scene *ScenePlay) Clearscreen() bool {
return true
}
func (scene *ScenePlay) CheckRule(state int64, neighbors int64) int64 {
var nextstate int64
@@ -366,7 +366,8 @@ func (scene *ScenePlay) SaveRectRLE() {
func (scene *ScenePlay) Update() error {
if scene.Config.Restart {
scene.Config.Restart = false
scene.Init()
scene.InitGrid(nil)
scene.InitCache()
return nil
}
@@ -485,9 +486,11 @@ func (scene *ScenePlay) DrawDebug(screen *ebiten.Image) {
}
debug := fmt.Sprintf(
"FPS: %0.2f, TPG: %d, Mem: %0.2fMB, Gen: %d, Scale: %.02f, Z: %d, Clear: %t %s",
"FPS: %0.2f, TPG: %d, Mem: %0.2fMB, Gen: %d, Scale: %.02f, Z: %d, Cam: %.02f,%.02f %s",
ebiten.ActualTPS(), scene.TPG, GetMem(), scene.Generations,
scene.Game.Scale, scene.Camera.ZoomFactor, ebiten.IsScreenClearedEveryFrame(), paused)
scene.Game.Scale, scene.Camera.ZoomFactor,
scene.Camera.Position[0], scene.Camera.Position[1],
paused)
FontRenderer.Renderer.SetSizePx(10 + int(scene.Game.Scale*10))
FontRenderer.Renderer.SetTarget(screen)
@@ -549,6 +552,7 @@ func (scene *ScenePlay) InitGrid(grid *Grid) {
gridb := NewGrid(scene.Config.Width, scene.Config.Height, scene.Config.Density, scene.Config.Empty)
history := NewGrid(scene.Config.Width, scene.Config.Height, scene.Config.Density, scene.Config.Empty)
// startup is delayed until user has selected options
grida.FillRandom()
grida.Copy(history)
@@ -607,7 +611,6 @@ func (scene *ScenePlay) Init() {
if scene.Config.StateGrid != nil {
grid = scene.Config.StateGrid
}
scene.Camera = Camera{
@@ -617,12 +620,24 @@ func (scene *ScenePlay) Init() {
},
}
scene.World = ebiten.NewImage(scene.Config.ScreenWidth, scene.Config.ScreenHeight)
scene.World = ebiten.NewImage(
scene.Config.Width*scene.Config.Cellsize,
scene.Config.Height*scene.Config.Cellsize,
)
scene.Cache = ebiten.NewImage(scene.Config.ScreenWidth, scene.Config.ScreenHeight)
scene.InitTiles()
scene.InitCache()
scene.InitGrid(grid)
if scene.Config.DelayedStart && !scene.Config.Empty {
scene.Config.Empty = true
scene.InitGrid(grid)
scene.Config.Empty = false
} else {
scene.InitGrid(grid)
}
scene.InitPattern()
scene.Index = 0

View File

@@ -14,9 +14,9 @@ type Scene interface {
SetNext(SceneName)
GetNext() SceneName
ResetNext()
Clearscreen() bool
Update() error
Draw(screen *ebiten.Image)
IsPrimary() bool // if true, this scene will be always drawn
}
const (

View File

@@ -69,23 +69,12 @@ func NewSeparator() widget.PreferredSizeLocateableWidget {
widget.ContainerOpts.Layout(widget.NewRowLayout(
widget.RowLayoutOpts.Direction(widget.DirectionVertical),
widget.RowLayoutOpts.Padding(widget.Insets{
Top: 20,
Bottom: 20,
Top: 3,
Bottom: 0,
}))),
widget.ContainerOpts.WidgetOpts(
widget.WidgetOpts.LayoutData(
widget.RowLayoutData{Stretch: true})))
c.AddChild(widget.NewGraphic(
widget.GraphicOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.RowLayoutData{
Stretch: true,
MaxHeight: 2,
})),
widget.GraphicOpts.ImageNineSlice(
image.NewNineSliceColor(
color.NRGBA{0xdf, 0xf4, 0xff, 0xff})),
))
return c
}
@@ -125,7 +114,7 @@ func NewRowContainer(title string) *RowContainer {
),
widget.ContainerOpts.Layout(widget.NewRowLayout(
widget.RowLayoutOpts.Direction(widget.DirectionVertical),
widget.RowLayoutOpts.Padding(widget.NewInsetsSimple(20)),
widget.RowLayoutOpts.Padding(widget.NewInsetsSimple(8)),
widget.RowLayoutOpts.Spacing(0),
)),
widget.ContainerOpts.BackgroundImage(buttonImageHover),