Tilemaps and Aseprite
Aseprite files, their use in a running game, and TileMap nodes.
Files: aseprite.odin, aseprite_nodes.odin, tilemap.odin, inflate.odin.
File overviews
Section titled “File overviews”aseprite.odin
Section titled “aseprite.odin”Aseprite files (.aseprite, .ase; https://www.aseprite.org, the pixel art editor), read with
the published format (Aseprite’s docs/ase-file-specs.md), so sprites, animations and tilemaps
drawn in Aseprite play in the engine.
Aseprite_Load / Aseprite_Parse read a file into plain data (Aseprite):
- The sprite: size, color mode (RGBA, grayscale or indexed: every image is turned into RGBA pixels here, through the palette for indexed ones), its grid and its user data.
- Layers in Aseprite’s order, bottom first: image, group and tilemap layers, with their
parent group (
parent), visibility, opacity, blend mode and user data. - Frames with their duration (milliseconds; each frame has its own) and cels: a layer’s
image in that frame (
pixels, RGBA, atx,y), or a tilemap layer’s tiles. Linked cels are copies of the cel they link to. - Tags (named frame ranges: Aseprite’s animations), with direction, repeats and color; slices with their keys (9-patch centers, pivots); tilesets (tile size, the tiles’ pixels as one column of tiles, tile 0 the empty one, and each tile’s user data).
- User data: text, a color and properties (
AsepriteValue) of the sprite, layers, cels, tags, slices, tilesets and tiles. Only the user’s own properties are kept (not extensions’).
Aseprite_FramePixels composites a frame exactly as Aseprite exports it (checked byte for byte
against Aseprite 1.3.17’s own exports: aseprite_matches_aseprite): Aseprite’s render plan (layers
numbered in tree order, groups flattened unless the file says to composite them, sorted by number
plus each cel’s z-index), hidden layers and those in hidden groups left out, reference layers too,
cel opacity times layer opacity, Aseprite’s 19 blend modes with its integer arithmetic and its
default “new blending” (blend_funcs.cpp, ported), tilemap layers drawn from their tileset with each
tile’s flips. Aseprite 1.3.17 never writes the compose-groups flag (its compose-groups preference
only changes its own canvas), so files are flattened as its exports are; the composited path, for
files that do set it, couldn’t be checked against Aseprite.
Aseprite_SheetPixels lays every frame out on a grid (an animation’s sheet). Textures from
Aseprite files use nearest filtering: they’re pixel art.
Everything a file holds lives in its own arena: Aseprite_Destroy frees it all. Reading never
trusts the file: anything truncated or malformed is an error, not a crash.
aseprite_nodes.odin
Section titled “aseprite_nodes.odin”Aseprite files in a running game, beyond their pixels (aseprite.odin reads them):
- Slices (
Aseprite_SliceAt: a slice’s key for a frame):- a Sprite’s or AnimatedSprite’s
pivotSliceputs that slice’s pivot on the node’s origin, frame by frame (Sprite_Origin); - a Sprite’s
nineSlicedraws that 9-patch slice stretched tonineSize(the corners keep their size, the edges and middle stretch); - a CollisionShape’s
slicetakes that slice’s rectangle, frame by frame (hitboxes, hurtboxes, a sword’s reach): it follows the nearest Sprite or AnimatedSprite showing an Aseprite file (an ancestor, or a child of an ancestor), turns off where the slice is hidden, and rebuilds its body’s shapes when it changes.
- a Sprite’s or AnimatedSprite’s
- Frame events (
Aseprite_FrameEvents): a cel’s text in Aseprite (its Properties > User Data), or itseventproperty, on any layer (hidden ones too: an “events” layer works), is an event of that frame; an AnimatedSprite playing the file’s tags sends it throughanimation.onFrameEvent(data: the name) when the frame shows. - Layers (
asepriteLayers, the scene file’slayers): a Sprite or AnimatedSprite draws only the named layers (a group’s name brings its layers), so a body and its sword can be two nodes. Their textures are keyed<file>?layers=Body,Sword(with#sheetbefore it for a sheet). Game_LoadAsepritekeeps each file the game reads (Game.aseprites); development runs read a saved file again (Game_ReloadChangedAseprites), so slices and events follow Aseprite too.
tilemap.odin
Section titled “tilemap.odin”TileMap nodes: the tilemap layers of an Aseprite file in a scene. This is the start of the
engine’s tilemaps, and it takes Aseprite’s model as its own: a tileset is tiles of one size,
tile 0 the empty one; a tilemap layer is a grid of 32-bit tile values, the tile’s index in its
tileset (ASEPRITE_TILE_ID) with flip bits (ASEPRITE_TILE_FLIP_X, _Y, _D); tiles carry user
data properties. The editor’s tile painting writes the same data (painted layers, below).
<node kind="TileMap" name="Ground" tilemap="assets/level.aseprite" layers="Ground,Walls"/>- Settings (
TileMapSettings): the file, the frame its tilemaps are taken from (frame), the tilemap layers built (layers, names separated by commas; none: every visible one), andtileCollision(default on). - What it builds: a
TileMapLayerchild per tilemap layer, bottom first, at its cel’s place, drawn in one batch (tile_batch.odin) with the layer’s and cel’s opacity; layers hidden in Aseprite are left out unless named. - Collision from the tiles’ properties (set in Aseprite: a tile’s Properties, or the
tileset’s for every tile of it):
collision= “solid”, “one-way” or “area” (solid= true is solid too); anareaproperty names the Area its tiles go in (and makes them area tiles). Solid and one-way tiles become one StaticBody, “Collision”, their rectangles merged (one-way shapes haveoneWay); area tiles an Area per name (“Area” without one). The bodies get the node’scollisionLayer,collisionMask,frictionandrestitution. - Animated (
animate,tag): it plays the file’s frames (or a tag’s) at their durations, each layer showing its cel in that frame (water, torches); collision stays onframe’s tiles, so bodies aren’t rebuilt as it plays. - Code:
TileMap_TileAt(the tile under a point),TileMap_CellAt(the cell),TileMap_TileProperty,TileMap_TileCollision, andTileMap_SetTile(a broken block, a door: drawn at once, an animated layer in every frame; its bodies rebuilt on the next update, so a script holding one of them must look it up again). - Development runs (
Game.devKeys) read a saved file again and rebuild the node’s layers and collision (twice a second).
inflate.odin
Section titled “inflate.odin”A strict zlib inflater (RFC 1950 / RFC 1951) for data the engine doesn’t trust (Aseprite files’
images): it writes into a buffer of the size the caller expects and never past it, treats running
out of input as an error, and checks the Adler-32 sum. core:compress/zlib feeds zeros after the
end of its input and grows its output without bound, so a damaged file could make it allocate
gigabytes (seen: a minute per bad image, then a crash).
AsepriteError
Section titled “AsepriteError”AsepriteError :: enum { None, // The file couldn't be read Unreadable, // Not an Aseprite file (its magic numbers are wrong) Not_Aseprite, // It ends early, or a chunk runs past its frame Truncated, // A compressed image didn't inflate to its size Bad_Image, // A color depth other than 8, 16 or 32 bits Unsupported_Depth, // Larger than the engine reads (16384 pixels across) Too_Large,}What went wrong reading an Aseprite file
enum. Source: aseprite.odin:44
AsepriteColorMode
Section titled “AsepriteColorMode”AsepriteColorMode :: enum { RGBA, Grayscale, Indexed,}A sprite’s color mode
enum. Source: aseprite.odin:64
AsepriteLayerType
Section titled “AsepriteLayerType”AsepriteLayerType :: enum { Image, Group, Tilemap,}What a layer is
enum. Source: aseprite.odin:71
AsepriteBlendMode
Section titled “AsepriteBlendMode”AsepriteBlendMode :: enum { Normal, Multiply, Screen, Overlay, Darken, Lighten, Color_Dodge, Color_Burn, Hard_Light, Soft_Light, Difference, Exclusion, Hue, Saturation, Color, Luminosity, Addition, Subtract, Divide,}How a layer is blended onto the layers under it (Aseprite’s order and names)
enum. Source: aseprite.odin:78
AsepriteDirection
Section titled “AsepriteDirection”AsepriteDirection :: enum { Forward, Reverse, Ping_Pong, Ping_Pong_Reverse,}Which way a tag plays its frames
enum. Source: aseprite.odin:101
AsepritePoint
Section titled “AsepritePoint”AsepritePoint :: distinct [2]i32A property’s point value (POINT)
distinct type. Source: aseprite.odin:109
AsepriteSize
Section titled “AsepriteSize”AsepriteSize :: distinct [2]i32A property’s size value (SIZE)
distinct type. Source: aseprite.odin:111
AsepriteRect
Section titled “AsepriteRect”AsepriteRect :: distinct [4]i32A property’s rectangle value (RECT): x, y, width, height
distinct type. Source: aseprite.odin:113
AsepriteUUID
Section titled “AsepriteUUID”AsepriteUUID :: distinct [16]u8A property’s UUID value
distinct type. Source: aseprite.odin:115
AsepriteValue
Section titled “AsepriteValue”AsepriteValue :: union { bool, i64, f64, string, AsepritePoint, AsepriteSize, AsepriteRect, AsepriteUUID, []AsepriteValue, map[string]AsepriteValue,}A property’s value: integers of every size as i64, fixed point and floats as f64, vectors as slices, nested maps as maps (all the file’s arena).
union. Source: aseprite.odin:121
AsepriteUserData
Section titled “AsepriteUserData”AsepriteUserData :: struct { // Its text ("" for none) text: string, // Its color, when `hasColor` color: [4]u8, // Whether it has a color hasColor: bool, // The user's properties by name (nil when none; extensions' properties aren't kept) properties: map[string]AsepriteValue,}User data Aseprite attaches to a sprite, layer, cel, tag, slice, tileset or tile
struct. Source: aseprite.odin:135
AsepriteLayer
Section titled “AsepriteLayer”AsepriteLayer :: struct { // Its name name: string, // Image, group or tilemap type: AsepriteLayerType, // The group it's in (-1: the top level) parent: int, // Visible in Aseprite (its eye); a hidden group hides what it holds visible: bool, // Aseprite's background layer (opaque, at the bottom) background: bool, // A reference layer (never exported, so never drawn here) reference: bool, // How it's blended onto what's under it blendMode: AsepriteBlendMode, // Its opacity (255 when the file doesn't set layer opacity) opacity: u8, // A tilemap layer's tileset (index in `Aseprite.tilesets`; -1 for other layers) tileset: int, // Its user data userData: AsepriteUserData,}A layer (bottom first in Aseprite.layers; its index is the one cels refer to)
struct. Source: aseprite.odin:147
AsepriteCel
Section titled “AsepriteCel”AsepriteCel :: struct { // The layer (index in `Aseprite.layers`) layer: int, // Where its top-left corner is in the sprite, in pixels x, y: int, // Its size: pixels for images, tiles for tilemaps width, height: int, // Its opacity opacity: u8, // Moves it up (+) or down (-) among the layers in this frame (Aseprite's z-index) zIndex: int, // An image's pixels: RGBA, row by row (nil on tilemap layers) pixels: []u8, // A tilemap's tiles, row by row: each a tile index with flip bits (ASEPRITE_TILE_*) tiles: []u32, // Its user data userData: AsepriteUserData,}A layer’s content in one frame: an image (pixels, RGBA, width x height at x, y in the
sprite) or, on a tilemap layer, tiles (tiles, width x height tiles from x, y).
struct. Source: aseprite.odin:174
AsepriteFrame
Section titled “AsepriteFrame”AsepriteFrame :: struct { // Milliseconds duration: int, // The layers' cels in this frame (layers without one are empty) cels: []AsepriteCel,}A frame: how long it shows, and its cels
struct. Source: aseprite.odin:203
AsepriteTag
Section titled “AsepriteTag”AsepriteTag :: struct { // Its name ("run") name: string, // The first and last frame (inclusive) from, to: int, // Which way it plays direction: AsepriteDirection, // Times it plays (0: unspecified, which Aseprite plays forever in its UI and once when exporting) repeat: int, // Its color in Aseprite's timeline color: [4]u8, // Its user data userData: AsepriteUserData,}A tag: a named range of frames, which is how Aseprite names animations
struct. Source: aseprite.odin:211
AsepriteSliceKey
Section titled “AsepriteSliceKey”AsepriteSliceKey :: struct { // The frame it applies from (to the next key, or the end) frame: int, // Its rectangle in the sprite: x, y, width, height (0 wide: hidden from this frame) bounds: [4]int, // A 9-patch slice's center, relative to `bounds` (when `Aseprite.slices[i].nineSlice`) center: [4]int, // Its pivot, relative to `bounds`' origin (when `Aseprite.slices[i].hasPivot`) pivot: [2]int,}A slice’s shape from a frame on
struct. Source: aseprite.odin:227
AsepriteSlice
Section titled “AsepriteSlice”AsepriteSlice :: struct { // Its name name: string, // It's a 9-patch (its keys have a center) nineSlice: bool, // Its keys have a pivot hasPivot: bool, // Its rectangle from frame to frame keys: []AsepriteSliceKey, // Its user data userData: AsepriteUserData,}A slice: a named rectangle (a hitbox, a 9-patch, a pivot) over frames
struct. Source: aseprite.odin:239
AsepriteTileset
Section titled “AsepriteTileset”AsepriteTileset :: struct { // The id tilemap layers refer to it by id: int, // Its name name: string, // A tile's size in pixels tileWidth, tileHeight: int, // How many tiles (tile 0, the empty one, included) count: int, // The number Aseprite shows for tile 1 (UI only; 1 by default) baseIndex: int, // The tiles' pixels, RGBA: one column, tile i at row `i * tileHeight` (nil for a tileset // kept in an external file) pixels: []u8, // An external tileset's file (from the external files chunk; "" when it's in this file) externalFile: string, // Each tile's user data (by index; shorter than `count` when the last tiles have none) tileUserData: []AsepriteUserData, // Its user data userData: AsepriteUserData,}A tileset: same-sized tiles that tilemap layers place by index
struct. Source: aseprite.odin:253
Aseprite
Section titled “Aseprite”Aseprite :: struct { // The sprite's size in pixels width, height: int, // Its color mode in Aseprite (its pixels here are all RGBA) colorMode: AsepriteColorMode, // Its grid: x, y, width, height (width 0: no grid) grid: [4]int, // The palette, RGBA palette: [][4]u8, // Indexed sprites: the palette entry that's transparent in layers other than the background transparentIndex: int, // Layers, bottom first layers: []AsepriteLayer, // Frames, in order frames: []AsepriteFrame, // Tags (animations) tags: []AsepriteTag, // Slices slices: []AsepriteSlice, // Tilesets tilesets: []AsepriteTileset, // The sprite's own user data userData: AsepriteUserData, // Layer blend modes and opacity apply to groups too (composited apart first) groupBlending: bool, // Where everything lives arena: MemoryArena,}An Aseprite file, read by Aseprite_Load or Aseprite_Parse. Everything in it is in its arena
(Aseprite_Destroy).
struct. Source: aseprite.odin:279
TileMapSettings
Section titled “TileMapSettings”TileMapSettings :: struct { // `tilemap`: the Aseprite file, relative to the project folder file: string, // `frame`: the frame its tilemaps come from frame: int, // `layers`: the tilemap layers built, by name, separated by commas ("": every visible one) layers: string, // `tileCollision`: tiles with collision properties become bodies (default true) collision: bool, // `animate`: plays the file's frames (or `tag`'s) at their durations; collision stays on // `frame`'s tiles animate: bool, // `tag`: the tag it plays ("": every frame) tag: string, // `<tiles>` children: layers painted in the editor (or by code), each replacing the file's // tilemap layer of its name, or a new layer on one of the file's tilesets (format 13) painted: [dynamic]TileLayerData,}A TileMap node’s settings (scene files’ attributes)
struct. Source: tilemap.odin:42
TileLayerData
Section titled “TileLayerData”TileLayerData :: struct { // The layer's name layer: string, // A new layer's tileset (index in the file's tilesets) tileset: int, // Its top-left corner, in pixels (in the TileMap node's space) x, y: int, // Its grid's size in tiles columns, rows: int, // The tile values, row by row (columns * rows) tiles: [dynamic]u32,}A tilemap layer painted in the editor, kept in the scene file:
<tiles layer="Ground" tileset="0" x="0" y="0" columns="40" rows="12" data="AQAAAAEAAAA..."/>data is the tile values (Aseprite’s: ASEPRITE_TILE_ID with the flip bits), row by row, as
little-endian 32-bit numbers in base64 (TileLayer_Encode). A layer named like one of the file’s
tilemap layers replaces its tiles in every frame (the file’s layer keeps its tileset, opacity and
place among the others); any other name is a new layer, drawn over the file’s, on the file’s
tileset tileset (an index in Aseprite.tilesets).
struct. Source: tilemap.odin:72
TileCollisionKind
Section titled “TileCollisionKind”TileCollisionKind :: enum { None, Solid, One_Way, Area,}What a tile becomes in the physics world (TileMap_TileCollision)
enum. Source: tilemap.odin:150
TileMapNode
Section titled “TileMapNode”TileMapNode :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Its settings (strings in the node's arena) settings: TileMapSettings, // The file as read (its own: freed with the node) ase: ^Aseprite, // The project folder its path is relative to (node arena) projectDir: string, // The physics settings its bodies get physics: TileMapPhysics, // The file's time when read, and seconds to the next look (development runs) modified: i64, watchTimer: f64, // The nodes it made (layers, bodies), replaced when the file is read again built: [dynamic]^Node, // Its tile layers, bottom first tileLayers: [dynamic]^TileMapLayer, // Its bodies (rebuilt when `TileMap_SetTile` changes collision: `collisionDirty`) bodies: [dynamic]^Node, collisionDirty: bool, // The file's frames it plays (`animate`: every frame, or its tag's; else just `frame`), the one // showing (index in `frames`) and how long it has shown frames: []int, shown: int, clock: f64, // Files replaced by rebuilds: freed once their layers are gone (the next update) retired: [dynamic]^Aseprite,}A TileMap node: its layers and collision are its children
struct. Source: tilemap.odin:158
TileMapPhysics
Section titled “TileMapPhysics”TileMapPhysics :: struct { layer, mask: u64, friction, restitution: f32,}The physics settings a TileMap’s bodies get (the node’s)
struct. Source: tilemap.odin:189
TileMapLayer
Section titled “TileMapLayer”TileMapLayer :: struct { // The node part: transform, hierarchy, hooks using node: Node, // Its tiles using batch: TileBatch, // The layer in the file (index in `Aseprite.layers`), and its name layerIndex: int, layerName: string, // Its grid as it shows now: tiles across and down, and the tile values (the file's) cells: [2]int, tiles: []u32, // The tileset (in the file) tileset: ^AsepriteTileset, // Its cel in the TileMap's `frame`: what collision comes from (nil when it has none there) base: ^AsepriteCel, // Its cel and tiles in each frame the TileMap plays (by index in `TileMapNode.frames`) frames: []TileMapLayerFrame, // The layer's and its cels' opacity opacity: u8,}A tilemap layer of a TileMap node, drawn in one batch
struct. Source: tilemap.odin:195
TileMapLayerFrame
Section titled “TileMapLayerFrame”TileMapLayerFrame :: struct { cel: ^AsepriteCel, quads: [dynamic]TileQuad,}A layer’s cel in one frame, and its tiles to draw (filled in place: never more than its cells)
struct. Source: tilemap.odin:217
Procedures
Section titled “Procedures”Aseprite_Load
Section titled “Aseprite_Load”Aseprite_Load :: proc(path: string) -> (^Aseprite, AsepriteError)Reads an Aseprite file through the platform layer (a data pack first, then the disk).
Inputs
- path: The file
Returns
- The file’s data (free it with
Aseprite_Destroy), or nil and what went wrong
Example
ase, err := e.Aseprite_Load("assets/hero.aseprite")if err == .None { defer e.Aseprite_Destroy(ase) for tag in ase.tags do e.Debug_Text(scene, {0, 0}, tag.name)}procedure. Source: aseprite.odin:324
Aseprite_Parse
Section titled “Aseprite_Parse”Aseprite_Parse :: proc(data: []u8) -> (^Aseprite, AsepriteError)Reads an Aseprite file’s bytes.
Inputs
- data: The file’s contents (not kept)
Returns
- The file’s data (free it with
Aseprite_Destroy), or nil and what went wrong
procedure. Source: aseprite.odin:339
Aseprite_Destroy
Section titled “Aseprite_Destroy”Aseprite_Destroy :: proc(ase: ^Aseprite)Frees an Aseprite file’s data and everything in it.
Inputs
- ase: The file (nil does nothing)
procedure. Source: aseprite.odin:359
Aseprite_IsFile
Section titled “Aseprite_IsFile”Aseprite_IsFile :: proc(path: string) -> boolWhether a path is an Aseprite file, by its extension (.aseprite or .ase, any case)
procedure. Source: aseprite.odin:366
Aseprite_FindLayer
Section titled “Aseprite_FindLayer”Aseprite_FindLayer :: proc(ase: ^Aseprite, name: string) -> intA layer by name.
Inputs
- ase: The file
- name: The layer’s name
Returns
- Its index in
ase.layers, or -1
procedure. Source: aseprite.odin:381
Aseprite_FindTag
Section titled “Aseprite_FindTag”Aseprite_FindTag :: proc(ase: ^Aseprite, name: string) -> ^AsepriteTagA tag by name.
Inputs
- ase: The file
- name: The tag’s name
Returns
- The tag, or nil
procedure. Source: aseprite.odin:396
Aseprite_Cel
Section titled “Aseprite_Cel”Aseprite_Cel :: proc(ase: ^Aseprite, frame, layer: int) -> ^AsepriteCelA layer’s cel in a frame.
Inputs
- ase: The file
- frame: The frame’s index
- layer: The layer’s index
Returns
- The cel, or nil when the layer is empty in that frame
procedure. Source: aseprite.odin:412
Aseprite_LayerShown
Section titled “Aseprite_LayerShown”Aseprite_LayerShown :: proc(ase: ^Aseprite, layer: int) -> boolWhether a layer is drawn: it’s visible, so are the groups it’s in, and it isn’t a reference layer.
Inputs
- ase: The file
- layer: The layer’s index
procedure. Source: aseprite.odin:425
Aseprite_FramePixels
Section titled “Aseprite_FramePixels”Aseprite_FramePixels :: proc(ase: ^Aseprite, frame: int, allocator := context.allocator, layers: []int = nil) -> []u8A frame as Aseprite shows it: the shown layers composited bottom up (see the file’s overview).
Inputs
- ase: The file
- frame: The frame’s index
- allocator: For the pixels
- layers: Only these layers (by index; nil: every shown layer). A listed layer is drawn even when hidden in Aseprite
Returns
- RGBA pixels,
ase.widthxase.height, row by row (all transparent for a frame out of range)
procedure. Source: aseprite.odin:445
Aseprite_SheetPixels
Section titled “Aseprite_SheetPixels”Aseprite_SheetPixels :: proc(ase: ^Aseprite, allocator := context.allocator, layers: []int = nil) -> (pixels: []u8, columns, rows: int)Every frame on one picture: a grid of columns x rows cells of the sprite’s size, frame i
at column i % columns, row i / columns (an animation’s sheet).
Inputs
- ase: The file
- allocator: For the pixels
- layers: As in
Aseprite_FramePixels
Returns
- RGBA pixels (
columns * ase.widthxrows * ase.height), and the grid’s columns and rows
procedure. Source: aseprite.odin:464
Aseprite_SheetGrid
Section titled “Aseprite_SheetGrid”Aseprite_SheetGrid :: proc(ase: ^Aseprite) -> (columns, rows: int)The grid Aseprite_SheetPixels lays frames out on: about square, kept under ASEPRITE_MAX_SIZE.
Inputs
- ase: The file
Returns
- Columns and rows
procedure. Source: aseprite.odin:487
Aseprite_CreateTexture
Section titled “Aseprite_CreateTexture”Aseprite_CreateTexture :: proc(renderer: ^sdl.Renderer, ase: ^Aseprite, frame := 0) -> ^sdl.TextureA texture of a frame (or of every frame as a sheet), with nearest filtering.
Inputs
- renderer: The renderer
- ase: The file
- frame: The frame (-1: the sheet of every frame,
Aseprite_SheetPixels)
Returns
- The texture (the caller’s), or nil
procedure. Source: aseprite.odin:506
Aseprite_TilePixels
Section titled “Aseprite_TilePixels”Aseprite_TilePixels :: proc(tileset: ^AsepriteTileset, tile: u32, allocator := context.allocator) -> []u8A tile’s pixels from a tileset, with the tile’s flips applied.
Inputs
- tileset: The tileset
- tile: The tile value (index and flip bits)
- allocator: For the pixels
Returns
- RGBA pixels,
tileWidthxtileHeight(a diagonal flip of a non-square tile is left out), or nil for the empty tile or an index past the tileset
procedure. Source: aseprite.odin:537
Aseprite_Property
Section titled “Aseprite_Property”Aseprite_Property :: proc(data: AsepriteUserData, name: string) -> (AsepriteValue, bool)A user data’s property, by name.
Inputs
- data: The user data
- name: The property’s name
Returns
- The value, and whether it’s there
procedure. Source: aseprite.odin:560
Game_LoadAseprite
Section titled “Game_LoadAseprite”Game_LoadAseprite :: proc(game: ^Game, path: string) -> ^AsepriteA file the game read, kept for its life (nil, logged, when it can’t be read; asked again, it stays nil until it’s saved again in a development run).
Inputs
- game: The game
- path: The file (as the resource manager has it: the project folder joined)
Returns
- The file’s data (the game’s: don’t free it), or nil
procedure. Source: aseprite_nodes.odin:44
Game_ForgetAseprites
Section titled “Game_ForgetAseprites”Game_ForgetAseprites :: proc(game: ^Game)Frees the Aseprite files the game keeps (Game_Destroy does it; editors’ preview games too).
Inputs
- game: The game
procedure. Source: aseprite_nodes.odin:66
Game_ReloadChangedAseprites
Section titled “Game_ReloadChangedAseprites”Game_ReloadChangedAseprites :: proc(game: ^Game)Reads again the Aseprite files the game keeps that were saved since (nothing keeps a file’s pointer: nodes look it up when they need it). Development runs call it twice a second; editors for their previews.
Inputs
- game: The game
procedure. Source: aseprite_nodes.odin:79
Aseprite_SliceAt
Section titled “Aseprite_SliceAt”Aseprite_SliceAt :: proc(ase: ^Aseprite, name: string, frame: int) -> (key: AsepriteSliceKey, ok: bool)A slice’s shape in a frame: its key for the last frame at or before it.
Inputs
- ase: The file
- name: The slice’s name
- frame: The frame
Returns
- The key, and false when there’s no such slice, it starts later, or it’s hidden in that frame (0 wide or high)
procedure. Source: aseprite_nodes.odin:106
Aseprite_FrameEvents
Section titled “Aseprite_FrameEvents”Aseprite_FrameEvents :: proc(ase: ^Aseprite, frame: int) -> stringA frame’s events: its cels’ text and event properties, on every layer (in layer order).
Inputs
- ase: The file
- frame: The frame
Returns
- The events, comma-separated (“” for none; temp allocated)
procedure. Source: aseprite_nodes.odin:126
Aseprite_LayersNamed
Section titled “Aseprite_LayersNamed”Aseprite_LayersNamed :: proc(ase: ^Aseprite, names: string) -> []intThe layers named (a group’s name brings every layer in it), for drawing only them.
Inputs
- ase: The file
- names: Layer names separated by commas (“” for none)
Returns
- Their indices (temp allocated), nil when none are named
procedure. Source: aseprite_nodes.odin:150
Sprite_Origin
Section titled “Sprite_Origin”Sprite_Origin :: proc(node: ^Node) -> [2]f32The point of a sprite’s picture drawn at the node’s origin: its pivot slice’s pivot in that frame, else the picture’s middle.
Inputs
- node: A Sprite or AnimatedSprite
Returns
- The point, in the picture’s pixels
procedure. Source: aseprite_nodes.odin:175
TileLayer_Encode
Section titled “TileLayer_Encode”TileLayer_Encode :: proc(tiles: []u32, allocator := context.allocator) -> stringTile values as the scene file’s data: little-endian 32-bit numbers in base64.
Inputs
- tiles: The tile values
- allocator: For the text
Returns
- The text
procedure. Source: tilemap.odin:95
TileLayer_Decode
Section titled “TileLayer_Decode”TileLayer_Decode :: proc(text: string, count: int, allocator := context.allocator) -> ([dynamic]u32, bool)A scene file’s data as tile values (TileLayer_Encode’s inverse).
Inputs
- text: The base64 text
- count: How many tiles it should hold (columns * rows)
- allocator: For the tiles
Returns
- The tiles (always
countof them: missing ones empty), and false when the text is damaged
procedure. Source: tilemap.odin:113
TileLayerData_Destroy
Section titled “TileLayerData_Destroy”TileLayerData_Destroy :: proc(layer: ^TileLayerData, allocator := context.allocator)Frees a painted layer’s strings and tiles
procedure. Source: tilemap.odin:124
TileLayerData_Clone
Section titled “TileLayerData_Clone”TileLayerData_Clone :: proc(layer: TileLayerData, allocator := context.allocator) -> TileLayerDataA copy of a painted layer (owning its name and tiles)
procedure. Source: tilemap.odin:131
TileLayerData_Equal
Section titled “TileLayerData_Equal”TileLayerData_Equal :: proc(a, b: TileLayerData) -> boolWhether two painted layers are the same
procedure. Source: tilemap.odin:140
TileMap_TileCollision
Section titled “TileMap_TileCollision”TileMap_TileCollision :: proc(tileset: ^AsepriteTileset, tile: u32) -> (kind: TileCollisionKind, area: string)A tile’s collision: its own properties, else its tileset’s (see the file’s overview).
Inputs
- tileset: The tileset
- tile: The tile value (its index; flips don’t matter)
Returns
- What it becomes, and an area tile’s Area name (“” for the default)
procedure. Source: tilemap.odin:232
TileMap_TileAt
Section titled “TileMap_TileAt”TileMap_TileAt :: proc(node: ^TileMapNode, layer: string, position: [2]f32) -> (tile: u32, at: ^TileMapLayer, ok: bool)The tile under a point of the world, in a layer of a TileMap.
Inputs
- node: The TileMap
- layer: The layer’s name (“”: the top-most layer with a tile there)
- position: A point in the world
Returns
- The tile value (0: empty), its layer, and false when the point is off every grid
procedure. Source: tilemap.odin:271
TileMap_TileProperty
Section titled “TileMap_TileProperty”TileMap_TileProperty :: proc(layer: ^TileMapLayer, tile: u32, name: string) -> (AsepriteValue, bool)A property of a tile (its own, else its tileset’s).
Inputs
- layer: The tile’s layer (
TileMap_TileAt) - tile: The tile value
- name: The property
Returns
- The value, and whether there’s one
Example
// Given: level: ^e.TileMapNode, hero: ^e.Nodeif tile, layer, ok := e.TileMap_TileAt(level, "Ground", e.Node_GetWorldPosition(hero)); ok { if value, has := e.TileMap_TileProperty(layer, tile, "damage"); has do log.info(value)}procedure. Source: tilemap.odin:301
TileMap_CellAt
Section titled “TileMap_CellAt”TileMap_CellAt :: proc(node: ^TileMapNode, layer: string, position: [2]f32) -> (column, row: int, ok: bool)The tile cell under a point of the world, in a layer as it shows now.
Inputs
- node: The TileMap
- layer: The layer’s name
- position: A point in the world
Returns
- The column and row, and false when the point is off the layer’s grid (or there’s no such layer)
procedure. Source: tilemap.odin:492
TileMap_SetTile
Section titled “TileMap_SetTile”TileMap_SetTile :: proc(node: ^TileMapNode, layer: string, column, row: int, tile: u32) -> boolChanges a tile: drawn at once, collision rebuilt on the node’s next update (a broken block, a door opening). An animated layer gets it in every frame it plays, so it stays.
Inputs
- node: The TileMap
- layer: The layer’s name
- column, row: The cell (in the layer’s grid, as
TileMap_CellAtgives it) - tile: The tile value (an index in the layer’s tileset, with flip bits; 0 empties it)
Returns
- false when there’s no such layer or cell
Example
// Given: level: ^e.TileMapNode, hit: [2]f32if column, row, ok := e.TileMap_CellAt(level, "Ground", hit); ok do e.TileMap_SetTile(level, "Ground", column, row, 0)procedure. Source: tilemap.odin:519
TileMap_Rebuild
Section titled “TileMap_Rebuild”TileMap_Rebuild :: proc(node: ^TileMapNode, ase: ^Aseprite)Builds a TileMap’s layers and collision again, from a file’s data (the node takes it and frees the old). Development runs do it when the file is saved; editors when it changes.
Inputs
- node: The TileMap
- ase: The file, read again
procedure. Source: tilemap.odin:688
Tileset_TerrainOf
Section titled “Tileset_TerrainOf”Tileset_TerrainOf :: proc(tileset: ^AsepriteTileset, tile: u32) -> stringThe terrain a tile belongs to: its terrain property in Aseprite (“” for none).
Inputs
- tileset: The tileset
- tile: A tile value (flips don’t matter)
procedure. Source: tilemap.odin:729
Tileset_Terrains
Section titled “Tileset_Terrains”Tileset_Terrains :: proc(tileset: ^AsepriteTileset, allocator := context.allocator) -> []stringA tileset’s terrains, in the order their first tiles come.
Inputs
- tileset: The tileset
- allocator: For the list
Returns
- The terrains’ names
procedure. Source: tilemap.odin:748
Terrain_TileFor
Section titled “Terrain_TileFor”Terrain_TileFor :: proc(tileset: ^AsepriteTileset, terrain: string, mask: int) -> u32The tile of a terrain drawn for a cell whose same-terrain neighbours are mask: the one whose
own mask matches best (exactly, else in the most neighbours; corners only when the terrain’s tiles
use them, so a 16-tile set of edges works too), else any tile of the terrain.
Inputs
- tileset: The tileset
- terrain: The terrain’s name
- mask: The cell’s neighbours of the same terrain (TERRAIN_* bits)
Returns
- The tile (an index; 0 when the tileset has no tile of that terrain)
procedure. Source: tilemap.odin:814
TileGrid_PaintTerrain
Section titled “TileGrid_PaintTerrain”TileGrid_PaintTerrain :: proc(tileset: ^AsepriteTileset, tiles: []u32, columns, rows, column, row: int, terrain: string) -> boolPaints a terrain into a grid of tiles (autotiling): the cell takes the terrain, then it and its
eight neighbours of a terrain take the tile that fits their neighbours (Terrain_TileFor).
Painting “” erases the cell and fixes its neighbours. Cells off the grid count as the same terrain,
so a terrain reaches the map’s edges without a border.
Inputs
- tileset: The tileset
- tiles: The grid, row by row (changed in place)
- columns, rows: Its size
- column, row: The cell
- terrain: The terrain (“” to erase)
Returns
- false when the cell is off the grid
procedure. Source: tilemap.odin:853
TileMap_SetTerrain
Section titled “TileMap_SetTerrain”TileMap_SetTerrain :: proc(node: ^TileMapNode, layer: string, column, row: int, terrain: string) -> boolPaints a terrain into a TileMap’s layer from code (TileGrid_PaintTerrain): drawn at once,
collision on the next update, every frame of an animated layer.
Inputs
- node: The TileMap
- layer: The layer’s name
- column, row: The cell
- terrain: The terrain’s name (“” erases)
Returns
- false when there’s no such layer or cell
Example
// Given: level: ^e.TileMapNode, hit: [2]f32if column, row, ok := e.TileMap_CellAt(level, "Ground", hit); ok do e.TileMap_SetTerrain(level, "Ground", column, row, "")procedure. Source: tilemap.odin:891
Constants and variables
Section titled “Constants and variables”ASEPRITE_MAX_SIZE
Section titled “ASEPRITE_MAX_SIZE”ASEPRITE_MAX_SIZE :: 16384The largest sprite, cel or tileset side the reader takes, in pixels or tiles
constant. Source: aseprite.odin:61
ASEPRITE_TILE_ID
Section titled “ASEPRITE_TILE_ID”ASEPRITE_TILE_ID :: u32(0x1fffffff)A tile’s index in its tileset: tile & ASEPRITE_TILE_ID (0 is the empty tile)
constant. Source: aseprite.odin:194
ASEPRITE_TILE_FLIP_X
Section titled “ASEPRITE_TILE_FLIP_X”ASEPRITE_TILE_FLIP_X :: u32(0x80000000)The tile is mirrored left to right
constant. Source: aseprite.odin:196
ASEPRITE_TILE_FLIP_Y
Section titled “ASEPRITE_TILE_FLIP_Y”ASEPRITE_TILE_FLIP_Y :: u32(0x40000000)The tile is mirrored top to bottom
constant. Source: aseprite.odin:198
ASEPRITE_TILE_FLIP_D
Section titled “ASEPRITE_TILE_FLIP_D”ASEPRITE_TILE_FLIP_D :: u32(0x20000000)The tile’s axes are swapped (a transpose; with the X or Y flip it makes the quarter turns)
constant. Source: aseprite.odin:200
ASEPRITE_LAYERS_SUFFIX
Section titled “ASEPRITE_LAYERS_SUFFIX”ASEPRITE_LAYERS_SUFFIX :: "?layers="The resource manager key suffix naming the layers a texture of an Aseprite file draws
constant. Source: aseprite_nodes.odin:31
DEFAULT_TILEMAP_SETTINGS
Section titled “DEFAULT_TILEMAP_SETTINGS”DEFAULT_TILEMAP_SETTINGS :: TileMapSettings{collision = true}A TileMap node’s settings by default
constant. Source: tilemap.odin:147
TERRAIN_N
Section titled “TERRAIN_N”TERRAIN_N :: 1The neighbour bits of a terrain tile’s mask property: the neighbours of the same terrain it’s
drawn for (a corner counts only with both its edges: the “blob” rule). This one: the tile above
constant. Source: tilemap.odin:706
TERRAIN_NE
Section titled “TERRAIN_NE”TERRAIN_NE :: 2A terrain mask’s bit for the tile above and to the right
constant. Source: tilemap.odin:708
TERRAIN_E
Section titled “TERRAIN_E”TERRAIN_E :: 4A terrain mask’s bit for the tile to the right
constant. Source: tilemap.odin:710
TERRAIN_SE
Section titled “TERRAIN_SE”TERRAIN_SE :: 8A terrain mask’s bit for the tile below and to the right
constant. Source: tilemap.odin:712
TERRAIN_S
Section titled “TERRAIN_S”TERRAIN_S :: 16A terrain mask’s bit for the tile below
constant. Source: tilemap.odin:714
TERRAIN_SW
Section titled “TERRAIN_SW”TERRAIN_SW :: 32A terrain mask’s bit for the tile below and to the left
constant. Source: tilemap.odin:716
TERRAIN_W
Section titled “TERRAIN_W”TERRAIN_W :: 64A terrain mask’s bit for the tile to the left
constant. Source: tilemap.odin:718
TERRAIN_NW
Section titled “TERRAIN_NW”TERRAIN_NW :: 128A terrain mask’s bit for the tile above and to the left
constant. Source: tilemap.odin:720
