level

package
v0.0.0-...-79996cc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 9, 2023 License: GPL-3.0 Imports: 33 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MapType uint64 = iota
	GridType
)

Types of chunks.

View Source
const PaletteSizeLimit = 256

Palettes are limited to uint8 in length, to aid image compression.

Variables

View Source
var (
	DefaultPaletteNames = []string{
		"Default",
		"Colored Pencil",
		"Blueprint",
		"Neon Bright",
	}

	DefaultPalettes = map[string]*Palette{
		"Default": {
			Swatches: []*Swatch{
				{
					Name:    "solid",
					Color:   render.MustHexColor("#777"),
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "decoration",
					Color:   render.MustHexColor("#CCC"),
					Pattern: "noise.png",
				},
				{
					Name:    "fire",
					Color:   render.Red,
					Fire:    true,
					Pattern: "marker.png",
				},
				{
					Name:    "water",
					Color:   render.MustHexColor("#09F"),
					Water:   true,
					Pattern: "bubbles.png",
				},
				{
					Name:      "semisolid",
					Color:     render.MustHexColor("#AAA"),
					SemiSolid: true,
					Pattern:   "ink.png",
				},
				{
					Name:    "hint",
					Color:   render.MustHexColor("#F0F"),
					Pattern: "marker.png",
				},
			},
		},

		"Colored Pencil": {
			Swatches: []*Swatch{
				{
					Name:    "darkstone",
					Color:   render.MustHexColor("#777"),
					Pattern: "noise.png",
					Solid:   true,
				},
				{
					Name:    "grass",
					Color:   render.DarkGreen,
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "dirt",
					Color:   render.MustHexColor("#960"),
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "stone",
					Color:   render.Grey,
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "sandstone",
					Color:   render.RGBA(215, 114, 44, 255),
					Solid:   true,
					Pattern: "perlin-noise.png",
				},
				{
					Name:      "planks",
					Color:     render.MustHexColor("#B80"),
					SemiSolid: true,
					Pattern:   "marker.png",
				},
				{
					Name:    "fire",
					Color:   render.Red,
					Fire:    true,
					Pattern: "marker.png",
				},
				{
					Name:    "water",
					Color:   render.RGBA(0, 153, 255, 255),
					Water:   true,
					Pattern: "bubbles.png",
				},
				{
					Name:     "ice",
					Color:    render.MustHexColor("#099"),
					Solid:    true,
					Slippery: true,
					Pattern:  "marker.png",
				},
				{
					Name:    "hint",
					Color:   render.MustHexColor("#F0F"),
					Pattern: "marker.png",
				},
			},
		},

		"Neon Bright": {
			Swatches: []*Swatch{
				{
					Name:    "ground",
					Color:   render.MustHexColor("#FFE"),
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "grass green",
					Color:   render.Green,
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "fire",
					Color:   render.MustHexColor("#F90"),
					Pattern: "marker.png",
				},
				{
					Name:      "electricity",
					Color:     render.Yellow,
					SemiSolid: true,
					Pattern:   "perlin.png",
				},
				{
					Name:    "water",
					Color:   render.MustHexColor("#09F"),
					Pattern: "bubbles.png",
				},
				{
					Name:     "ice blue",
					Color:    render.MustHexColor("#0FF"),
					Solid:    true,
					Slippery: true,
					Pattern:  "marker.png",
				},
				{
					Name:    "hint",
					Color:   render.Magenta,
					Pattern: "marker.png",
				},
			},
		},

		"Blueprint": {
			Swatches: []*Swatch{
				{
					Name:    "solid",
					Color:   render.RGBA(254, 254, 254, 255),
					Solid:   true,
					Pattern: "noise.png",
				},
				{
					Name:    "decoration",
					Color:   render.Grey,
					Pattern: "noise.png",
				},
				{
					Name:    "fire",
					Color:   render.RGBA(255, 80, 0, 255),
					Fire:    true,
					Pattern: "bubbles.png",
				},
				{
					Name:    "water",
					Color:   render.RGBA(0, 153, 255, 255),
					Water:   true,
					Pattern: "bubbles.png",
				},
				{
					Name:     "ice",
					Color:    render.MustHexColor("#FAF"),
					Solid:    true,
					Slippery: true,
					Pattern:  "marker.png",
				},
				{
					Name:      "electric",
					Color:     render.RGBA(255, 255, 0, 255),
					SemiSolid: true,
					Pattern:   "marker.png",
				},
				{
					Name:    "hint",
					Color:   render.MustHexColor("#F0F"),
					Pattern: "marker.png",
				},
			},
		},
	}
)

Some choice of palettes.

View Source
var (
	DefaultWallpaper = "notebook.png"
)

Useful variables.

Functions

