187 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package game
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"image/color"
 | |
| 	"log/slog"
 | |
| 	"openquell/assets"
 | |
| 	"openquell/config"
 | |
| 	"openquell/gameui"
 | |
| 	"openquell/observers"
 | |
| 
 | |
| 	"github.com/ebitenui/ebitenui"
 | |
| 	"github.com/ebitenui/ebitenui/image"
 | |
| 	"github.com/ebitenui/ebitenui/widget"
 | |
| 
 | |
| 	"github.com/hajimehoshi/ebiten/v2"
 | |
| 	"github.com/hajimehoshi/ebiten/v2/inpututil"
 | |
| )
 | |
| 
 | |
| 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()
 | |
| 
 | |
| 	if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
 | |
| 		scene.SetNext(Menu)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (scene *SelectScene) Draw(screen *ebiten.Image) {
 | |
| 	scene.Ui.Draw(screen)
 | |
| }
 | |
| 
 | |
| type LevelEntry struct {
 | |
| 	Id     int
 | |
| 	Number int
 | |
| 	Name   string
 | |
| }
 | |
| 
 | |
| func (scene *SelectScene) SetupUI() {
 | |
| 	gameobserver := observers.GetGameObserver(scene.Game.World)
 | |
| 
 | |
| 	rowContainer := gameui.NewRowContainer()
 | |
| 
 | |
| 	label := widget.NewText(
 | |
| 		widget.TextOpts.Text("Select Level", *assets.FontRenderer.FontBig, config.FontColorFG),
 | |
| 		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, Number: scene.Game.Levels[id].Number, 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: 200,
 | |
| 			}),
 | |
| 		)),
 | |
| 		// 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).Number, 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
 | |
| 		}),
 | |
| 	)
 | |
| 
 | |
| 	buttonContainer := widget.NewContainer(
 | |
| 		widget.ContainerOpts.Layout(widget.NewGridLayout(
 | |
| 			widget.GridLayoutOpts.Columns(2),
 | |
| 			widget.GridLayoutOpts.Padding(widget.NewInsetsSimple(30)),
 | |
| 			widget.GridLayoutOpts.Spacing(20, 10),
 | |
| 			widget.GridLayoutOpts.Stretch([]bool{true, false}, []bool{false, true}),
 | |
| 		)),
 | |
| 	)
 | |
| 
 | |
| 	buttonPlay := gameui.NewMenuButton("Play selected level", *assets.FontRenderer.FontNormal,
 | |
| 		func(args *widget.ButtonClickedEventArgs) {
 | |
| 			scene.SetNext(Play)
 | |
| 		})
 | |
| 
 | |
| 	buttonAbort := gameui.NewMenuButton("Back", *assets.FontRenderer.FontNormal,
 | |
| 		func(args *widget.ButtonClickedEventArgs) {
 | |
| 			scene.SetNext(Menu)
 | |
| 		})
 | |
| 
 | |
| 	buttonContainer.AddChild(buttonPlay)
 | |
| 	buttonContainer.AddChild(buttonAbort)
 | |
| 
 | |
| 	rowContainer.AddChild(label)
 | |
| 	rowContainer.AddChild(list)
 | |
| 	rowContainer.AddChild(buttonContainer)
 | |
| 
 | |
| 	scene.Ui = &ebitenui.UI{
 | |
| 		Container: rowContainer.Container(),
 | |
| 	}
 | |
| }
 |