doodle/play_scene.go

175 lines
3.8 KiB
Go
Raw Normal View History

2018-06-21 02:00:46 +00:00
package doodle
import (
"fmt"
"git.kirsle.net/apps/doodle/balance"
"git.kirsle.net/apps/doodle/doodads"
2018-10-21 02:49:59 +00:00
"git.kirsle.net/apps/doodle/doodads/dummy"
2018-06-21 02:00:46 +00:00
"git.kirsle.net/apps/doodle/events"
"git.kirsle.net/apps/doodle/level"
"git.kirsle.net/apps/doodle/render"
"git.kirsle.net/apps/doodle/uix"
2018-06-21 02:00:46 +00:00
)
// PlayScene manages the "Edit Level" game mode.
type PlayScene struct {
// Configuration attributes.
Filename string
Level *level.Level
// Private variables.
drawing *uix.Canvas
2018-06-21 02:00:46 +00:00
// Player character
2018-10-21 02:49:59 +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 {
s.drawing = uix.NewCanvas(balance.ChunkSize, false)
s.drawing.MoveTo(render.Origin)
Draw Actors Embedded in Levels in Edit Mode Add the JSON format for embedding Actors (Doodad instances) inside of a Level. I made a test map that manually inserted a couple of actors. Actors are given to the Canvas responsible for the Level via the function `InstallActors()`. So it means you'll call LoadLevel and then InstallActors to hook everything up. The Canvas creates sub-Canvas widgets from each Actor. After drawing the main level geometry from the Canvas.Chunker, it calls the drawActors() function which does the same but for Actors. Levels keep a global map of all Actors that exist. For any Actors that are visible within the Viewport, their sub-Canvas widgets are presented appropriately on top of the parent Canvas. In case their sub-Canvas overlaps the parent's boundaries, their sub-Canvas is resized and moved appropriately. - Allow the MainWindow to be resized at run time, and the UI recalculates its sizing and position. - Made the in-game Shell properties editable via environment variables. The kirsle.env file sets a blue and pink color scheme. - Begin the ground work for Levels and Doodads to embed files inside their data via the level.FileSystem type. - UI: Labels can now contain line break characters. It will appropriately render multiple lines of render.Text and take into account the proper BoxSize to contain them all. - Add environment variable DOODLE_DEBUG_ALL=true that will turn on ALL debug overlay and visualization options. - Add debug overlay to "tag" each Canvas widget with some of its details, like its Name and World Position. Can be enabled with the environment variable DEBUG_CANVAS_LABEL=true - Improved the FPS debug overlay to show in labeled columns and multiple colors, with easy ability to add new data points to it.
2018-10-19 20:31:58 +00:00
s.drawing.Resize(render.NewRect(int32(d.width), int32(d.height)))
s.drawing.Compute(d.Engine)
// Given a filename or map data to play?
if s.Level != nil {
log.Debug("PlayScene.Setup: received level from scene caller")
s.drawing.LoadLevel(s.Level)
2018-10-21 02:49:59 +00:00
s.drawing.InstallActors(s.Level.Actors)
} else if s.Filename != "" {
log.Debug("PlayScene.Setup: loading map from file %s", s.Filename)
s.LoadLevel(s.Filename)
}
2018-10-21 02:49:59 +00:00
player := dummy.NewPlayer()
s.Player = uix.NewActor(player.ID(), &level.Actor{}, player.Doodad)
2018-06-21 02:00:46 +00:00
if s.Level == nil {
log.Debug("PlayScene.Setup: no grid given, initializing empty grid")
s.Level = level.New()
s.drawing.LoadLevel(s.Level)
2018-06-21 02:00:46 +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.
func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
2018-10-21 02:49:59 +00:00
// 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
}
}
// Switching to Edit Mode?
if ev.KeyName.Read() == "e" {
log.Info("Edit Mode, Go!")
d.Goto(&EditorScene{
Filename: s.Filename,
Level: s.Level,
})
return nil
}
2018-10-21 02:49:59 +00:00
s.drawing.Loop(ev)
s.movePlayer(ev)
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.
d.Engine.Clear(render.White)
2018-06-21 02:00:46 +00:00
// Draw the level.
s.drawing.Present(d.Engine, s.drawing.Point())
2018-06-21 02:00:46 +00:00
// Draw our hero.
2018-10-21 02:49:59 +00:00
{
d.Engine.DrawBox(render.RGBA(255, 255, 153, 255), render.Rect{
X: s.Player.Position().X,
Y: s.Player.Position().Y,
W: s.Player.Size().W,
H: s.Player.Size().H,
})
}
2018-06-21 02:00:46 +00:00
2018-10-21 02:49:59 +00:00
// Draw our bounding boxes.
d.DrawCollisionBox(s.Player)
2018-06-21 02:00:46 +00:00
return nil
}
// movePlayer updates the player's X,Y coordinate based on key pressed.
func (s *PlayScene) movePlayer(ev *events.State) {
delta := s.Player.Position()
var playerSpeed int32 = 8
var gravity int32 = 2
2018-06-21 02:00:46 +00:00
if ev.Down.Now {
delta.Y += playerSpeed
2018-06-21 02:00:46 +00:00
}
if ev.Left.Now {
delta.X -= playerSpeed
2018-06-21 02:00:46 +00:00
}
if ev.Right.Now {
delta.X += playerSpeed
2018-06-21 02:00:46 +00:00
}
if ev.Up.Now {
delta.Y -= playerSpeed
}
// Apply gravity.
// var onFloor bool
info, ok := doodads.CollidesWithGrid(s.Player, s.Level.Chunker, delta)
if ok {
// Collision happened with world.
}
delta = info.MoveTo
// Apply gravity if not grounded.
if !s.Player.Grounded() {
// Gravity has to pipe through the collision checker, too, so it
// can't give us a cheated downward boost.
delta.Y += gravity
2018-06-21 02:00:46 +00:00
}
s.Player.MoveTo(delta)
2018-06-21 02:00:46 +00:00
}
// LoadLevel loads a level from disk.
func (s *PlayScene) LoadLevel(filename string) error {
s.Filename = filename
2018-06-21 02:00:46 +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
s.Level = level
s.drawing.LoadLevel(s.Level)
2018-10-21 02:49:59 +00:00
s.drawing.InstallActors(s.Level.Actors)
s.drawing.AddActor(s.Player)
2018-06-21 02:00:46 +00:00
return nil
}
// Destroy the scene.
func (s *PlayScene) Destroy() error {
return nil
}