doodle/pkg/balance/feature_flags.go
Noah Petherbridge 5654145fd8 (Experimental) Run Length Encoding for Levels
Finally add a second option for Chunk MapAccessor implementation besides the
MapAccessor. The RLEAccessor is basically a MapAccessor that will compress
your drawing with Run Length Encoding (RLE) in the on-disk format in the ZIP
file.

This slashes the file sizes of most levels:

* Shapeshifter: 21.8 MB -> 8.1 MB
* Jungle: 10.4 MB -> 4.1 MB
* Zoo: 2.8 MB -> 1.3 MB

Implementation details:

* The RLE binary format for Chunks is a stream of Uvarint pairs storing the
  palette index number and the number of pixels to repeat it (along the Y,X
  axis of the chunk).
    * Null colors are represented by a Uvarint that decodes to 0xFFFF
      or 65535 in decimal.
    * Gameplay logic currently limits maps to 256 colors.
* The default for newly created chunks in-game will be RLE by default.
* Its in-memory representation is still a MapAccessor (a map of absolute
  world coordinates to palette index).
* The game can still open and play legacy MapAccessor maps.
* On save in the editor, the game will upgrade/convert MapAccessor chunks over
  to RLEAccessors, improving on your level's file size with a simple re-save.

Current Bugs

* On every re-save to RLE, one pixel is lost in the bottom-right corner of
  each chunk. Each subsequent re-save loses one more pixel to the left, so what
  starts as a single pixel per chunk slowly evolves into a horizontal line.
* Some pixels smear vertically as well.
* Off-by-negative-one errors when some chunks Iter() their pixels but compute
  a relative coordinate of (-1,0)! Some mismatch between the stored world coords
  of a pixel inside the chunk vs. the chunk's assigned coordinate by the Chunker:
  certain combinations of chunk coord/abs coord.

To Do

* The `doodad touch` command should re-save existing levels to upgrade them.
2024-05-23 23:02:01 -07:00

80 lines
2.6 KiB
Go

package balance
// Hard-coded feature flags.
const (
// Enable "v1.5" compression in the MapAccessor Chunker.
//
// The original MapAccessor encodes a chunk to json using syntax like
// {"x,y": index} mapping coordinates to palette swatches.
//
// With compression on, it is encoded to a byte stream of x,y,index
// triplets. The game can read both formats and will follow this flag
// on all saves. NOTE: this applies to when we still use JSON format.
// If BinaryChunkerEnabled, map accessors are always compressed as they
// are written to .bin files instead of .json.
CompressMapAccessor = true
// Enable "v2" binary storage of Chunk data in Zipfiles.
//
// This is a separate toggle to the CompressMapAccessor. Some possible
// variations of these flags includes:
//
// - CompressMapAccessor=true alone, will write the compressed bytes
// still wrapped in the JSON format as a Base64 encoded string.
// - With BinaryChunkerEnabled=true: all chunks are encoded to
// binary and put in the zip as .bin instead of as .json files.
// MapAccessor is always compressed in binary mode.
//
// If you set both flags to false, level zipfiles will use the classic
// json chunk format as before on save.
BinaryChunkerEnabled = true
// Enable "v3" Run-Length Encoding for level chunker.
//
// This only supports Zipfile levels and will use the ".bin" format
// enabled by the previous setting.
RLEBinaryChunkerEnabled = true
)
// Feature Flags to turn on/off experimental content.
var Feature = feature{
/////////
// Experimental features that are off by default
ViewportWindow: false, // Open new viewport into your level
/////////
// Fully activated features
// Attach custom wallpaper img to levels
CustomWallpaper: true,
// Allow embedded doodads in levels.
EmbeddableDoodads: true,
// Enable the zoom in/out feature (kinda buggy still)
Zoom: true,
// Reassign an existing level's palette to a different builtin.
ChangePalette: true,
// LoadUnloadChunk feature to better optimize memory. Set it to false and the
// loadscreen will eager load all chunk bitmaps (stable, but uses a lot of
// memory), set true and the Canvas will load/unload bitmaps + free SDL textures
// for chunks falling outside the LoadingViewport (new, maybe unstable).
LoadUnloadChunk: true,
}
// FeaturesOn turns on all feature flags, from CLI --experimental option.
func FeaturesOn() {
Feature.ViewportWindow = true
}
type feature struct {
Zoom bool
CustomWallpaper bool
ChangePalette bool
EmbeddableDoodads bool
ViewportWindow bool
LoadUnloadChunk bool
}