Noah Petherbridge
215ed5c847
* The loading screen for Edit and Play modes is stable and the risk of game crash is removed. The root cause was the setupAsync() functions running on a background goroutine, and running SDL2 draw functions while NOT on the main thread, which causes problems. * The fix is all SDL2 Texture draws become lazy loaded: when the main thread is presenting, any Wallpaper or ui.Image that has no texture yet gets one created at that time from the cached image.Image. * All internal game logic then uses image.Image types, to cache bitmaps of Level Chunks, Wallpaper images, Sprite icons, etc. and the game is free to prepare these asynchronously; only the main thread ever Presents and the SDL2 textures initialize on first appearance. * Several functions had arguments cleaned up: Canvas.LoadLevel() does not need the render.Engine as (e.g. wallpaper) textures don't render at that stage.
145 lines
3.2 KiB
Go
145 lines
3.2 KiB
Go
package doodle
|
|
|
|
import (
|
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
|
"git.kirsle.net/apps/doodle/pkg/campaign"
|
|
"git.kirsle.net/apps/doodle/pkg/level"
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"git.kirsle.net/apps/doodle/pkg/uix"
|
|
"git.kirsle.net/go/render"
|
|
"git.kirsle.net/go/render/event"
|
|
"git.kirsle.net/go/ui"
|
|
)
|
|
|
|
// StoryScene manages the "Story Mode" menu selection screen.
|
|
type StoryScene struct {
|
|
// Private variables.
|
|
d *Doodle
|
|
running bool
|
|
|
|
// Background wallpaper canvas.
|
|
canvas *uix.Canvas
|
|
|
|
// UI widgets.
|
|
supervisor *ui.Supervisor
|
|
campaignFrame *ui.Frame // Select a Campaign screen
|
|
levelSelectFrame *ui.Frame // Select a level in the campaign screen
|
|
|
|
// Pointer to the currently active frame.
|
|
activeFrame *ui.Frame
|
|
}
|
|
|
|
// Name of the scene.
|
|
func (s *StoryScene) Name() string {
|
|
return "Story"
|
|
}
|
|
|
|
// GotoStoryMenu initializes the story menu scene.
|
|
func (d *Doodle) GotoStoryMenu() {
|
|
log.Info("Loading Story Scene")
|
|
scene := &StoryScene{}
|
|
d.Goto(scene)
|
|
}
|
|
|
|
// Setup the play scene.
|
|
func (s *StoryScene) Setup(d *Doodle) error {
|
|
s.d = d
|
|
|
|
// Set up the background wallpaper canvas.
|
|
s.canvas = uix.NewCanvas(100, false)
|
|
s.canvas.Resize(render.NewRect(d.width, d.height))
|
|
s.canvas.LoadLevel(&level.Level{
|
|
Chunker: level.NewChunker(100),
|
|
Palette: level.NewPalette(),
|
|
PageType: level.Bounded,
|
|
Wallpaper: "notebook.png",
|
|
})
|
|
|
|
s.supervisor = ui.NewSupervisor()
|
|
|
|
// Set up the sub-screens of this scene.
|
|
s.campaignFrame = s.setupCampaignFrame()
|
|
s.levelSelectFrame = s.setupLevelSelectFrame()
|
|
|
|
s.activeFrame = s.campaignFrame
|
|
|
|
return nil
|
|
}
|
|
|
|
// setupCampaignFrame sets up the Campaign List screen.
|
|
func (s *StoryScene) setupCampaignFrame() *ui.Frame {
|
|
var frame = ui.NewFrame("List Frame")
|
|
frame.SetBackground(render.RGBA(0, 0, 255, 20))
|
|
|
|
// Title label
|
|
labelTitle := ui.NewLabel(ui.Label{
|
|
Text: "Select a Story",
|
|
Font: balance.TitleScreenFont,
|
|
})
|
|
labelTitle.Compute(s.d.Engine)
|
|
frame.Place(labelTitle, ui.Place{
|
|
Top: 120,
|
|
Center: true,
|
|
})
|
|
|
|
// Buttons for campaign selection.
|
|
{
|
|
campaignFiles, err := campaign.List()
|
|
if err != nil {
|
|
log.Error("campaign.List: %s", err)
|
|
}
|
|
|
|
_ = campaignFiles
|
|
// for _, file := range campaignFiles {
|
|
//
|
|
// }
|
|
}
|
|
|
|
frame.Resize(render.NewRect(s.d.width, s.d.height))
|
|
frame.Compute(s.d.Engine)
|
|
return frame
|
|
}
|
|
|
|
// setupLevelSelectFrame sets up the Level Select screen.
|
|
func (s *StoryScene) setupLevelSelectFrame() *ui.Frame {
|
|
var frame = ui.NewFrame("List Frame")
|
|
|
|
return frame
|
|
}
|
|
|
|
// Loop the story scene.
|
|
func (s *StoryScene) Loop(d *Doodle, ev *event.State) error {
|
|
s.supervisor.Loop(ev)
|
|
|
|
// Has the window been resized?
|
|
if ev.WindowResized {
|
|
w, h := d.Engine.WindowSize()
|
|
if w != d.width || h != d.height {
|
|
d.width = w
|
|
d.height = h
|
|
s.canvas.Resize(render.NewRect(d.width, d.height))
|
|
s.activeFrame.Resize(render.NewRect(d.width, d.height))
|
|
s.activeFrame.Compute(d.Engine)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Draw the pixels on this frame.
|
|
func (s *StoryScene) Draw(d *Doodle) error {
|
|
// Draw the background canvas.
|
|
s.canvas.Present(d.Engine, render.Origin)
|
|
|
|
// Draw the active screen.
|
|
s.activeFrame.Present(d.Engine, render.Origin)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Destroy the scene.
|
|
func (s *StoryScene) Destroy() error {
|
|
return nil
|
|
}
|