func ChunkInZipfile

func ChunkInZipfile(zf *zip.Reader, layer int, coord render.Point) bool

ChunkInZipfile tests whether the chunk exists in the zipfile.

func ChunksInZipfile

func ChunksInZipfile(zf *zip.Reader, layer int) []render.Point

ChunksInZipfile returns the list of chunk coordinates in a zipfile.

func ListSystemLevels

func ListSystemLevels() ([]string, error)

ListSystemLevels returns a list of built-in levels.

Types

type Accessor

type Accessor interface {
	Inflate(*Palette) error
	Iter() <-chan Pixel
	IterViewport(viewport render.Rect) <-chan Pixel
	Get(render.Point) (*Swatch, error)
	Set(render.Point, *Swatch) error
	Delete(render.Point) error
	Len() int
	MarshalBinary() ([]byte, error)
	UnmarshalBinary([]byte) error
	MarshalJSON() ([]byte, error)
	UnmarshalJSON([]byte) error
}

Accessor provides a high-level API to interact with absolute pixel coordinates while abstracting away the details of how they're stored.

type Actor

type Actor struct {
	Filename string             `json:"filename"` // like "exit.doodad"
	Point    render.Point       `json:"point"`
	Links    []string           `json:"links,omitempty"` // IDs of linked actors
	Options  map[string]*Option `json:"options,omitempty"`
	// contains filtered or unexported fields
}

Actor is an instance of a Doodad in the level.

func NewActor

func NewActor(a Actor) *Actor

NewActor initializes a level.Actor.

func (a *Actor) AddLink(id string)

AddLink adds a linked Actor to an Actor. Add the linked actor by its ID.

func (*Actor) ID

func (a *Actor) ID() string

ID returns the actor's ID.

func (*Actor) IsLinked

func (a *Actor) IsLinked(id string) bool

IsLinked checks if the actor is linked to the other actor's ID.

func (*Actor) SetOption

func (a *Actor) SetOption(name, dataType, v string) string

SetOption sets an actor option, safely.

func (a *Actor) Unlink(id string)

Unlink removes the linked actor's ID.

type ActorMap

type ActorMap map[string]*Actor

ActorMap holds the doodad information by their ID in the level data.

func (ActorMap) Add

func (m ActorMap) Add(a *Actor)

Add a new Actor to the map. If it doesn't already have an ID it will be given a random UUIDv4 ID.

func (ActorMap) Inflate

func (m ActorMap) Inflate()

Inflate assigns each actor its ID from the hash map for their self reference.

func (ActorMap) Remove

func (m ActorMap) Remove(a *Actor) bool

Remove an Actor from the map. The ID must be set at the very least, so to remove by ID just create an Actor{id: x}

type Base

type Base struct {
	Version     int    `json:"version"`     // File format version spec.
	GameVersion string `json:"gameVersion"` // Game version that created the level.
	Title       string `json:"title"`
	Author      string `json:"author"`
	Locked      bool   `json:"locked"`

	// v2 level format: zip files with external chunks.
	// (v0 was json text, v1 was gzip compressed json text).
	// The game must load levels created using the previous
	// formats, they will not have a Zipfile and will have
	// Chunkers in memory from their (gz) json.
	Zipfile *zip.Reader `json:"-"`

	// Every drawing type is able to embed other files inside of itself.
	Files *FileSystem `json:"files,omitempty"`
}

Base provides the common struct keys that are shared between Levels and Doodads.

type Chunk

type Chunk struct {
	Type uint64 // map vs. 2D array.
	Accessor

	// Values told to it from higher up, not stored in JSON.
	Point render.Point
	Size  uint8
	// contains filtered or unexported fields
}

Chunk holds a single portion of the pixel canvas.

func ChunkFromZipfile

func ChunkFromZipfile(zf *zip.Reader, layer int, coord render.Point) (*Chunk, error)

ChunkFromZipfile loads a chunk from a zipfile.

func NewChunk

func NewChunk() *Chunk

NewChunk creates a new chunk.

func (*Chunk) CachedBitmap

func (c *Chunk) CachedBitmap(mask render.Color) image.Image

CachedBitmap returns a cached render of the chunk as a bitmap image.

This is like Texture() but skips the step of actually producing an (SDL2) texture. The benefit of this is that you can call it from your non-main threads and offload the bitmap work into background tasks, then when SDL2 needs the Texture, the cached bitmap is immediately there saving time on the main thread.

func (*Chunk) Delete

func (c *Chunk) Delete(p render.Point) error

Delete proxies to the accessor and flags the texture as dirty and marks the chunk "Modified".

func (*Chunk) IsModified

func (c *Chunk) IsModified() bool

