Noah Petherbridge
fb5a8a1ae8
* The "Giant Screenshot" feature takes a very long time, so it is made asynchronous. If you try and run a second one while the first is busy, you get an error flash. You can continue editing the level, even playtest it, or load a different level, and it will continue crunching on the Giant Screenshot and flash when it's finished. * Updated the player physics to use proper Velocity to jump off the ground rather than the hacky timer-based fixed speed approach. * FlashError() function to flash "error level" messages to the screen. They appear in orange text instead of the usual blue, and most error messages in the game use this now. The dev console "error <msg>" command can simulate an error message. * Flashed message fonts are updated. The blue font now uses softer stroke and shadow colors and the same algorithm applies to the orange error flashes. Some other changes to player physics: * Max velocity, acceleration speed, and gravity have been tweaked. * Fast turn-around if you are moving right and then need to go left. Your velocity resets to zero at the transition so you quickly get going the way you want to go. Some levels that need a bit of love for the new platforming physics: * Tutorial 3.level
240 lines
5.4 KiB
Go
240 lines
5.4 KiB
Go
package doodle
|
|
|
|
import (
|
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
|
"git.kirsle.net/apps/doodle/pkg/level"
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"git.kirsle.net/apps/doodle/pkg/uix"
|
|
"git.kirsle.net/apps/doodle/pkg/windows"
|
|
"git.kirsle.net/go/render"
|
|
"git.kirsle.net/go/render/event"
|
|
"git.kirsle.net/go/ui"
|
|
)
|
|
|
|
/*
|
|
MenuScene holds the main dialog menu UIs for:
|
|
|
|
* New Level
|
|
* Open Level
|
|
* Settings
|
|
*/
|
|
type MenuScene struct {
|
|
// Configuration.
|
|
StartupMenu string
|
|
|
|
Supervisor *ui.Supervisor
|
|
|
|
// Private widgets.
|
|
window *ui.Window
|
|
|
|
// Background wallpaper canvas.
|
|
canvas *uix.Canvas
|
|
|
|
// Values for the New menu
|
|
newPageType string
|
|
newWallpaper string
|
|
|
|
// Values for the Load/Play menu.
|
|
loadForPlay bool // false = load for edit
|
|
}
|
|
|
|
// Name of the scene.
|
|
func (s *MenuScene) Name() string {
|
|
return "Menu"
|
|
}
|
|
|
|
// DebugGetWindow surfaces the underlying private window.
|
|
func (s *MenuScene) DebugGetWindow() *ui.Window {
|
|
return s.window
|
|
}
|
|
|
|
// GotoNewMenu loads the MenuScene and shows the "New" window.
|
|
func (d *Doodle) GotoNewMenu() {
|
|
log.Info("Loading the MenuScene to the New window")
|
|
scene := &MenuScene{
|
|
StartupMenu: "new",
|
|
}
|
|
d.Goto(scene)
|
|
}
|
|
|
|
// GotoLoadMenu loads the MenuScene and shows the "Load" window.
|
|
func (d *Doodle) GotoLoadMenu() {
|
|
log.Info("Loading the MenuScene to the Load window for Edit Mode")
|
|
scene := &MenuScene{
|
|
StartupMenu: "load",
|
|
}
|
|
d.Goto(scene)
|
|
}
|
|
|
|
// GotoPlayMenu loads the MenuScene and shows the "Load" window for playing a
|
|
// level, not editing it.
|
|
func (d *Doodle) GotoPlayMenu() {
|
|
log.Info("Loading the MenuScene to the Load window for Play Mode")
|
|
scene := &MenuScene{
|
|
StartupMenu: "load",
|
|
loadForPlay: true,
|
|
}
|
|
d.Goto(scene)
|
|
}
|
|
|
|
// GotoSettingsMenu loads the settings screen.
|
|
func (d *Doodle) GotoSettingsMenu() {
|
|
log.Info("Loading the MenuScene to the Settings Menu")
|
|
scene := &MenuScene{
|
|
StartupMenu: "settings",
|
|
}
|
|
d.Goto(scene)
|
|
}
|
|
|
|
// Setup the scene.
|
|
func (s *MenuScene) Setup(d *Doodle) error {
|
|
s.Supervisor = ui.NewSupervisor()
|
|
|
|
// Set up the background wallpaper canvas.
|
|
s.canvas = uix.NewCanvas(100, false)
|
|
s.canvas.Resize(render.Rect{
|
|
W: d.width,
|
|
H: d.height,
|
|
})
|
|
s.canvas.LoadLevel(&level.Level{
|
|
Chunker: level.NewChunker(100),
|
|
Palette: level.NewPalette(),
|
|
PageType: level.Bounded,
|
|
Wallpaper: "notebook.png",
|
|
})
|
|
|
|
switch s.StartupMenu {
|
|
case "new":
|
|
if err := s.setupNewWindow(d); err != nil {
|
|
return err
|
|
}
|
|
case "load":
|
|
if err := s.setupLoadWindow(d); err != nil {
|
|
return err
|
|
}
|
|
case "settings":
|
|
if err := s.setupSettingsWindow(d); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
d.FlashError("No Valid StartupMenu Given to MenuScene")
|
|
}
|
|
|
|
// Whatever window we got, give it window manager controls under Supervisor.
|
|
s.window.Supervise(s.Supervisor)
|
|
s.window.Compute(d.Engine)
|
|
|
|
// Center the window.
|
|
s.window.MoveTo(render.Point{
|
|
X: (d.width / 2) - (s.window.Size().W / 2),
|
|
Y: 60,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// configureCanvas updates the settings of the background canvas, so a live
|
|
// preview of the wallpaper and wrapping type can be shown.
|
|
func (s *MenuScene) configureCanvas(pageType level.PageType, wallpaper string) {
|
|
s.canvas.LoadLevel(&level.Level{
|
|
Chunker: level.NewChunker(100),
|
|
Palette: level.NewPalette(),
|
|
PageType: pageType,
|
|
Wallpaper: wallpaper,
|
|
})
|
|
}
|
|
|
|
// setupNewWindow sets up the UI for the "New" window.
|
|
func (s *MenuScene) setupNewWindow(d *Doodle) error {
|
|
window := windows.NewAddEditLevel(windows.AddEditLevel{
|
|
Supervisor: s.Supervisor,
|
|
Engine: d.Engine,
|
|
OnChangePageTypeAndWallpaper: func(pageType level.PageType, wallpaper string) {
|
|
log.Info("OnChangePageTypeAndWallpaper called: %+v, %+v", pageType, wallpaper)
|
|
s.configureCanvas(pageType, wallpaper)
|
|
},
|
|
OnCreateNewLevel: func(lvl *level.Level) {
|
|
d.Goto(&EditorScene{
|
|
DrawingType: enum.LevelDrawing,
|
|
Level: lvl,
|
|
})
|
|
},
|
|
OnCancel: func() {
|
|
d.Goto(&MainScene{})
|
|
},
|
|
})
|
|
s.window = window
|
|
window.SetButtons(0)
|
|
window.Show()
|
|
return nil
|
|
}
|
|
|
|
// setupLoadWindow sets up the UI for the "New" window.
|
|
func (s *MenuScene) setupLoadWindow(d *Doodle) error {
|
|
window := windows.NewOpenLevelEditor(windows.OpenLevelEditor{
|
|
Supervisor: s.Supervisor,
|
|
Engine: d.Engine,
|
|
LoadForPlay: s.loadForPlay,
|
|
OnPlayLevel: func(filename string) {
|
|
d.PlayLevel(filename)
|
|
},
|
|
OnEditLevel: func(filename string) {
|
|
d.EditFile(filename)
|
|
},
|
|
OnCancel: func() {
|
|
d.Goto(&MainScene{})
|
|
},
|
|
})
|
|
s.window = window
|
|
return nil
|
|
}
|
|
|
|
// setupLoadWindow sets up the UI for the "New" window.
|
|
func (s *MenuScene) setupSettingsWindow(d *Doodle) error {
|
|
window := windows.NewSettingsWindow(windows.Settings{
|
|
Supervisor: s.Supervisor,
|
|
Engine: d.Engine,
|
|
})
|
|
window.SetButtons(0)
|
|
s.window = window
|
|
return nil
|
|
}
|
|
|
|
// Loop the editor scene.
|
|
func (s *MenuScene) Loop(d *Doodle, ev *event.State) error {
|
|
s.Supervisor.Loop(ev)
|
|
|
|
if ev.WindowResized {
|
|
w, h := d.Engine.WindowSize()
|
|
d.width = w
|
|
d.height = h
|
|
log.Info("Resized to %dx%d", d.width, d.height)
|
|
s.canvas.Resize(render.Rect{
|
|
W: d.width,
|
|
H: d.height,
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Draw the pixels on this frame.
|
|
func (s *MenuScene) Draw(d *Doodle) error {
|
|
// Draw the background canvas.
|
|
s.canvas.Present(d.Engine, render.Origin)
|
|
|
|
// TODO: if I don't call Compute here, buttons in the Edit Window get all
|
|
// bunched up. Investigate why later.
|
|
s.window.Compute(d.Engine)
|
|
|
|
// Draw the window managed by Supervisor.
|
|
s.Supervisor.Present(d.Engine)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Destroy the scene.
|
|
func (s *MenuScene) Destroy() error {
|
|
return nil
|
|
}
|