openquell/game/select_scene.go

164 lines
4.8 KiB
Go

package game
import (
"fmt"
"image/color"
"log/slog"
"openquell/assets"
"openquell/gameui"
"openquell/observers"
"github.com/ebitenui/ebitenui"
"github.com/ebitenui/ebitenui/image"
"github.com/ebitenui/ebitenui/widget"
"github.com/hajimehoshi/ebiten/v2"
)
type SelectScene struct {
Game *Game
Next SceneName
Whoami SceneName
UseCache bool
Ui *ebitenui.UI
SelectedLevel int
}
func NewSelectScene(game *Game) Scene {
scene := &SelectScene{Whoami: Select, Game: game, Next: Select}
scene.SetupUI()
return scene
}
func (scene *SelectScene) SetLevel(level int) {}
func (scene *SelectScene) GetNext() SceneName {
return scene.Next
}
func (scene *SelectScene) ResetNext() {
scene.Next = scene.Whoami
}
func (scene *SelectScene) SetNext(next SceneName) {
scene.Next = next
}
func (scene *SelectScene) Clearscreen() bool {
// both level_scene AND the popup must not clear to get an actual popup
return true
}
func (scene *SelectScene) Update() error {
scene.Ui.Update()
return nil
}
func (scene *SelectScene) Draw(screen *ebiten.Image) {
scene.Ui.Draw(screen)
}
type LevelEntry struct {
Id int
Name string
}
func (scene *SelectScene) SetupUI() {
gameobserver := observers.GetGameObserver(scene.Game.World)
blue := color.RGBA{0, 255, 128, 255}
rowContainer := gameui.NewRowContainer()
label := widget.NewText(
widget.TextOpts.Text("Select Level", *assets.FontRenderer.FontBig, blue),
widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
)
levels := make([]any, 0, len(scene.Game.Levels))
for id := 0; id < len(scene.Game.Levels); id++ {
levels = append(levels, LevelEntry{Id: id, Name: scene.Game.Levels[id].Name})
}
slog.Debug("levels", "levels", levels)
buttonImage, err := gameui.LoadButtonImage()
if err != nil {
panic(err)
}
list := widget.NewList(
// Set how wide the list should be
widget.ListOpts.ContainerOpts(widget.ContainerOpts.WidgetOpts(
widget.WidgetOpts.MinSize(150, 0),
widget.WidgetOpts.LayoutData(widget.RowLayoutData{
Position: widget.RowLayoutPositionCenter,
Stretch: true,
MaxHeight: 300,
}),
)),
// Set the entries in the list
widget.ListOpts.Entries(levels),
widget.ListOpts.ScrollContainerOpts(
// Set the background images/color for the list
widget.ScrollContainerOpts.Image(&widget.ScrollContainerImage{
Idle: image.NewNineSliceColor(color.NRGBA{100, 100, 100, 255}),
Disabled: image.NewNineSliceColor(color.NRGBA{100, 100, 100, 255}),
Mask: image.NewNineSliceColor(color.NRGBA{100, 100, 100, 255}),
}),
),
widget.ListOpts.SliderOpts(
// Set the background images/color for the background of the slider track
widget.SliderOpts.Images(&widget.SliderTrackImage{
Idle: image.NewNineSliceColor(color.NRGBA{100, 100, 100, 255}),
Hover: image.NewNineSliceColor(color.NRGBA{100, 100, 100, 255}),
}, buttonImage),
widget.SliderOpts.MinHandleSize(5),
// Set how wide the track should be
widget.SliderOpts.TrackPadding(widget.NewInsetsSimple(2))),
// Hide the horizontal slider
widget.ListOpts.HideHorizontalSlider(),
// Set the font for the list options
widget.ListOpts.EntryFontFace(*assets.FontRenderer.FontNormal),
// Set the colors for the list
widget.ListOpts.EntryColor(&widget.ListEntryColor{
Selected: color.NRGBA{0, 255, 0, 255},
Unselected: color.NRGBA{254, 255, 255, 255},
SelectedBackground: color.NRGBA{R: 130, G: 130, B: 200, A: 255},
SelectedFocusedBackground: color.NRGBA{R: 130, G: 130, B: 170, A: 255},
FocusedBackground: color.NRGBA{R: 170, G: 170, B: 180, A: 255},
DisabledUnselected: color.NRGBA{100, 100, 100, 255},
DisabledSelected: color.NRGBA{100, 100, 100, 255},
DisabledSelectedBackground: color.NRGBA{100, 100, 100, 255},
}),
// This required function returns the string displayed in the list
widget.ListOpts.EntryLabelFunc(func(e interface{}) string {
return fmt.Sprintf("%02d %s", e.(LevelEntry).Id, e.(LevelEntry).Name)
}),
// Padding for each entry
widget.ListOpts.EntryTextPadding(widget.NewInsetsSimple(5)),
// Text position for each entry
widget.ListOpts.EntryTextPosition(widget.TextPositionStart, widget.TextPositionCenter),
// This handler defines what function to run when a list item is selected.
widget.ListOpts.EntrySelectedHandler(func(args *widget.ListEntrySelectedEventArgs) {
entry := args.Entry.(LevelEntry)
fmt.Println("Entry Selected: ", entry)
gameobserver.CurrentLevel = entry.Id
}),
)
buttonPlay := gameui.NewMenuButton("Play selected level", *assets.FontRenderer.FontNormal,
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Play)
})
rowContainer.AddChild(label)
rowContainer.AddChild(list)
rowContainer.AddChild(buttonPlay)
scene.Ui = &ebitenui.UI{
Container: rowContainer.Container(),
}
}