2018-06-21 02:00:46 +00:00
|
|
|
package doodle
|
|
|
|
|
|
|
|
import (
|
2018-09-25 16:40:34 +00:00
|
|
|
"fmt"
|
|
|
|
|
2019-04-10 00:35:44 +00:00
|
|
|
"git.kirsle.net/apps/doodle/lib/events"
|
|
|
|
"git.kirsle.net/apps/doodle/lib/render"
|
|
|
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
2019-04-10 02:17:56 +00:00
|
|
|
"git.kirsle.net/apps/doodle/pkg/doodads/dummy"
|
2019-04-10 00:35:44 +00:00
|
|
|
"git.kirsle.net/apps/doodle/pkg/level"
|
|
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
2019-04-16 06:07:15 +00:00
|
|
|
"git.kirsle.net/apps/doodle/pkg/scripting"
|
2019-04-10 00:35:44 +00:00
|
|
|
"git.kirsle.net/apps/doodle/pkg/uix"
|
2018-06-21 02:00:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// PlayScene manages the "Edit Level" game mode.
|
|
|
|
type PlayScene struct {
|
2018-07-24 03:10:53 +00:00
|
|
|
// Configuration attributes.
|
|
|
|
Filename string
|
2018-09-25 16:40:34 +00:00
|
|
|
Level *level.Level
|
2018-07-24 03:10:53 +00:00
|
|
|
|
|
|
|
// Private variables.
|
2019-04-16 06:07:15 +00:00
|
|
|
d *Doodle
|
|
|
|
drawing *uix.Canvas
|
|
|
|
scripting *scripting.Supervisor
|
2018-06-21 02:00:46 +00:00
|
|
|
|
2019-04-10 01:28:08 +00:00
|
|
|
// Custom debug labels.
|
|
|
|
debPosition *string
|
|
|
|
debViewport *string
|
|
|
|
debScroll *string
|
|
|
|
debWorldIndex *string
|
|
|
|
|
2018-07-24 03:10:53 +00:00
|
|
|
// Player character
|
2019-04-10 02:17:56 +00:00
|
|
|
Player *uix.Actor
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Name of the scene.
|
|
|
|
func (s *PlayScene) Name() string {
|
|
|
|
return "Play"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup the play scene.
|
|
|
|
func (s *PlayScene) Setup(d *Doodle) error {
|
2018-10-28 05:22:13 +00:00
|
|
|
s.d = d
|
2019-04-16 06:07:15 +00:00
|
|
|
s.scripting = scripting.NewSupervisor()
|
2019-04-10 01:28:08 +00:00
|
|
|
|
|
|
|
// Initialize debug overlay values.
|
|
|
|
s.debPosition = new(string)
|
|
|
|
s.debViewport = new(string)
|
|
|
|
s.debScroll = new(string)
|
|
|
|
s.debWorldIndex = new(string)
|
|
|
|
customDebugLabels = []debugLabel{
|
|
|
|
{"Pixel:", s.debWorldIndex},
|
|
|
|
{"Player:", s.debPosition},
|
|
|
|
{"Viewport:", s.debViewport},
|
|
|
|
{"Scroll:", s.debScroll},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the drawing canvas.
|
2018-09-26 17:04:46 +00:00
|
|
|
s.drawing = uix.NewCanvas(balance.ChunkSize, false)
|
2019-04-14 22:25:03 +00:00
|
|
|
s.drawing.Name = "play-canvas"
|
2018-09-25 16:40:34 +00:00
|
|
|
s.drawing.MoveTo(render.Origin)
|
2018-10-19 20:31:58 +00:00
|
|
|
s.drawing.Resize(render.NewRect(int32(d.width), int32(d.height)))
|
2018-09-25 16:40:34 +00:00
|
|
|
s.drawing.Compute(d.Engine)
|
2018-07-24 03:10:53 +00:00
|
|
|
|
2018-09-25 16:40:34 +00:00
|
|
|
// Given a filename or map data to play?
|
|
|
|
if s.Level != nil {
|
|
|
|
log.Debug("PlayScene.Setup: received level from scene caller")
|
2018-10-28 05:22:13 +00:00
|
|
|
s.drawing.LoadLevel(d.Engine, s.Level)
|
2019-04-10 02:17:56 +00:00
|
|
|
s.drawing.InstallActors(s.Level.Actors)
|
2018-07-24 03:10:53 +00:00
|
|
|
} else if s.Filename != "" {
|
|
|
|
log.Debug("PlayScene.Setup: loading map from file %s", s.Filename)
|
2019-04-16 06:07:15 +00:00
|
|
|
// NOTE: s.LoadLevel also calls s.drawing.InstallActors
|
2018-07-24 03:10:53 +00:00
|
|
|
s.LoadLevel(s.Filename)
|
|
|
|
}
|
|
|
|
|
2018-09-25 16:40:34 +00:00
|
|
|
if s.Level == nil {
|
2018-07-24 03:10:53 +00:00
|
|
|
log.Debug("PlayScene.Setup: no grid given, initializing empty grid")
|
2018-09-25 16:40:34 +00:00
|
|
|
s.Level = level.New()
|
2018-10-28 05:22:13 +00:00
|
|
|
s.drawing.LoadLevel(d.Engine, s.Level)
|
2019-04-10 02:17:56 +00:00
|
|
|
s.drawing.InstallActors(s.Level.Actors)
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
2018-07-24 03:10:53 +00:00
|
|
|
|
2019-04-16 06:07:15 +00:00
|
|
|
// Load all actor scripts.
|
|
|
|
s.drawing.SetScriptSupervisor(s.scripting)
|
|
|
|
if err := s.scripting.InstallScripts(s.Level); err != nil {
|
|
|
|
log.Error("PlayScene.Setup: failed to InstallScripts: %s", err)
|
|
|
|
}
|
|
|
|
if err := s.drawing.InstallScripts(); err != nil {
|
|
|
|
log.Error("PlayScene.Setup: failed to drawing.InstallScripts: %s", err)
|
|
|
|
}
|
|
|
|
|
2019-04-10 02:17:56 +00:00
|
|
|
player := dummy.NewPlayer()
|
|
|
|
s.Player = uix.NewActor(player.ID(), &level.Actor{}, player.Doodad)
|
|
|
|
s.Player.MoveTo(render.NewPoint(128, 128))
|
|
|
|
s.drawing.AddActor(s.Player)
|
|
|
|
s.drawing.FollowActor = s.Player.ID()
|
|
|
|
|
2018-07-24 03:10:53 +00:00
|
|
|
d.Flash("Entered Play Mode. Press 'E' to edit this map.")
|
|
|
|
|
2018-06-21 02:00:46 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loop the editor scene.
|
2018-07-22 00:12:22 +00:00
|
|
|
func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
2019-04-10 01:28:08 +00:00
|
|
|
// Update debug overlay values.
|
|
|
|
*s.debWorldIndex = s.drawing.WorldIndexAt(render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)).String()
|
2019-04-14 22:25:03 +00:00
|
|
|
*s.debPosition = s.Player.Position().String() + " vel " + s.Player.Velocity().String()
|
2019-04-10 01:28:08 +00:00
|
|
|
*s.debViewport = s.drawing.Viewport().String()
|
|
|
|
*s.debScroll = s.drawing.Scroll.String()
|
|
|
|
|
|
|
|
// Has the window been resized?
|
|
|
|
if resized := ev.Resized.Read(); resized {
|
|
|
|
w, h := d.Engine.WindowSize()
|
|
|
|
if w != d.width || h != d.height {
|
|
|
|
d.width = w
|
|
|
|
d.height = h
|
|
|
|
s.drawing.Resize(render.NewRect(int32(d.width), int32(d.height)))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 03:10:53 +00:00
|
|
|
// Switching to Edit Mode?
|
|
|
|
if ev.KeyName.Read() == "e" {
|
|
|
|
log.Info("Edit Mode, Go!")
|
|
|
|
d.Goto(&EditorScene{
|
2018-09-25 16:40:34 +00:00
|
|
|
Filename: s.Filename,
|
|
|
|
Level: s.Level,
|
2018-07-24 03:10:53 +00:00
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-04-19 01:15:05 +00:00
|
|
|
// Loop the script supervisor so timeouts/intervals can fire in scripts.
|
|
|
|
if err := s.scripting.Loop(); err != nil {
|
|
|
|
log.Error("PlayScene.Loop: scripting.Loop: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-07-22 00:12:22 +00:00
|
|
|
s.movePlayer(ev)
|
2019-04-10 02:17:56 +00:00
|
|
|
if err := s.drawing.Loop(ev); err != nil {
|
|
|
|
log.Error("Drawing loop error: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
2018-07-22 03:43:01 +00:00
|
|
|
return nil
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the pixels on this frame.
|
|
|
|
func (s *PlayScene) Draw(d *Doodle) error {
|
|
|
|
// Clear the canvas and fill it with white.
|
2018-07-22 00:12:22 +00:00
|
|
|
d.Engine.Clear(render.White)
|
2018-06-21 02:00:46 +00:00
|
|
|
|
2018-09-25 16:40:34 +00:00
|
|
|
// Draw the level.
|
|
|
|
s.drawing.Present(d.Engine, s.drawing.Point())
|
2018-06-21 02:00:46 +00:00
|
|
|
|
2018-07-25 03:57:22 +00:00
|
|
|
// Draw out bounding boxes.
|
2018-07-26 02:38:54 +00:00
|
|
|
d.DrawCollisionBox(s.Player)
|
2018-07-25 03:57:22 +00:00
|
|
|
|
2018-06-21 02:00:46 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-07-22 00:12:22 +00:00
|
|
|
// movePlayer updates the player's X,Y coordinate based on key pressed.
|
|
|
|
func (s *PlayScene) movePlayer(ev *events.State) {
|
2019-04-10 02:17:56 +00:00
|
|
|
var playerSpeed = int32(balance.PlayerMaxVelocity)
|
|
|
|
var gravity = int32(balance.Gravity)
|
|
|
|
|
|
|
|
var velocity render.Point
|
2018-07-24 03:10:53 +00:00
|
|
|
|
2018-06-21 02:00:46 +00:00
|
|
|
if ev.Down.Now {
|
2019-04-10 02:17:56 +00:00
|
|
|
velocity.Y = playerSpeed
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
if ev.Left.Now {
|
2019-04-10 02:17:56 +00:00
|
|
|
velocity.X = -playerSpeed
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
if ev.Right.Now {
|
2019-04-10 02:17:56 +00:00
|
|
|
velocity.X = playerSpeed
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
if ev.Up.Now {
|
2019-04-10 02:17:56 +00:00
|
|
|
velocity.Y = -playerSpeed
|
2018-07-24 03:10:53 +00:00
|
|
|
}
|
|
|
|
|
2018-07-25 03:57:22 +00:00
|
|
|
// Apply gravity if not grounded.
|
2018-07-26 02:38:54 +00:00
|
|
|
if !s.Player.Grounded() {
|
2018-07-25 05:26:27 +00:00
|
|
|
// Gravity has to pipe through the collision checker, too, so it
|
|
|
|
// can't give us a cheated downward boost.
|
2019-04-10 02:17:56 +00:00
|
|
|
velocity.Y += gravity
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
2018-07-24 03:10:53 +00:00
|
|
|
|
2019-04-14 22:25:03 +00:00
|
|
|
s.Player.SetVelocity(velocity)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Drawing returns the private world drawing, for debugging with the console.
|
|
|
|
func (s *PlayScene) Drawing() *uix.Canvas {
|
|
|
|
return s.drawing
|
2018-06-21 02:00:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// LoadLevel loads a level from disk.
|
2018-07-21 22:11:00 +00:00
|
|
|
func (s *PlayScene) LoadLevel(filename string) error {
|
2018-09-25 16:40:34 +00:00
|
|
|
s.Filename = filename
|
2018-06-21 02:00:46 +00:00
|
|
|
|
2018-09-25 16:40:34 +00:00
|
|
|
level, err := level.LoadJSON(filename)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("PlayScene.LoadLevel(%s): %s", filename, err)
|
|
|
|
}
|
2018-06-21 02:00:46 +00:00
|
|
|
|
2018-09-25 16:40:34 +00:00
|
|
|
s.Level = level
|
2018-10-28 05:22:13 +00:00
|
|
|
s.drawing.LoadLevel(s.d.Engine, s.Level)
|
2019-04-16 06:07:15 +00:00
|
|
|
// s.drawing.InstallActors(s.Level.Actors)
|
2018-06-21 02:00:46 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-07-24 03:10:53 +00:00
|
|
|
|
|
|
|
// Destroy the scene.
|
|
|
|
func (s *PlayScene) Destroy() error {
|
|
|
|
return nil
|
|
|
|
}
|