127 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package game
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"image"
 | |
| 	"log/slog"
 | |
| 	"openquell/config"
 | |
| 	"openquell/observers"
 | |
| 
 | |
| 	"github.com/hajimehoshi/ebiten/v2"
 | |
| 	"github.com/mlange-42/arche/ecs"
 | |
| )
 | |
| 
 | |
| type Game struct {
 | |
| 	World                               *ecs.World
 | |
| 	Bounds                              image.Rectangle
 | |
| 	ScreenWidth, ScreenHeight, Cellsize int
 | |
| 	Scenes                              map[SceneName]Scene
 | |
| 	CurrentScene                        SceneName
 | |
| 	Observer                            *observers.GameObserver
 | |
| 	Levels                              []*Level // needed to feed select_scene
 | |
| 	Config                              *config.Config
 | |
| }
 | |
| 
 | |
| func NewGame(width, height, cellsize int, cfg *config.Config, startscene SceneName) *Game {
 | |
| 	world := ecs.NewWorld()
 | |
| 
 | |
| 	game := &Game{
 | |
| 		Bounds:       image.Rectangle{},
 | |
| 		World:        &world,
 | |
| 		ScreenWidth:  width,
 | |
| 		ScreenHeight: height,
 | |
| 		Scenes:       map[SceneName]Scene{},
 | |
| 		Cellsize:     cellsize,
 | |
| 		Config:       cfg,
 | |
| 	}
 | |
| 
 | |
| 	observers.NewPlayerObserver(&world)
 | |
| 	observers.NewParticleObserver(&world)
 | |
| 	observers.NewObstacleObserver(&world)
 | |
| 	game.Observer = observers.NewGameObserver(&world, cfg.Startlevel, width, height, cellsize)
 | |
| 
 | |
| 	game.Scenes[Welcome] = NewWelcomeScene(game)
 | |
| 	game.Scenes[Menu] = NewMenuScene(game)
 | |
| 	game.Scenes[About] = NewAboutScene(game)
 | |
| 	game.Scenes[Popup] = NewPopupScene(game)
 | |
| 	game.Scenes[Play] = NewLevelScene(game, cfg.Startlevel)
 | |
| 	game.Scenes[Select] = NewSelectScene(game)
 | |
| 
 | |
| 	game.CurrentScene = startscene
 | |
| 
 | |
| 	fmt.Println(game.World.Stats().String())
 | |
| 
 | |
| 	return game
 | |
| }
 | |
| 
 | |
| func (game *Game) GetCurrentScene() Scene {
 | |
| 	return game.Scenes[game.CurrentScene]
 | |
| }
 | |
| 
 | |
| func (game *Game) Update() error {
 | |
| 	gameobserver := observers.GetGameObserver(game.World)
 | |
| 
 | |
| 	// handle level ends
 | |
| 	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()
 | |
| 
 | |
| 		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()
 | |
| 	scene.Update()
 | |
| 
 | |
| 	if scene.Clearscreen() {
 | |
| 		ebiten.SetScreenClearedEveryFrame(true)
 | |
| 	} else {
 | |
| 		ebiten.SetScreenClearedEveryFrame(false)
 | |
| 	}
 | |
| 
 | |
| 	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].SetLevel(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()
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (game *Game) Draw(screen *ebiten.Image) {
 | |
| 	game.GetCurrentScene().Draw(screen)
 | |
| }
 | |
| 
 | |
| func (g *Game) Layout(newWidth, newHeight int) (int, int) {
 | |
| 	return g.ScreenWidth, g.ScreenHeight
 | |
| }
 |