IsModified returns the chunk's Modified flag. This is most likely to occur in the Editor when the user is drawing onto the level. Modified chunks are not unloaded from memory ever, until they can be saved back to disk in the Zipfile format. During regular gameplay, chunks are loaded and unloaded as needed.

The modified flag is flipped on Set() or Delete() and is never unflipped. On file save, the Chunker is reloaded from scratch to hold chunks cached from zipfile members.

func (*Chunk) MarshalBinary

func (c *Chunk) MarshalBinary() ([]byte, error)

MarshalBinary encodes a chunk to binary format.

The binary format consists of one Uvarint for the chunk Type and then followed by whatever binary representation that chunk type encodes its data with.

func (*Chunk) MarshalJSON

func (c *Chunk) MarshalJSON() ([]byte, error)

MarshalJSON writes the chunk to JSON.

DEPRECATED: MarshalBinary will encode chunks to a tighter binary format.

func (*Chunk) Rect

func (c *Chunk) Rect() render.Rect

Rect returns the bounding coordinates that the Chunk has pixels for.

func (*Chunk) Set

func (c *Chunk) Set(p render.Point, sw *Swatch) error

Set proxies to the accessor and flags the texture as dirty.

It also marks the chunk as "Modified" so it will be kept in memory until the drawing is next saved to disk and the chunk written out to the zipfile.

func (*Chunk) SetDirty

func (c *Chunk) SetDirty()

SetDirty sets the `dirty` flag to true and forces the texture to be re-computed next frame.

func (*Chunk) SizePositive

func (c *Chunk) SizePositive() render.Rect

SizePositive returns the Size anchored to 0,0 with only positive coordinates.

func (*Chunk) Teardown

func (c *Chunk) Teardown() int

Teardown the chunk and free (SDL2) texture memory in ways Go can not by itself. Returns the number of textures freed.

func (*Chunk) Texture

func (c *Chunk) Texture(e render.Engine) render.Texturer

Texture will return a cached texture for the rendering engine for this chunk's pixel data. If the cache is dirty it will be rebuilt in this func.

Texture cache can be disabled with balance.DisableChunkTextureCache=true.

func (*Chunk) TextureMasked

func (c *Chunk) TextureMasked(e render.Engine, mask render.Color) render.Texturer

TextureMasked returns a cached texture with the ColorMask applied.

func (*Chunk) ToBitmap

func (c *Chunk) ToBitmap(mask render.Color) image.Image

ToBitmap exports the chunk's pixels as a bitmap image. NOT CACHED! This will always run the logic. Use Bitmap() if you want a cached bitmap image that only generates itself once, and again when marked dirty.

func (*Chunk) ToZipfile

func (c *Chunk) ToZipfile(zf *zip.Writer, layer int, coord render.Point) error

ToZipfile writes just a chunk's data into a zipfile.

It will write a file like "chunks/{layer}/{coord}.json" if using JSON format or a .bin file for binary format based on the BinaryChunkerEnabled game config constant.

func (*Chunk) UnmarshalBinary

func (c *Chunk) UnmarshalBinary(b []byte) error

UnmarshalBinary decodes a chunk from binary format.

func (*Chunk) UnmarshalJSON

func (c *Chunk) UnmarshalJSON(b []byte) error

UnmarshalJSON loads the chunk from JSON and uses the correct accessor to parse the inner details.

DEPRECATED in favor of binary marshalling.

func (*Chunk) Usage

func (c *Chunk) Usage(size int) float64

Usage returns the percent of free space vs. allocated pixels in the chunk.

type ChunkMap

type ChunkMap map[render.Point]*Chunk

ChunkMap maps a chunk coordinate to its chunk data.

func (ChunkMap) MarshalJSON

func (c ChunkMap) MarshalJSON() ([]byte, error)

MarshalJSON to convert the chunk map to JSON. This is needed for writing so the JSON encoder knows how to serializes a `map[Point]*Chunk` but the inverse is not necessary to implement.

type Chunker

type Chunker struct {
	// Layer is optional for the caller, levels use only 0 and
	// doodads use them for frames. When chunks are exported to
	// zipfile the Layer keeps them from overlapping.
	Layer int   `json:"-"` // internal use only
	Size  uint8 `json:"size"`

	// A Zipfile reference for new-style levels and doodads which
	// keep their chunks in external parts of a zip file.
	Zipfile *zip.Reader `json:"-"`

	// Chunks, oh boy.
	// The v1 drawing format had all the chunks in the JSON file.
	// New drawings write them to zips. Legacy drawings can be converted
	// simply by loading and resaving: their Chunks loads from JSON and
	// is committed to zipfile on save. This makes Chunks also a good
	// cache even when we have a zipfile to fall back on.
	Chunks ChunkMap `json:"chunks"`
	// contains filtered or unexported fields
}

