implemented basic menu and options structure, most stuff works

This commit is contained in:
2024-05-30 19:45:13 +02:00
parent 7ed0c83fcd
commit 538216ea4d
8 changed files with 228 additions and 19 deletions

View File

@@ -27,6 +27,8 @@ 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
StartWithMenu bool
// for internal profiling // for internal profiling
ProfileFile string ProfileFile string
@@ -209,3 +211,16 @@ func ParseCommandline() (*Config, error) {
func (config *Config) TogglePaused() { func (config *Config) TogglePaused() {
config.Paused = !config.Paused config.Paused = !config.Paused
} }
func (config *Config) ToggleDebugging() {
fmt.Println("DEBUG TOGGLED")
config.Debug = !config.Debug
}
func (config *Config) ToggleInvert() {
config.Invert = !config.Invert
}
func (config *Config) ToggleGridlines() {
config.NoGrid = !config.NoGrid
}

View File

@@ -24,6 +24,7 @@ func NewGame(config *Config, startscene SceneName) *Game {
game.CurrentScene = startscene game.CurrentScene = startscene
game.Scenes[Play] = NewPlayScene(game, config) game.Scenes[Play] = NewPlayScene(game, config)
game.Scenes[Menu] = NewMenuScene(game, config) game.Scenes[Menu] = NewMenuScene(game, config)
game.Scenes[Options] = NewOptionsScene(game, config)
// setup environment // setup environment
ebiten.SetWindowSize(game.ScreenWidth, game.ScreenHeight) ebiten.SetWindowSize(game.ScreenWidth, game.ScreenHeight)

11
main.go
View File

@@ -12,6 +12,11 @@ import (
) )
func main() { func main() {
dau := true
if len(os.Args) > 1 {
dau = false
}
config, err := ParseCommandline() config, err := ParseCommandline()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@@ -22,7 +27,11 @@ func main() {
os.Exit(0) os.Exit(0)
} }
game := NewGame(config, Play) start := Play
if dau {
start = Menu
}
game := NewGame(config, SceneName(start))
if config.ProfileFile != "" { if config.ProfileFile != "" {
// enable cpu profiling. Do NOT use q to stop the game but // enable cpu profiling. Do NOT use q to stop the game but

View File

@@ -2,6 +2,7 @@ package main
import ( import (
"image/color" "image/color"
"os"
"github.com/ebitenui/ebitenui" "github.com/ebitenui/ebitenui"
"github.com/ebitenui/ebitenui/widget" "github.com/ebitenui/ebitenui/widget"
@@ -16,6 +17,7 @@ type SceneMenu struct {
Whoami SceneName Whoami SceneName
Ui *ebitenui.UI Ui *ebitenui.UI
FontColor color.RGBA FontColor color.RGBA
First bool
} }
func NewMenuScene(game *Game, config *Config) Scene { func NewMenuScene(game *Game, config *Config) Scene {
@@ -64,28 +66,54 @@ func (scene *SceneMenu) Draw(screen *ebiten.Image) {
} }
func (scene *SceneMenu) Init() { func (scene *SceneMenu) Init() {
rowContainer := NewRowContainer() rowContainer := NewRowContainer("Main Menu")
pause := NewCheckbox("Pause", *FontRenderer.FontSmall, empty := NewMenuButton("Start with empty grid",
func(args *widget.CheckboxChangedEventArgs) { func(args *widget.ButtonClickedEventArgs) {
scene.Config.TogglePaused() scene.Config.Empty = true
scene.Config.Restart = true
scene.SetNext(Play)
}) })
copy := NewMenuButton("Save Copy as RLE", *FontRenderer.FontSmall, random := NewMenuButton("Start with random patterns",
func(args *widget.ButtonClickedEventArgs) {
scene.Config.Restart = true
scene.SetNext(Play)
})
copy := NewMenuButton("Save Copy as RLE",
func(args *widget.ButtonClickedEventArgs) { func(args *widget.ButtonClickedEventArgs) {
scene.Config.Markmode = true scene.Config.Markmode = true
scene.Config.Paused = true scene.Config.Paused = true
scene.SetNext(Play) scene.SetNext(Play)
}) })
label := widget.NewText( options := NewMenuButton("Options",
widget.TextOpts.Text("Menu", *FontRenderer.FontNormal, scene.FontColor), func(args *widget.ButtonClickedEventArgs) {
widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter), scene.SetNext(Options)
) })
rowContainer.AddChild(label) separator1 := NewSeparator()
rowContainer.AddChild(pause) separator2 := NewSeparator()
cancel := NewMenuButton("Close",
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Play)
})
quit := NewMenuButton("Quit",
func(args *widget.ButtonClickedEventArgs) {
os.Exit(0)
})
rowContainer.AddChild(empty)
rowContainer.AddChild(random)
rowContainer.AddChild(separator1)
rowContainer.AddChild(options)
rowContainer.AddChild(copy) rowContainer.AddChild(copy)
rowContainer.AddChild(separator2)
rowContainer.AddChild(cancel)
rowContainer.AddChild(quit)
scene.Ui = &ebitenui.UI{ scene.Ui = &ebitenui.UI{
Container: rowContainer.Container(), Container: rowContainer.Container(),

114
scene-options.go Normal file
View File

@@ -0,0 +1,114 @@
package main
import (
"image/color"
"github.com/ebitenui/ebitenui"
"github.com/ebitenui/ebitenui/widget"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
)
type SceneOptions struct {
Game *Game
Config *Config
Next SceneName
Whoami SceneName
Ui *ebitenui.UI
FontColor color.RGBA
}
func NewOptionsScene(game *Game, config *Config) Scene {
scene := &SceneOptions{
Whoami: Options,
Game: game,
Next: Options,
Config: config,
FontColor: color.RGBA{255, 30, 30, 0xff},
}
scene.Init()
return scene
}
func (scene *SceneOptions) GetNext() SceneName {
return scene.Next
}
func (scene *SceneOptions) ResetNext() {
scene.Next = scene.Whoami
}
func (scene *SceneOptions) SetNext(next SceneName) {
scene.Next = next
}
func (scene *SceneOptions) Clearscreen() bool {
return false
}
func (scene *SceneOptions) Update() error {
scene.Ui.Update()
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) || inpututil.IsKeyJustPressed(ebiten.KeyQ) {
scene.SetNext(Play)
}
return nil
}
func (scene *SceneOptions) Draw(screen *ebiten.Image) {
scene.Ui.Draw(screen)
}
func (scene *SceneOptions) Init() {
rowContainer := NewRowContainer("Options")
pause := NewCheckbox("Pause",
func(args *widget.CheckboxChangedEventArgs) {
scene.Config.TogglePaused()
})
debugging := NewCheckbox("Debugging",
func(args *widget.CheckboxChangedEventArgs) {
scene.Config.ToggleDebugging()
})
var debug int
if scene.Config.Debug {
debug = 1
}
debugging.SetState(
widget.WidgetState(debug),
)
invert := NewCheckbox("Invert",
func(args *widget.CheckboxChangedEventArgs) {
scene.Config.Invert = true
})
gridlines := NewCheckbox("Show grid lines",
func(args *widget.CheckboxChangedEventArgs) {
scene.Config.ToggleGridlines()
})
separator := NewSeparator()
cancel := NewMenuButton("Close",
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Menu)
})
rowContainer.AddChild(pause)
rowContainer.AddChild(debugging)
rowContainer.AddChild(invert)
rowContainer.AddChild(gridlines)
rowContainer.AddChild(separator)
rowContainer.AddChild(cancel)
scene.Ui = &ebitenui.UI{
Container: rowContainer.Container(),
}
}

View File

@@ -366,6 +366,12 @@ func (scene *ScenePlay) SaveRectRLE() {
} }
func (scene *ScenePlay) Update() error { func (scene *ScenePlay) Update() error {
if scene.Config.Restart {
scene.Config.Restart = false
scene.Init()
return nil
}
scene.CheckInput() scene.CheckInput()
scene.CheckDraggingInput() scene.CheckDraggingInput()
scene.CheckMarkInput() scene.CheckMarkInput()

View File

@@ -22,4 +22,5 @@ type Scene interface {
const ( const (
Menu = iota // main top level menu Menu = iota // main top level menu
Play // actual playing happens here Play // actual playing happens here
Options
) )

View File

@@ -5,12 +5,10 @@ import (
"github.com/ebitenui/ebitenui/image" "github.com/ebitenui/ebitenui/image"
"github.com/ebitenui/ebitenui/widget" "github.com/ebitenui/ebitenui/widget"
"golang.org/x/image/font"
) )
func NewMenuButton( func NewMenuButton(
text string, text string,
face font.Face,
action func(args *widget.ButtonClickedEventArgs)) *widget.Button { action func(args *widget.ButtonClickedEventArgs)) *widget.Button {
buttonImage, _ := LoadButtonImage() buttonImage, _ := LoadButtonImage()
@@ -27,7 +25,7 @@ func NewMenuButton(
widget.ButtonOpts.Image(buttonImage), widget.ButtonOpts.Image(buttonImage),
widget.ButtonOpts.Text(text, face, &widget.ButtonTextColor{ widget.ButtonOpts.Text(text, *FontRenderer.FontSmall, &widget.ButtonTextColor{
Idle: color.NRGBA{0xdf, 0xf4, 0xff, 0xff}, Idle: color.NRGBA{0xdf, 0xf4, 0xff, 0xff},
}), }),
@@ -44,7 +42,6 @@ func NewMenuButton(
func NewCheckbox( func NewCheckbox(
text string, text string,
face font.Face,
action func(args *widget.CheckboxChangedEventArgs)) *widget.LabeledCheckbox { action func(args *widget.CheckboxChangedEventArgs)) *widget.LabeledCheckbox {
checkboxImage, _ := LoadCheckboxImage() checkboxImage, _ := LoadCheckboxImage()
@@ -52,12 +49,14 @@ func NewCheckbox(
return widget.NewLabeledCheckbox( return widget.NewLabeledCheckbox(
widget.LabeledCheckboxOpts.CheckboxOpts( widget.LabeledCheckboxOpts.CheckboxOpts(
widget.CheckboxOpts.ButtonOpts(widget.ButtonOpts.Image(buttonImage)), widget.CheckboxOpts.ButtonOpts(
widget.ButtonOpts.Image(buttonImage),
),
widget.CheckboxOpts.Image(checkboxImage), widget.CheckboxOpts.Image(checkboxImage),
widget.CheckboxOpts.StateChangedHandler(action), widget.CheckboxOpts.StateChangedHandler(action),
), ),
widget.LabeledCheckboxOpts.LabelOpts( widget.LabeledCheckboxOpts.LabelOpts(
widget.LabelOpts.Text(text, face, widget.LabelOpts.Text(text, *FontRenderer.FontSmall,
&widget.LabelColor{ &widget.LabelColor{
Idle: color.NRGBA{0xdf, 0xf4, 0xff, 0xff}, Idle: color.NRGBA{0xdf, 0xf4, 0xff, 0xff},
}), }),
@@ -65,6 +64,31 @@ func NewCheckbox(
) )
} }
func NewSeparator() widget.PreferredSizeLocateableWidget {
c := widget.NewContainer(
widget.ContainerOpts.Layout(widget.NewRowLayout(
widget.RowLayoutOpts.Direction(widget.DirectionVertical),
widget.RowLayoutOpts.Padding(widget.Insets{
Top: 20,
Bottom: 20,
}))),
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
}
type RowContainer struct { type RowContainer struct {
Root *widget.Container Root *widget.Container
Row *widget.Container Row *widget.Container
@@ -79,11 +103,19 @@ func (container *RowContainer) Container() *widget.Container {
} }
// set arg to false if no background needed // set arg to false if no background needed
func NewRowContainer() *RowContainer { func NewRowContainer(title string) *RowContainer {
buttonImageHover := image.NewNineSlice(Assets["button-9slice3"], [3]int{3, 3, 3}, [3]int{3, 3, 3})
uiContainer := widget.NewContainer( uiContainer := widget.NewContainer(
widget.ContainerOpts.Layout(widget.NewAnchorLayout()), widget.ContainerOpts.Layout(widget.NewAnchorLayout()),
) )
titleLabel := widget.NewText(
widget.TextOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.RowLayoutData{
Stretch: true,
})),
widget.TextOpts.Text(title, *FontRenderer.FontNormal, color.NRGBA{0xdf, 0xf4, 0xff, 0xff}))
rowContainer := widget.NewContainer( rowContainer := widget.NewContainer(
widget.ContainerOpts.WidgetOpts( widget.ContainerOpts.WidgetOpts(
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{ widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
@@ -96,8 +128,11 @@ func NewRowContainer() *RowContainer {
widget.RowLayoutOpts.Padding(widget.NewInsetsSimple(20)), widget.RowLayoutOpts.Padding(widget.NewInsetsSimple(20)),
widget.RowLayoutOpts.Spacing(0), widget.RowLayoutOpts.Spacing(0),
)), )),
widget.ContainerOpts.BackgroundImage(buttonImageHover),
) )
rowContainer.AddChild(titleLabel)
uiContainer.AddChild(rowContainer) uiContainer.AddChild(rowContainer)
return &RowContainer{ return &RowContainer{