added intermediate popup after win/loose, refresh level setup, fixes

This commit is contained in:
2024-02-19 19:05:48 +01:00
parent e12af87fb7
commit fd570216f0
16 changed files with 322 additions and 20 deletions

View File

@@ -3,6 +3,7 @@ package game
import (
"fmt"
"image"
"log/slog"
"openquell/observers"
"github.com/hajimehoshi/ebiten/v2"
@@ -38,7 +39,7 @@ func NewGame(width, height, cellsize, startlevel int, startscene SceneName) *Gam
game.Scenes[Menu] = NewMenuScene(game)
game.Scenes[About] = NewAboutScene(game)
game.Scenes[Popup] = NewPopupScene(game)
game.Scenes[Play] = NewLevelScene(game, startlevel)
//game.Scenes[Play] = NewLevelScene(game, startlevel)
game.Scenes[Select] = NewSelectScene(game)
game.CurrentScene = startscene
@@ -56,13 +57,20 @@ func (game *Game) Update() error {
gameobserver := observers.GetGameObserver(game.World)
// handle level ends
// FIXME: add a scene here, which asks: restart, next or abort
timer := gameobserver.StopTimer
if timer.IsReady() {
// a level is either lost or won, we display a small popup
// asking the user how to continue from here
timer.Reset()
gameobserver.CurrentLevel++
gameobserver.Score++ // FIXME: use level.Score(), see TODO
slog.Debug("timer ready", "lost", gameobserver.Lost, "retry", gameobserver.Retry)
if !gameobserver.Lost {
gameobserver.Score++ // FIXME: use level.Score(), see TODO
}
game.Scenes[Nextlevel] = NewNextlevelScene(game, gameobserver.Lost)
game.CurrentScene = Nextlevel
}
scene := game.GetCurrentScene()
@@ -76,8 +84,27 @@ func (game *Game) Update() error {
next := scene.GetNext()
if next != game.CurrentScene {
if next == Play && game.CurrentScene == Nextlevel {
// switched from nextlevel (lost or won) popup to play (either retry or next level)
if !gameobserver.Retry {
gameobserver.CurrentLevel++
}
gameobserver.Retry = false
}
if next == Play {
// fresh setup of actual level every time we enter the play scene
game.Scenes[Play] = NewLevelScene(game, gameobserver.CurrentLevel)
}
// make sure we stay on the selected scene
scene.ResetNext()
// finally switch
game.CurrentScene = next
// FIXME: add some reset function to gameobserver for these kinds of things
gameobserver.Lost = false
}
timer.Update()

View File

@@ -30,6 +30,7 @@ type Level struct {
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
gridsystem := systems.NewGridSystem(game.World, game.ScreenWidth,
game.ScreenHeight, cellsize, plan.Background)
playersystem := systems.NewPlayerSystem(game.World, gridsystem)
return &Level{

117
game/nextlevel_scene.go Normal file
View File

@@ -0,0 +1,117 @@
package game
import (
"image/color"
"log/slog"
"openquell/assets"
"openquell/gameui"
"openquell/observers"
"github.com/ebitenui/ebitenui"
"github.com/ebitenui/ebitenui/widget"
"github.com/hajimehoshi/ebiten/v2"
)
type NextlevelScene struct {
Game *Game
Next SceneName
Whoami SceneName
UseCache bool
Ui *ebitenui.UI
Lost bool
}
func NewNextlevelScene(game *Game, lost bool) Scene {
scene := &NextlevelScene{
Whoami: Nextlevel,
Game: game,
Next: Nextlevel,
Lost: lost,
}
scene.SetupUI()
return scene
}
func (scene *NextlevelScene) GetNext() SceneName {
return scene.Next
}
func (scene *NextlevelScene) ResetNext() {
scene.Next = scene.Whoami
}
func (scene *NextlevelScene) SetNext(next SceneName) {
slog.Debug("select setnext", "next", next)
scene.Next = next
}
func (scene *NextlevelScene) Clearscreen() bool {
// both level_scene AND the popup must not clear to get an actual popup
return false
}
func (scene *NextlevelScene) Update() error {
scene.Ui.Update()
return nil
}
func (scene *NextlevelScene) Draw(screen *ebiten.Image) {
background := assets.Assets["background-popup"]
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(
float64((scene.Game.ScreenWidth/2)-(background.Bounds().Dx()/2)),
float64((scene.Game.ScreenHeight/2)-(background.Bounds().Dy()/2)),
)
screen.DrawImage(assets.Assets["background-popup"], op)
scene.Ui.Draw(screen)
}
func (scene *NextlevelScene) SetupUI() {
blue := color.RGBA{0, 255, 128, 255}
gameobserver := observers.GetGameObserver(scene.Game.World)
rowContainer := gameui.NewRowContainer(false)
labeltext := "Success"
switch scene.Lost {
case true:
labeltext = "Failure"
}
buttonRetry := gameui.NewMenuButton("Retry", *assets.FontRenderer.FontNormal,
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Play)
gameobserver.Retry = true
})
buttonNext := gameui.NewMenuButton("Next Level", *assets.FontRenderer.FontNormal,
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Play)
gameobserver.Retry = false
})
buttonAbort := gameui.NewMenuButton("Abort", *assets.FontRenderer.FontNormal,
func(args *widget.ButtonClickedEventArgs) {
scene.SetNext(Menu)
})
label := widget.NewText(
widget.TextOpts.Text(labeltext, *assets.FontRenderer.FontBig, blue),
widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
)
rowContainer.AddChild(label)
rowContainer.AddChild(buttonNext)
rowContainer.AddChild(buttonRetry)
rowContainer.AddChild(buttonAbort)
scene.Ui = &ebitenui.UI{
Container: rowContainer.Container(),
}
}

View File

@@ -5,13 +5,14 @@ import (
)
const (
Welcome = iota // startup
Menu // main top level menu
Play // actual playing happens here
About // about the game
Settings // options
Popup // in-game options
Select // select which level to play
Welcome = iota // startup
Menu // main top level menu
Play // actual playing happens here
About // about the game
Settings // options
Popup // in-game options
Select // select which level to play
Nextlevel // displayed after loose or win
)
// Wrapper for different screens to be shown, as Welcome, Options,