Chunker is the data structure that manages the chunks of a level, and provides the API to interact with the pixels using their absolute coordinates while abstracting away the underlying details.

func NewChunker

func NewChunker(size uint8) *Chunker

NewChunker creates a new chunk manager with a given chunk size.

func (*Chunker) Bounds

func (c *Chunker) Bounds() (low, high render.Point)

Bounds returns the boundary points of the lowest and highest chunk which have any data in them.

func (*Chunker) CacheSize

func (c *Chunker) CacheSize() int

CacheSize returns the number of chunks in memory.

func (*Chunker) ChunkCoordinate

func (c *Chunker) ChunkCoordinate(abs render.Point) render.Point

ChunkCoordinate computes a chunk coordinate from an absolute coordinate.

func (*Chunker) ClearChunkCache

func (c *Chunker) ClearChunkCache()

ClearChunkCache completely flushes the ChunkMap from memory. BE CAREFUL. If the level is a Zipfile the chunks will reload as needed, but old style levels this will nuke the whole drawing!

func (*Chunker) Delete

func (c *Chunker) Delete(p render.Point) error

Delete a pixel at the given coordinate.

func (*Chunker) DeleteRect

func (c *Chunker) DeleteRect(r render.Rect) error

DeleteRect deletes a rectangle of pixels between two points. The rect is a relative one with a width and height, and the X,Y values are an absolute world coordinate.

func (*Chunker) FreeCaches

func (c *Chunker) FreeCaches() int

FreeCaches unloads chunks that have not been requested in 2 frames.

Only on chunkers that have zipfiles, old-style levels without zips wouldn't be able to restore their chunks otherwise! Returns -1 if no Zipfile, otherwise number of chunks freed.

func (*Chunker) FreeChunk

func (c *Chunker) FreeChunk(p render.Point) bool

FreeChunk unloads a chunk from active memory for zipfile-backed levels.

Not thread safe: it is assumed the caller has the lock on c.Chunks.

func (*Chunker) GCSize

func (c *Chunker) GCSize() int

GCSize returns the number of chunks pending free (not accessed in 2+ ticks)

func (*Chunker) Get

func (c *Chunker) Get(p render.Point) (*Swatch, error)

Get a pixel at the given coordinate. Returns the Palette entry for that pixel or else returns an error if not found.

func (*Chunker) GetChunk

func (c *Chunker) GetChunk(p render.Point) (*Chunk, bool)

GetChunk gets a chunk at a certain position. Returns false if not found.

This should be the centralized function to request a Chunk from the Chunker (or IterChunksThemselves). On old-style levels all of the chunks were just in memory as part of the JSON struct, in Zip files we can load/unload them at will from external files.

func (*Chunker) Inflate

func (c *Chunker) Inflate(pal *Palette) error

Inflate iterates over the pixels in the (loaded) chunks and expands any Sparse Swatches (which have only their palette index, from the file format on disk) to connect references to the swatches in the palette.

func (*Chunker) IterCachedChunks

func (c *Chunker) IterCachedChunks() <-chan *Chunk

IterCachedChunks iterates ONLY over the chunks currently cached in memory, e.g. so they can be torn down without loading extra chunks by looping normally.

func (*Chunker) IterChunks

func (c *Chunker) IterChunks() <-chan render.Point

IterChunks returns a channel to iterate over all chunks in the drawing.

func (*Chunker) IterChunksThemselves

func (c *Chunker) IterChunksThemselves() <-chan *Chunk

IterChunksThemselves iterates all chunks in the drawing rather than coords.

Note: this will mark every chunk as "touched" this frame, so in a zipfile level will load ALL chunks into memory.

func (*Chunker) IterPixels

func (c *Chunker) IterPixels() <-chan Pixel

IterPixels returns a channel to iterate over every pixel in the entire chunker.

func (*Chunker) IterViewport

func (c *Chunker) IterViewport(viewport render.Rect) <-chan Pixel

IterViewport returns a channel to iterate every point that exists within the viewport rect.

func (*Chunker) IterViewportChunks

func (c *Chunker) IterViewportChunks(viewport render.Rect) <-chan render.Point

IterViewportChunks returns a channel to iterate over the Chunk objects that appear within the viewport rect, instead of the pixels in each chunk.

func (*Chunker) MigrateZipfile

func (c *Chunker) MigrateZipfile(zf *zip.Writer) error

MigrateZipfile is called on save to migrate old-style ChunkMap chunks into external zipfile members and free up space in the master Level or Doodad struct.

func (*Chunker) Prerender

func (c *Chunker) Prerender()

Prerender visits every chunk and fetches its texture, in order to pre-load the whole drawing for smooth gameplay rather than chunks lazy rendering as they enter the screen.

