package groovy import ( "os" "github.com/hajimehoshi/ebiten/v2" ) const ( defaultWidth = 1024 defaultHeight = 768 ) type Area struct { Width int Height int } type GameInfo struct { Name string Version string Dimension Area } type Manager struct { Info GameInfo currentScene Scene currentSceneId uint nextSceneId uint scenes []Scene EventMap map[SceneEvent]func() } // can be used to create default manager instance func NewManager() Manager { return Manager{ Info: GameInfo{ Name: "groovy", Version: "1.0", Dimension: Area{ Width: defaultWidth, Height: defaultHeight, }, }, currentSceneId: 0, nextSceneId: 1, } } // ebitengine update proxy on behalf of current scene func (m *Manager) Update() error { if m.currentScene == nil { return nil } return m.currentScene.Update() } // shutdown application func (m *Manager) Quit() { os.Exit(0) } // 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.Dimension.Width, m.Info.Dimension.Height } // appends scene to the managed scenes func (m *Manager) AddScene(s Scene) { setDefaultHandlers(m, s) m.scenes = append(m.scenes, 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 Scene) { s.SetEventHandler(RESET, func() { m.ResetScenes() }) s.SetEventHandler(COMPLETED, func() { m.TransitionScene() }) s.SetEventHandler(ENDGAME, 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.scenes)) { m.Quit() } m.currentSceneId = sceneId m.currentScene = m.scenes[sceneId] } // 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 Area) { m.Info.Dimension = a } // report number of total scenes func (m *Manager) SceneCount() uint { return uint(len(m.scenes)) }