package screenmanager import ( "mover/gamedata" "mover/screens" "github.com/hajimehoshi/ebiten/v2" ) const ( defaultWidth = 1024 defaultHeight = 768 ) type Manager struct { Info gamedata.GameInfo currentScene screens.Screen currentSceneId uint nextSceneId uint screens []screens.Screen internalerr error } // can be used to create default manager instance func NewManager() Manager { return Manager{ Info: gamedata.GameInfo{ Name: "survive", Version: "0.32", Dimensions: gamedata.Area{ Width: defaultWidth, Height: defaultHeight, }, }, currentSceneId: 0, nextSceneId: 1, internalerr: nil, } } // ebitengine update proxy on behalf of current scene func (m *Manager) Update() error { if m.currentScene == nil { return nil } err := m.currentScene.Update() if err != nil { return err } return m.internalerr } // shutdown application func (m *Manager) Quit() { m.internalerr = ebiten.Termination } // calls current scene's draw method if the currentscene is valid func (m *Manager) Draw(screen *ebiten.Image) { if m.currentScene != nil { m.currentScene.Draw(screen) } } // ebitengine proxy for layout func (m *Manager) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { return m.Info.Dimensions.Width, m.Info.Dimensions.Height } // appends scene to the managed screens func (m *Manager) AddScene(s screens.Screen) { setDefaultHandlers(m, s) s.SetDimensions(m.Info.Dimensions) m.screens = append(m.screens, s) } // sets the default callback handlers for a given scene within manager // Default Handling behaviours: // // reset: sets (scene, nextscene) to {0, 1} // scene completion: sets (scene, nextscene) to {nextscene, nextscene+1} // end game: shutdown groovy // // note: NOOP and RELOAD are purposefully not mapped; they are scene // specific and should be mapped to by user of groovy func setDefaultHandlers(m *Manager, s screens.Screen) { s.SetEventHandler(screens.EventReset, func() { m.ResetScenes() }) s.SetEventHandler(screens.EventCompleted, func() { m.TransitionScene() }) s.SetEventHandler(screens.EventEndgame, func() { m.Quit() }) } // we're going to reset the scene to the first one func (m *Manager) ResetScenes() { m.currentSceneId = 0 m.nextSceneId = 1 m.SetCurrentScene(0) } // sets the current scene, based on sceneindex n // n > scenelist, quit // otherwise, scene = n func (m *Manager) SetCurrentScene(sceneId uint) { if sceneId >= uint(len(m.screens)) { m.Quit() } else { m.currentSceneId = sceneId m.currentScene = m.screens[sceneId] m.nextSceneId = m.currentSceneId + 1 } } // handle scene transition func (m *Manager) TransitionScene() { m.SetCurrentScene(m.nextSceneId) } // set new sceneId as the successor func (m *Manager) SetNextScene(sceneId uint) { m.nextSceneId = sceneId } // sets sene dimensions func (m *Manager) SetDimensions(a gamedata.Area) { m.Info.Dimensions = a } // report number of total screens func (m *Manager) SceneCount() uint { return uint(len(m.screens)) } func (m *Manager) GetScene(sceneId uint) screens.Screen { return m.screens[sceneId] }