func (*Chunker) PrerenderN

func (c *Chunker) PrerenderN(n int) (remaining int)

PrerenderN will pre-render the texture for N number of chunks and then yield back to the caller. Returns the number of chunks that still need textures rendered; zero when the last chunk has been prerendered.

func (*Chunker) Redraw

func (c *Chunker) Redraw()

Redraw marks every chunk as dirty and invalidates all their texture caches, forcing the drawing to re-generate from scratch.

func (*Chunker) Set

func (c *Chunker) Set(p render.Point, sw *Swatch) error

Set a pixel at the given coordinate.

func (*Chunker) SetChunk

func (c *Chunker) SetChunk(p render.Point, chunk *Chunk)

SetChunk writes the chunk into the cache dict and nothing more.

This function should be the singular writer to the chunk cache.

func (*Chunker) SetRect

func (c *Chunker) SetRect(r render.Rect, sw *Swatch) error

SetRect sets a rectangle of pixels to a color all at once.

func (*Chunker) WorldSize

func (c *Chunker) WorldSize() render.Rect

WorldSize returns the bounding coordinates that the Chunker has chunks to manage: the lowest pixels from the lowest chunks to the highest pixels of the highest chunks.

func (*Chunker) WorldSizePositive

func (c *Chunker) WorldSizePositive() render.Rect

WorldSizePositive returns the WorldSize anchored to 0,0 with only positive coordinates.

type File

type File struct {
	Data []byte `json:"data,omitempty"`
}

File holds details about a file in the FileSystem.

type FileSystem

type FileSystem struct {
	Zipfile *zip.Reader `json:"-"` // New Zipfile format accessor
	// contains filtered or unexported fields
}

FileSystem embeds a map of files inside a parent drawing.

Old-style drawings this was a map of filenames to their data in the JSON. New-style drawings this just holds the filenames and the data is read from the zipfile on demand.

func NewFileSystem

func NewFileSystem() *FileSystem

NewFileSystem initializes the FileSystem struct.

func (*FileSystem) Checksum

func (fs *FileSystem) Checksum(filename string) (string, error)

Checksum returns a SHA-256 checksum of a file's data.

func (*FileSystem) Delete

func (fs *FileSystem) Delete(filename string)

Delete a file from the FileSystem. This will store zero bytes in the legacy file map structure to mark it for deletion. On the next save, filemap files with zero bytes skip the ZIP archive.

func (*FileSystem) Get

func (fs *FileSystem) Get(filename string) ([]byte, error)

Get a file from the FileSystem.

func (*FileSystem) List

func (fs *FileSystem) List() []string

List files in the FileSystem, including the ZIP file.

In the ZIP file, attachments are under the "assets/" prefix so this function won't mistakenly return chunks or level.json/doodad.json.

func (*FileSystem) ListPrefix

func (fs *FileSystem) ListPrefix(prefix string) []string

ListPrefix returns a list of files starting with the prefix.

func (*FileSystem) MigrateZipfile

func (fs *FileSystem) MigrateZipfile(zf *zip.Writer) error

MigrateZipfile is called on save to write attached files to the ZIP file format.

func (*FileSystem) Set

func (fs *FileSystem) Set(filename string, data []byte)

Set a file into the FileSystem. Note: it will go into the legacy map structure until the next save to disk, at which point queued files are committed to ZIP.

func (*FileSystem) UnmarshalJSON

func (fs *FileSystem) UnmarshalJSON(text []byte) error

UnmarshalJSON reads in a FileSystem from its legacy JSON representation.

type GameRule

type GameRule struct {
	Difficulty enum.Difficulty `json:"difficulty"`
	Survival   bool            `json:"survival,omitempty"`
}

GameRule

type JSONChunk

type JSONChunk struct {
	Type    uint64          `json:"type"`
	Data    json.RawMessage `json:"data"`
	BinData interface{}     `json:"-"`
}

JSONChunk holds a lightweight (interface-free) copy of the Chunk for unmarshalling JSON files from disk.

type Level

type Level struct {
	Base
	Password string   `json:"passwd"`
	UUID     string   `json:"uuid"` // unique level IDs, especially for the savegame.json
	GameRule GameRule `json:"rules"`

	// Chunked pixel data.
	Chunker *Chunker `json:"chunks"`

	// The Palette holds the unique "colors" used in this map file, and their
	// properties (solid, fire, slippery, etc.)
	Palette *Palette `json:"palette"`

	// Page boundaries and wallpaper settings.
	PageType  PageType `json:"pageType"`
	MaxWidth  int64    `json:"boundedWidth"` // only if bounded or bordered
	MaxHeight int64    `json:"boundedHeight"`
	Wallpaper string   `json:"wallpaper"`

	// The last scrolled position in the editor.
	ScrollPosition render.Point `json:"scroll"`

	// Actors keep a list of the doodad instances in this map.
	Actors ActorMap `json:"actors"`

	// Publishing: attach any custom doodads the map uses on save.
	SaveDoodads  bool `json:"saveDoodads"`
	SaveBuiltins bool `json:"saveBuiltins"`

	// Signature for a level with embedded doodads to still play in free mode.
	Signature []byte `json:"signature,omitempty"`

	// Undo history, temporary live data not persisted to the level file.
	UndoHistory *drawtool.History `json:"-"`
}

