Improvements to the Debug Overlay Feature
* Scenes can insert custom key/value labels to the debug overlay and track string variables in real time * Added ability to unthrottle FPS in main loop
This commit is contained in:
parent
bd3dd41cea
commit
8fc4f39da0
7
docs/Shell.md
Normal file
7
docs/Shell.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Developer Console
|
||||
|
||||
## Cheats
|
||||
|
||||
| Cheat Code | Effect |
|
||||
|-------------------|--------------------------------|
|
||||
| unleash the beast | Disable frame rate throttling. |
|
|
@ -9,6 +9,16 @@ var (
|
|||
// Speed to scroll a canvas with arrow keys in Edit Mode.
|
||||
CanvasScrollSpeed int32 = 8
|
||||
|
||||
// Window scrolling behavior in Play Mode.
|
||||
ScrollboxHoz = 64 // horizontal px from window border to start scrol
|
||||
ScrollboxVert = 128
|
||||
ScrollMaxVelocity = 24
|
||||
|
||||
// Player speeds
|
||||
PlayerMaxVelocity = 12
|
||||
PlayerAcceleration = 2
|
||||
Gravity = 2
|
||||
|
||||
// Default chunk size for canvases.
|
||||
ChunkSize = 128
|
||||
|
||||
|
|
|
@ -22,6 +22,17 @@ func (c Command) Run(d *Doodle) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Cheat codes
|
||||
if c.Raw == "unleash the beast" {
|
||||
if fpsDoNotCap {
|
||||
d.Flash("Reset frame rate throttle to factory default FPS")
|
||||
} else {
|
||||
d.Flash("Unleashing as many frames as we can render!")
|
||||
}
|
||||
fpsDoNotCap = !fpsDoNotCap
|
||||
return nil
|
||||
}
|
||||
|
||||
switch c.Command {
|
||||
case "echo":
|
||||
d.Flash(c.ArgsLiteral)
|
||||
|
|
|
@ -148,13 +148,15 @@ func (d *Doodle) Run() error {
|
|||
}
|
||||
|
||||
// Delay to maintain the target frames per second.
|
||||
elapsed := time.Now().Sub(start)
|
||||
tmp := elapsed / time.Millisecond
|
||||
var delay uint32
|
||||
if TargetFPS-int(tmp) > 0 { // make sure it won't roll under
|
||||
delay = uint32(TargetFPS - int(tmp))
|
||||
if !fpsDoNotCap {
|
||||
elapsed := time.Now().Sub(start)
|
||||
tmp := elapsed / time.Millisecond
|
||||
if TargetFPS-int(tmp) > 0 { // make sure it won't roll under
|
||||
delay = uint32(TargetFPS - int(tmp))
|
||||
}
|
||||
d.Engine.Delay(delay)
|
||||
}
|
||||
d.Engine.Delay(delay)
|
||||
|
||||
// Track how long this frame took to measure FPS over time.
|
||||
d.TrackFPS(delay)
|
||||
|
|
|
@ -32,6 +32,11 @@ type EditorScene struct {
|
|||
Level *level.Level
|
||||
Doodad *doodads.Doodad
|
||||
|
||||
// Custom debug overlay values.
|
||||
debTool *string
|
||||
debSwatch *string
|
||||
debWorldIndex *string
|
||||
|
||||
// Last saved filename by the user.
|
||||
filename string
|
||||
}
|
||||
|
@ -43,6 +48,16 @@ func (s *EditorScene) Name() string {
|
|||
|
||||
// Setup the editor scene.
|
||||
func (s *EditorScene) Setup(d *Doodle) error {
|
||||
// Debug overlay values.
|
||||
s.debTool = new(string)
|
||||
s.debSwatch = new(string)
|
||||
s.debWorldIndex = new(string)
|
||||
customDebugLabels = []debugLabel{
|
||||
{"Pixel", s.debWorldIndex},
|
||||
{"Tool", s.debTool},
|
||||
{"Swatch", s.debSwatch},
|
||||
}
|
||||
|
||||
// Initialize the user interface. It references the palette and such so it
|
||||
// must be initialized after those things.
|
||||
s.d = d
|
||||
|
@ -107,6 +122,11 @@ func (s *EditorScene) Setup(d *Doodle) error {
|
|||
|
||||
// Loop the editor scene.
|
||||
func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
||||
// Update debug overlay values.
|
||||
*s.debTool = s.UI.Canvas.Tool.String()
|
||||
*s.debSwatch = s.UI.Canvas.Palette.ActiveSwatch.Name
|
||||
*s.debWorldIndex = s.UI.Canvas.WorldIndexAt(s.UI.cursor).String()
|
||||
|
||||
// Has the window been resized?
|
||||
if resized := ev.Resized.Read(); resized {
|
||||
w, h := d.Engine.WindowSize()
|
||||
|
@ -262,6 +282,5 @@ func (s *EditorScene) SaveDoodad(filename string) error {
|
|||
|
||||
// Destroy the scene.
|
||||
func (s *EditorScene) Destroy() error {
|
||||
debugWorldIndex = render.Origin
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -164,11 +164,10 @@ func (u *EditorUI) Loop(ev *events.State) error {
|
|||
|
||||
// Update status bar labels.
|
||||
{
|
||||
debugWorldIndex = u.Canvas.WorldIndexAt(u.cursor)
|
||||
u.StatusMouseText = fmt.Sprintf("Rel:(%d,%d) Abs:(%s)",
|
||||
ev.CursorX.Now,
|
||||
ev.CursorY.Now,
|
||||
debugWorldIndex,
|
||||
*u.Scene.debWorldIndex,
|
||||
)
|
||||
u.StatusPaletteText = fmt.Sprintf("%s Tool",
|
||||
u.Canvas.Tool,
|
||||
|
|
57
pkg/fps.go
57
pkg/fps.go
|
@ -33,37 +33,72 @@ var (
|
|||
fpsFrames int
|
||||
fpsSkipped uint32
|
||||
fpsInterval uint32 = 1000
|
||||
fpsDoNotCap bool // remove the FPS delay cap in main loop
|
||||
|
||||
// XXX: some opt-in WorldIndex variables for the debug overlay.
|
||||
// This is the world pixel that the mouse cursor is over,
|
||||
// the Cursor + Scroll position of the canvas.
|
||||
debugWorldIndex render.Point
|
||||
// Custom labels for individual Scenes to add debug info.
|
||||
customDebugLabels []debugLabel
|
||||
)
|
||||
|
||||
type debugLabel struct {
|
||||
key string
|
||||
variable *string
|
||||
}
|
||||
|
||||
// DrawDebugOverlay draws the debug FPS text on the SDL canvas.
|
||||
func (d *Doodle) DrawDebugOverlay() {
|
||||
if !d.Debug || !DebugOverlay {
|
||||
if !DebugOverlay {
|
||||
return
|
||||
}
|
||||
|
||||
var framesSkipped = fmt.Sprintf("(skip: %dms)", fpsSkipped)
|
||||
if fpsDoNotCap {
|
||||
framesSkipped = "uncapped"
|
||||
}
|
||||
|
||||
var (
|
||||
darken = balance.DebugStrokeDarken
|
||||
Yoffset int32 = 20 // leave room for the menu bar
|
||||
Xoffset int32 = 5
|
||||
Xoffset int32 = 20
|
||||
keys = []string{
|
||||
" FPS:",
|
||||
"FPS:",
|
||||
"Scene:",
|
||||
"Pixel:",
|
||||
"Mouse:",
|
||||
}
|
||||
values = []string{
|
||||
fmt.Sprintf("%d (skip: %dms)", fpsCurrent, fpsSkipped),
|
||||
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
||||
d.Scene.Name(),
|
||||
debugWorldIndex.String(),
|
||||
fmt.Sprintf("%d,%d", d.event.CursorX.Now, d.event.CursorY.Now),
|
||||
}
|
||||
)
|
||||
|
||||
// Insert custom keys.
|
||||
for _, custom := range customDebugLabels {
|
||||
keys = append(keys, custom.key)
|
||||
if custom.variable == nil {
|
||||
values = append(values, "<nil>")
|
||||
} else if len(*custom.variable) == 0 {
|
||||
values = append(values, `""`)
|
||||
} else {
|
||||
values = append(values, *custom.variable)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the longest key to align the labels up.
|
||||
var longest int
|
||||
for _, key := range keys {
|
||||
if len(key) > longest {
|
||||
longest = len(key)
|
||||
}
|
||||
}
|
||||
|
||||
// Space pad the keys for alignment.
|
||||
for i, key := range keys {
|
||||
if len(key) < longest {
|
||||
key = strings.Repeat(" ", longest-len(key)) + key
|
||||
keys[i] = key
|
||||
}
|
||||
}
|
||||
|
||||
key := ui.NewLabel(ui.Label{
|
||||
Text: strings.Join(keys, "\n"),
|
||||
Font: render.Text{
|
||||
|
@ -97,7 +132,7 @@ func (d *Doodle) DrawDebugOverlay() {
|
|||
|
||||
// DrawCollisionBox draws the collision box around a Doodad.
|
||||
func (d *Doodle) DrawCollisionBox(actor doodads.Actor) {
|
||||
if !d.Debug || !DebugCollision {
|
||||
if !DebugCollision {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,12 @@ type PlayScene struct {
|
|||
d *Doodle
|
||||
drawing *uix.Canvas
|
||||
|
||||
// Custom debug labels.
|
||||
debPosition *string
|
||||
debViewport *string
|
||||
debScroll *string
|
||||
debWorldIndex *string
|
||||
|
||||
// Player character
|
||||
Player doodads.Actor
|
||||
}
|
||||
|
@ -34,6 +40,20 @@ func (s *PlayScene) Name() string {
|
|||
// Setup the play scene.
|
||||
func (s *PlayScene) Setup(d *Doodle) error {
|
||||
s.d = d
|
||||
|
||||
// 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.
|
||||
s.drawing = uix.NewCanvas(balance.ChunkSize, false)
|
||||
s.drawing.MoveTo(render.Origin)
|
||||
s.drawing.Resize(render.NewRect(int32(d.width), int32(d.height)))
|
||||
|
@ -63,6 +83,23 @@ func (s *PlayScene) Setup(d *Doodle) error {
|
|||
|
||||
// Loop the editor scene.
|
||||
func (s *PlayScene) Loop(d *Doodle, ev *events.State) error {
|
||||
// Update debug overlay values.
|
||||
*s.debWorldIndex = s.drawing.WorldIndexAt(render.NewPoint(ev.CursorX.Now, ev.CursorY.Now)).String()
|
||||
*s.debPosition = s.Player.Position().String()
|
||||
*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
|
||||
}
|
||||
}
|
||||
|
||||
// Switching to Edit Mode?
|
||||
if ev.KeyName.Read() == "e" {
|
||||
log.Info("Edit Mode, Go!")
|
||||
|
|
Loading…
Reference in New Issue
Block a user