Prepare v0.12.1 for release
This commit is contained in:
parent
c5353df211
commit
9cdc7260bb
32
Changes.md
32
Changes.md
|
@ -1,5 +1,37 @@
|
|||
# Changes
|
||||
|
||||
## v0.12.1 (April 16 2022)
|
||||
|
||||
This update focuses on memory and performance improvements for the game.
|
||||
Some larger levels such as "Azulian Tag - Forest" could run out of
|
||||
memory on 32-bit systems. To improve on memory usage, the game more
|
||||
aggressively frees SDL2 textures when no longer needed and it doesn't
|
||||
try to keep the _whole_ level's chunks ready in memory (as rendered
|
||||
images) -- only the chunks near the window viewport are loaded, and
|
||||
chunks that leave the viewport are freed to reclaim memory. Improvements
|
||||
are still a work in progress.
|
||||
|
||||
New fields are added to the F3 debug overlay to peek at its performance:
|
||||
|
||||
* "Textures:" shows the count of SDL2 textures currently loaded
|
||||
in memory. Some textures, such as toolbar buttons and the
|
||||
loadscreen wallpaper, lazy load and persist in memory. Most level
|
||||
and doodad textures should free when the level exits.
|
||||
* "Sys/Heap:" shows current memory utilization in terms of MiB taken
|
||||
from the OS and MiB of active heap memory, respectively.
|
||||
* "Threads:" counts the number of goroutines currently active. In
|
||||
gameplay, each actor monitors its PubSub queue on a goroutine and
|
||||
these should clean up when the level exits.
|
||||
* "Chunks:" shows the count of level chunks inside and outside the
|
||||
loading viewport.
|
||||
|
||||
Some other changes and bug fixes in this release include:
|
||||
|
||||
* Fixed the bug where the player was able to "climb" vertical walls to
|
||||
their right.
|
||||
* When entering a cheat code that changes the default player character
|
||||
during gameplay, you immediately become that character.
|
||||
|
||||
## v0.12.0 (March 27 2022)
|
||||
|
||||
This update adds several new features to gameplay and the Level Editor.
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -88,6 +89,10 @@ func main() {
|
|||
Aliases: []string{"d"},
|
||||
Usage: "enable debug level logging",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pprof",
|
||||
Usage: "record pprof metrics to a filename",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "chdir",
|
||||
Usage: "working directory for the game's runtime package",
|
||||
|
@ -125,6 +130,23 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Recording pprof stats?
|
||||
if cpufile := c.String("pprof"); cpufile != "" {
|
||||
log.Info("Saving CPU profiling data to %s", cpufile)
|
||||
fh, err := os.Create(cpufile)
|
||||
if err != nil {
|
||||
log.Error("--pprof: can't create file: %s", err)
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
|
||||
if err := pprof.StartCPUProfile(fh); err != nil {
|
||||
log.Error("pprof: %s", err)
|
||||
return err
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
var filename string
|
||||
if c.NArg() > 0 {
|
||||
filename = c.Args().Get(0)
|
||||
|
|
|
@ -17,7 +17,7 @@ var (
|
|||
|
||||
// Debug overlay (FPS etc.) settings.
|
||||
DebugFontFilename = SansBoldFont
|
||||
DebugFontSize = 16
|
||||
DebugFontSize = 14
|
||||
DebugLabelColor = render.MustHexColor("#FF9900")
|
||||
DebugValueColor = render.MustHexColor("#00CCFF")
|
||||
DebugStrokeDarken = 80
|
||||
|
|
30
pkg/fps.go
30
pkg/fps.go
|
@ -2,6 +2,7 @@ package doodle
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
|
@ -38,6 +39,11 @@ var (
|
|||
fpsInterval uint32 = 1000
|
||||
fpsDoNotCap bool // remove the FPS delay cap in main loop
|
||||
|
||||
// Memory usage metrics.
|
||||
memHeap uint64 // Current heap memory size (shrinks on GC)
|
||||
memSys uint64 // Current total memory usage
|
||||
numGoroutine int
|
||||
|
||||
// Custom labels for individual Scenes to add debug info.
|
||||
customDebugLabels []debugLabel
|
||||
)
|
||||
|
@ -72,13 +78,17 @@ func (d *Doodle) DrawDebugOverlay() {
|
|||
"FPS:",
|
||||
"Scene:",
|
||||
"Mouse:",
|
||||
"Tex:",
|
||||
"Textures:",
|
||||
"Sys/Heap:",
|
||||
"Threads:",
|
||||
}
|
||||
values = []string{
|
||||
fmt.Sprintf("%d %s", fpsCurrent, framesSkipped),
|
||||
d.Scene.Name(),
|
||||
fmt.Sprintf("%d,%d", d.event.CursorX, d.event.CursorY),
|
||||
texCount,
|
||||
fmt.Sprintf("%d MiB / %d MiB", memSys, memHeap),
|
||||
fmt.Sprintf("%d", numGoroutine),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -202,4 +212,22 @@ func (d *Doodle) TrackFPS(skipped uint32) {
|
|||
|
||||
// FPS in the title bar.
|
||||
d.Engine.SetTitle(fmt.Sprintf("%s (%d FPS)", d.Title(), fpsCurrent))
|
||||
|
||||
// Refresh memory usage.
|
||||
GetMemUsage()
|
||||
}
|
||||
|
||||
// GetMemUsage collects statistics on memory utilization.
|
||||
func GetMemUsage() {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
|
||||
memHeap = bToMb(m.Alloc)
|
||||
memSys = bToMb(m.Sys)
|
||||
|
||||
numGoroutine = runtime.NumGoroutine()
|
||||
}
|
||||
|
||||
func bToMb(b uint64) uint64 {
|
||||
return b / 1024 / 1024
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ type MainScene struct {
|
|||
// happens one time, and does not re-adapt when the window is made
|
||||
// tall enough again.
|
||||
landscapeMode bool
|
||||
|
||||
// Debug F3 overlay vars
|
||||
debLoadingViewport *string
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -88,6 +91,11 @@ func (s *MainScene) Name() string {
|
|||
|
||||
// Setup the scene.
|
||||
func (s *MainScene) Setup(d *Doodle) error {
|
||||
s.debLoadingViewport = new(string)
|
||||
customDebugLabels = []debugLabel{
|
||||
{"Chunks:", s.debLoadingViewport},
|
||||
}
|
||||
|
||||
s.Supervisor = ui.NewSupervisor()
|
||||
|
||||
if err := s.SetupDemoLevel(d); err != nil {
|
||||
|
@ -405,6 +413,9 @@ func (s *MainScene) SetupDemoLevel(d *Doodle) error {
|
|||
func (s *MainScene) Loop(d *Doodle, ev *event.State) error {
|
||||
s.Supervisor.Loop(ev)
|
||||
|
||||
inside, outside := s.canvas.LoadUnloadMetrics()
|
||||
*s.debLoadingViewport = fmt.Sprintf("%d in %d out", inside, outside)
|
||||
|
||||
if err := s.scripting.Loop(); err != nil {
|
||||
log.Error("MainScene.Loop: scripting.Loop: %s", err)
|
||||
}
|
||||
|
|
|
@ -63,6 +63,12 @@ func ShowWithProgress() {
|
|||
visible = true
|
||||
withProgress = true
|
||||
subtitle = ""
|
||||
|
||||
// TODO: hide the progress trough. With the new LoadUnloadChunks,
|
||||
// the progress bar does nothing - all the loading time is spent
|
||||
// reading the level from disk and then it starts.
|
||||
withProgress = false
|
||||
|
||||
SetProgress(0)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user