Level is the container format for Doodle map drawings.

func FromGzip

func FromGzip(data []byte) (*Level, error)

FromGzip deserializes a gzip compressed level JSON.

func FromJSON

func FromJSON(filename string, data []byte) (*Level, error)

FromJSON loads a level from "JSON string" (gzip supported).

This is the primary "load level from file on disk" method. It can read levels of all historical file formats the game supported:

  • If the data begins with a `{` it is parsed in the legacy (v1) JSON format.
  • If the level begins with a Gzip header (hex `1F8B“) it is taken to be a gzip compressed (v2) level JSON file.
  • If the file is identified by `net/http#DetectContentType()` to be an application/zip file (v3) it is loaded from zipfile format.

func FromZipfile

func FromZipfile(data []byte) (*Level, error)

FromZipfile reads a level in zipfile format.

func LoadFile

func LoadFile(filename string) (*Level, error)

LoadFile reads a level file from disk, checking a few locations.

func LoadJSON

func LoadJSON(filename string) (*Level, error)

LoadJSON loads a map from JSON file (gzip supported).

func New

func New() *Level

New creates a blank level object with all its members initialized.

func (*Level) AsJSON

func (m *Level) AsJSON() ([]byte, error)

AsJSON returns it just as JSON without any fancy gzip/zip magic.

func (*Level) DeleteFile

func (l *Level) DeleteFile(filename string) bool

DeleteFile removes an embedded file.

func (*Level) DeleteFiles

func (l *Level) DeleteFiles(prefix string) int

DeleteFiles removes all files beginning with the prefix.

func (*Level) GetFile

func (l *Level) GetFile(filename string) ([]byte, error)

GetFile looks up an embedded file.

func (*Level) Inflate

func (l *Level) Inflate()

Inflate the level from its compressed JSON form.

This is called as part of the LoadJSON function when the level is read from disk. In the JSON format, pixels in the level refer to the palette by its index number.

This function calls the following:

  • Chunker.Inflate(Palette) to update references to the level's pixels to point to the Swatch entry.
  • Actors.Inflate()
  • Palette.Inflate() to load private instance values for the palette subsystem.

func (*Level) ListFiles

func (l *Level) ListFiles() []string

ListFiles returns the list of all embedded file names, alphabetically.

func (*Level) ListFilesAt

func (l *Level) ListFilesAt(prefix string) []string

ListFilesAt returns the list of files having a common prefix.

func (*Level) Loop

func (m *Level) Loop() error

Loop may be called each loop to allow the level to maintain its memory usage, e.g., for chunks not requested recently from a zipfile level to free those from RAM.

func (m *Level) PruneLinks() int

PruneLinks cleans up any Actor Links that can not be resolved in the level data. For example, if actors were linked in Edit Mode and one actor is deleted leaving a broken link.

Returns the number of broken links pruned.

This is called automatically in WriteFile.

func (*Level) ReloadZipfile

func (m *Level) ReloadZipfile(data []byte) error

ReloadZipfile re-reads the level's zipfile after a write.

func (*Level) ReplacePalette

func (l *Level) ReplacePalette(pal *Palette)

ReplacePalette installs a new palette into your level. Your existing level colors, by index, are replaced by the incoming palette. If the new palette is smaller, extraneous indices are left alone.

func (*Level) SetFile

func (l *Level) SetFile(filename string, data []byte)

SetFile sets a file's data in the level.

func (*Level) Teardown

func (m *Level) Teardown()

Teardown the level when the game is done with it. This frees up SDL2 cached texture chunks and reclaims memory in ways the Go garbage collector can not.

func (*Level) ToGzip

func (m *Level) ToGzip() ([]byte, error)

ToGzip serializes the level as gzip compressed JSON.

func (*Level) ToJSON

func (m *Level) ToJSON() ([]byte, error)

ToJSON serializes the level as JSON (gzip supported).

This is the primary "write level to disk" function and can output in a vairety of historical formats controlled by pkg/balance#DrawingFormat:

  • balance.FormatJSON (the default): writes the level as an original-style single JSON document that contains all chunk data directly. These levels take a long time to load from disk for any non-trivial level design. (v1)
  • balance.FormatGzip: writes as a gzip compressed JSON file (v2)
  • balance.FormatZipfile: creates a zip file where most of the level JSON is stored as "index.json" and chunks and attached doodads are separate members of the zipfile.

Notice about gzip: if the pkg/balance.CompressLevels boolean is true, this function will apply gzip compression before returning the byte string. This gzip-compressed level can be read back by any functions that say "gzip supported" in their descriptions.

func (*Level) ToZipfile

func (m *Level) ToZipfile() ([]byte, error)

ToZipfile serializes the level as a ZIP archive and also migrates data loaded from an older save into the new zip format.

func (*Level) WriteFile

func (m *Level) WriteFile(filename string) error

WriteFile saves a level to disk in the user's config directory.

func (*Level) WriteJSON

func (m *Level) WriteJSON(filename string) error

WriteJSON writes a level to JSON on disk.

type MapAccessor

type MapAccessor struct {
	// contains filtered or unexported fields
}

MapAccessor implements a chunk accessor by using a map of points to their palette indexes. This is the simplest accessor and is best for sparse chunks.

func NewMapAccessor

func NewMapAccessor() *MapAccessor

NewMapAccessor initializes a MapAccessor.

func (*MapAccessor) Delete

func (a *MapAccessor) Delete(p render.Point) error

Delete a pixel from the map.

func (*MapAccessor) Get

func (a *MapAccessor) Get(p render.Point) (*Swatch, error)

Get a pixel from the map.

func (*MapAccessor) Inflate

func (a *MapAccessor) Inflate(pal *Palette) error

Inflate the sparse swatches from their palette indexes.

func (*MapAccessor) Iter

func (a *MapAccessor) Iter() <-chan Pixel

Iter returns a channel to loop over all points in this chunk.

func (*MapAccessor) IterViewport

func (a *MapAccessor) IterViewport(viewport render.Rect) <-chan Pixel

IterViewport returns a channel to loop over pixels in the viewport.

func (*MapAccessor) Len

func (a *MapAccessor) Len() int

Len returns the current size of the map, or number of pixels registered.

func (*MapAccessor) MarshalBinary

func (a *MapAccessor) MarshalBinary() ([]byte, error)

MarshalBinary converts the chunk data to a binary representation, for better compression compared to JSON.

In the binary format each chunk begins with one Varint (the chunk Type) followed by whatever wire format the chunk needs given its type.

This function is related to the CompressMapAccessor config constant: the MapAccessor compression boils down each point to a series if packed varints: the X, Y coord (varint) followed by palette index (Uvarint).

The output of this function is just the compressed MapAccessor stream.

func (*MapAccessor) MarshalJSON

func (a *MapAccessor) MarshalJSON() ([]byte, error)

MarshalJSON to convert the chunk map to JSON.

When serialized, the key is the "X,Y" coordinate and the value is the swatch index of the Palette, rather than redundantly serializing out the Swatch object for every pixel.

DEPRECATED: in the Zipfile format chunks will be saved as binary files instead of with their JSON wrappers, so MarshalJSON will be phased out.

func (*MapAccessor) Set

func (a *MapAccessor) Set(p render.Point, sw *Swatch) error

Set a pixel on the map.

func (*MapAccessor) UnmarshalBinary

func (a *MapAccessor) UnmarshalBinary(compressed []byte) error

UnmarshalBinary will decode a compressed MapAccessor byte stream.

func (*MapAccessor) UnmarshalJSON

func (a *MapAccessor) UnmarshalJSON(b []byte) error

UnmarshalJSON to convert the chunk map back from JSON.

DEPRECATED: in the Zipfile format chunks will be saved as binary files instead of with their JSON wrappers, so MarshalJSON will be phased out.

type Option

type Option struct {
	Type  string      `json:"type"` // bool, str, int
	Name  string      `json:"name"`
	Value interface{} `json:"value"`
}

Option for runtime, user configurable overrides of Doodad Options.

func (*Option) Set

func (o *Option) Set(v string) string

Set an option value. Generally do not call this yourself - use SetOption to safely set an option which will create the map value the first time.

type PageType

type PageType int

PageType configures the bounds and wallpaper behavior of a Level.

const (
	// Unbounded means the map can grow freely in any direction.
	// - Only the repeat texture is used for the wallpaper.
	Unbounded PageType = iota

	// NoNegativeSpace means the map is bounded at the top left edges.
	// - Can't scroll or visit any pixels in negative X,Y coordinates.
	// - Wallpaper shows the Corner at 0,0
	// - Wallpaper repeats the Top along the Y=0 plane
	// - Wallpaper repeats the Left along the X=0 plane
	// - The repeat texture fills the rest of the level.
	NoNegativeSpace

	// Bounded is the same as NoNegativeSpace but the level is imposing a
	// maximum cap on the width and height of the level.
	// - Can't scroll below X,Y origin at 0,0
	// - Can't scroll past the bounded width and height of the level
	Bounded

	// Bordered is like Bounded except the corner textures are wrapped
	// around the other edges of the level too.
	// - The wallpaper hoz mirrors Left along the X=Width plane
	// - The wallpaper vert mirrors Top along the Y=Width plane
	// - The wallpaper 180 rotates the Corner for opposite corners
	Bordered
)

PageType values.

func PageTypeFromString

func PageTypeFromString(name string) (PageType, bool)

PageTypeFromString returns a PageType from its string version.

func (PageType) String

func (p PageType) String() string

String converts the PageType to a string label.

type Palette

type Palette struct {
	Swatches []*Swatch `json:"swatches"`

	// Private runtime values
	ActiveSwatch *Swatch `json:"-"` // name of the actively selected color
	// contains filtered or unexported fields
}

Palette holds an index of colors used in a drawing.

func DefaultPalette

func DefaultPalette() *Palette

DefaultPalette returns a sensible default palette.

func NewBlueprintPalette

func NewBlueprintPalette() *Palette

NewBlueprintPalette returns the blueprint theme's color palette. DEPRECATED in favor of DefaultPalettes.

func NewPalette

func NewPalette() *Palette

NewPalette initializes a blank palette.

func (*Palette) AddSwatch

func (p *Palette) AddSwatch(swatch *Swatch) error

AddSwatch adds a new swatch to the palette.

func (*Palette) FlushCaches

func (p *Palette) FlushCaches()

FlushCaches if you have modified the swatches, especially if you have changed the name of an existing color. This invalidates the "by name" cache and rebuilds it from scratch.

func (*Palette) Get

func (p *Palette) Get(name string) (result *Swatch, exists bool)

Get a swatch by name.

func (*Palette) Inflate

func (p *Palette) Inflate()

Inflate the palette swatch caches. Always call this method after you have initialized the palette (i.e. loaded it from JSON); this will update the "color by name" cache and assign the index numbers to each swatch.

func (*Palette) NewSwatch

func (p *Palette) NewSwatch() (*Swatch, error)

NewSwatch adds a new swatch to the palette.

type Pixel

type Pixel struct {
	X            int `json:"x"`
	Y            int `json:"y"`
	PaletteIndex int `json:"p"`

	// Private runtime values.
	Swatch *Swatch `json:"-"` // pointer to its swatch, for when rendered.
}

Pixel associates a coordinate with a palette index.

func (Pixel) MarshalJSON

func (p Pixel) MarshalJSON() ([]byte, error)

MarshalJSON serializes a Pixel compactly as a simple list.

func (Pixel) Point

func (p Pixel) Point() render.Point

Point returns the pixel's point.

func (Pixel) String

func (p Pixel) String() string

func (*Pixel) UnmarshalJSON

func (p *Pixel) UnmarshalJSON(text []byte) error

UnmarshalJSON loads a Pixel from JSON again.

type Swatch

type Swatch struct {
	Name    string       `json:"name"`
	Color   render.Color `json:"color"`
	Pattern string       `json:"pattern"` // like "noise.png"

	// Optional attributes.
	Solid     bool `json:"solid,omitempty"`
	SemiSolid bool `json:"semisolid,omitempty"`
	Fire      bool `json:"fire,omitempty"`
	Water     bool `json:"water,omitempty"`
	Slippery  bool `json:"slippery,omitempty"`
	// contains filtered or unexported fields
}

Swatch holds details about a single value in the palette.

func NewSparseSwatch

func NewSparseSwatch(paletteIndex int) *Swatch

NewSparseSwatch creates a sparse Swatch from a palette index that will need later expansion, when loading drawings from disk.

func (*Swatch) Attributes

func (s *Swatch) Attributes() string

Attributes returns a comma-separated list of attributes as a string on this swatch. This is for debugging and the `doodad show` CLI command to summarize the swatch and shouldn't be used for game logic.

func (*Swatch) Index

func (s *Swatch) Index() int

Index returns the Swatch's position in the palette.

func (*Swatch) IsSparse

func (s *Swatch) IsSparse() bool

IsSparse returns whether this Swatch is sparse (has only a palette index) and requires inflation.

func (Swatch) String

func (s Swatch) String() string

Directories

Path Synopsis
Package publishing contains functionality for "publishing" a Level, which involves the writing and reading of custom doodads embedded inside the levels.
Package publishing contains functionality for "publishing" a Level, which involves the writing and reading of custom doodads embedded inside the levels.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL