Asset registry (assets.yaml)
The asset registry gives your game's resources names: images, sounds, fonts,
materials, sprite animations, actors and data files. Your code and other data
files refer to assets by these names instead of by file path, and ctgame
uses the registry to know which files to ship.
By default the game loads data/assets.yaml. Set
paths.asset_registry in game.json to use another
file.
Example
images:
- name: ship
path: images/ship.png
- name: ship_normal
path: images/ship-normal.png
srgb: false
mipmaps: true
sounds:
- name: laser
path: audio/laser.ogg
fonts:
- name: body
package: data/fonts/body.ctfont
- name: hud
atlas: images/fonts/hud-msdf.png
metrics: data/fonts/hud-msdf.json
materials:
- name: hull
system: pbr
mipmaps: true
textures:
- name: albedo
image: ship
- name: normal
image: ship_normal
- name: roughness
color: [0.6, 0.6, 0.6]
parameters:
- name: normal_strength
value: 1
animations:
- name: ship_flight
image: ship
clips:
- origin: [0, 0]
frame_size: [100, 100]
count: 3
duration: 0.06
loop: once
actors:
- name: PlayerShip
path: data/actors/PlayerShip.yaml
files:
- name: scene
path: data/scene.yaml
- name: tuning
path: data/tuning.yaml
- name: muzzle_flash
path: data/effects/muzzle_flash.effect
Paths are relative to the folder containing game.json, not to the
registry file. Write the folder as part of each path. Absolute paths work
when you run the game locally but can't be exported.
Top-level fields
| Field | Type | Description |
|---|---|---|
format | map | Optional file format version; see File format versions. |
images | list | PNG textures. |
sounds | list | Sound effects and music. |
fonts | list | Fonts for text. |
shaders | list | Names for shaders built into the game. |
materials | list | How meshes and sprites are shaded. |
animations | list | Sprite-sheet animations. |
actors | list | Actor definitions. |
files | list | Any other data file: scenes, tuning, effects, your own YAML or JSON. |
Every section is optional. Names must be unique within a section (an image and a sound may share a name). Names are case-sensitive. Unknown keys are ignored.
images
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
path | string | — | Required. PNG file. |
srgb | bool | true | true for color art. Set false for data textures: normal maps, masks, distance fields, lookup tables. |
premultiply | bool | false | Premultiply color by alpha when loading. |
mipmaps | bool | see below | Generate smaller versions of the image (mipmaps) so it looks smooth when drawn small. |
mipmap_levels | integer 0–16 | 0 | Most mip levels to generate, including the full-size image. 0 means as many as possible; 1 means none. |
mipmap_filter | auto, color, data or normal | auto | How smaller levels are averaged. auto picks normal for images used as a material's normal input, color for sRGB images and data otherwise. |
Booleans accept true/yes/1 and false/no/0.
Mipmap policy
You rarely need to set mipmaps on an image:
- An image used by a material with
mipmaps: truegets mipmaps, using the material'smipmap_levels. - An image used by an animation gets mipmaps. Each frame is shrunk on its own, so frames never bleed into each other, and frames never shrink below 4 pixels.
- Any other image has no mipmaps.
Setting mipmaps or mipmap_levels on the image overrides these defaults.
The color filter needs srgb: true; normal needs srgb: false and
premultiply: false.
sounds
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
path | string | — | Required. .wav, .flac or .ogg (Vorbis) file. |
fonts
Give each font either a package, or an atlas and metrics together.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
package | string | — | A .ctfont file made from TrueType fonts with ctfont-pack. Sharp at any size. |
atlas | string | — | Multi-channel signed distance field (MSDF) atlas PNG. Needs metrics. |
metrics | string | — | The atlas's metrics JSON. Needs atlas. |
shaders
Shaders are compiled into the game. A shaders entry gives one a name that
materials and effects can use.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
provider | string | — | Required. Shader to use. Built in: sprite, sprite_gpu_anim, vfx, sprite_pbr, armor, armor_shadow. Games with C code can register their own. |
materials
A material says how a mesh or sprite is shaded: which images or colors it uses and its settings.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
system | string | — | Required. Render system that draws it, for example pbr or mesh_lit. |
shader | string | system default | Shader asset name. |
cast_shadows | bool | true | Objects with this material cast shadows. |
receive_shadows | bool | true | Shadows fall on objects with this material. |
mipmaps | bool | false | Give this material's images mipmaps (unless an image says otherwise). |
mipmap_levels | integer 0–16 | 0 | Default mipmap_levels for this material's images. |
textures | list | empty | Image inputs; see below. |
parameters | list | empty | Numeric settings; see below. |
textures
Each texture needs a name and either image or color.
| Field | Type | Description |
|---|---|---|
name | string | Input name, defined by the render system: for example albedo, normal, height, metallic, roughness. |
image | string | Image asset name. |
color | [r, g, b] or [r, g, b, a] | A flat color instead of an image. Each value 0–1; alpha defaults to 1. |
Inputs the render system requires must be present.
parameters
| Field | Type | Description |
|---|---|---|
name | string | Setting name, defined by the render system. |
value | number or list | One number, or a list of 2–4 numbers, matching the setting. Mesh systems also accept a whole number or 16 numbers (a 4×4 matrix). |
animations
A sprite animation plays frames from a sprite-sheet image.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Required. Asset name. |
image | string | — | Required. Image asset name (not a path). |
clips | list | — | Required. At least one clip. Code selects clips by position in this list, starting at 0. |
clips
| Field | Type | Default | Description |
|---|---|---|---|
origin | [x, y] | [0, 0] | Pixel position of the first frame in the image. |
frame_size | [w, h] | — | Required. Frame size in pixels. |
count | integer | — | Required. Number of frames. |
frames_per_row | integer | count | Frames before wrapping to the next row (or column). |
horizontal | bool | false | true: frames run left to right, then wrap down. false: frames run top to bottom, then wrap right. |
duration | number | — | Required. Seconds per frame. |
loop | loop, once or pingpong | loop | Repeat, play once and stop, or play back and forth. |
All the animations of one image can have at most 100,000 frames in total.
actors
| Field | Type | Description |
|---|---|---|
name | string | Required. Actor name. Must match the name inside the actor file. |
path | string | Required. The actor file. |
Actor files are checked when the game starts, so a broken actor stops the game with an error.
files
Any other file your game reads. The registry only checks that the file exists; your code decides what's in it.
| Field | Type | Description |
|---|---|---|
name | string | Required. Asset name. |
path | string | Required. The file. |
Some names have a meaning to cTurtle:
| Name | Contents |
|---|---|
scene | Your main scene. paths.scene in game.json overrides it. |
models | Your procedural models, used by Studio. |
Other common entries are effects, motion clips and rigs and tuning data.
Tuning and other data files
Keep gameplay numbers (speeds, health, HUD spacing) in your own YAML file
instead of in code. Register it under files, then decode the part each
system needs into a BT object that holds its defaults:
# data/assets.yaml
files:
- name: tuning
path: data/tuning.yaml
# data/tuning.yaml
hud:
bottom_padding: 14
include "cturtle/yaml";
object HudSettings { float bottom_padding; }
object HudTuning { HudSettings hud; }
fn load_hud_tuning() -> HudTuning {
HudTuning tuning = HudTuning { hud: HudSettings { bottom_padding: 10.0 } };
yaml_decode_asset("tuning", tuning)?;
return tuning;
}
Keys missing from the file keep the defaults you set. Each system can decode its own part of the same file. Edits take effect the next time the file is decoded, normally on the next launch. Registered files are exported automatically.
Per-actor values (an enemy's weapons or health) belong in its actor file instead.
Reading assets from BT
| To get | Call |
|---|---|
| An image | renderImageGet("ship") |
| A sound | audioSound("laser") |
| A file or actor file, decoded into an object | yaml_decode_asset(name, target), yaml_decode_asset_defaults(name, target, defaults), json_decode_asset(name, target) |
| A file or actor file, as a YAML document | yaml_parse_asset(name) |
See cturtle/yaml,
cturtle/render and
cturtle/audio. A data file can be at most
64 MiB.
YAML rules
The registry, scenes and actor files support common YAML, with these limits:
- Use indentation for maps and
- itemfor lists. Lists of numbers can be written inline:[1, 2, 3]. Inline maps ({ a: 1 }) aren't supported. - Every value fits on one line. No multi-line strings, anchors, aliases, tags or multiple documents in one file.
#starts a comment.- A line or value can be at most 255 characters. A key can be at most 63 characters, and keys can nest at most 16 levels deep.
Exported builds
ctgame ships the registry and every file it names. It also converts each
image to a .ktx2 file, with its mipmaps, which loads faster than a PNG. See
Packaging.
Errors
Errors stop the game at startup and look like
asset registry '<path>': <message>.
| Message | What to do |
|---|---|
assets.yaml: `version: 1` is no longer used | Delete the version line (an older file). |
assets.yaml uses format version X; this cTurtle reads format … | The file was written for a newer cTurtle; see File format versions. |
image N requires non-empty name and path (also sound, file, actor) | Entry number N is missing a field. |
duplicate image asset 'X' (also other types) | Two entries share a name, possibly one in game.json assets. |
font N requires exactly package or atlas plus metrics | Use either package, or atlas and metrics. |
'images.N' mipmap_levels must be 0..16 | Fix the level count. |
'materials.N' uses mipmap_filter on a material; set it on each image | Move mipmap_filter to the images. |
image 'X' color mipmap_filter requires srgb / normal mipmap_filter requires srgb: false | The filter doesn't match the image's srgb. |
image 'X' is used as both normal and non-normal map; set mipmap_filter explicitly | Set mipmap_filter on that image. |
image 'X' has conflicting material mipmap_levels | Two materials want different levels; set mipmap_levels on the image. |
material 'X' texture N requires a name and exactly one of image or color | Fix the texture entry. |
material 'X' texture 'Y' color must be normalized | Color values must be 0–1. |
animation 'X' requires at least one clip, clip N requires positive frame_size (or count, duration) | Fix the clip. |
animation 'X' clip N has unknown loop mode 'Y' | Use loop, once or pingpong. |
material asset 'X' references unavailable mesh system 'Y' | Unknown system. |
material asset 'X' has unknown texture input 'Y' for system 'Z' (or unknown parameter, invalid value for parameter) | The render system has no such input, or the value has the wrong number of components. |
material asset 'X' is missing required texture input 'Y' | Add the input. |
material asset 'X' references unknown image 'Y' (also animation asset) | Register the image first. |
could not prepare image asset 'X' from 'P' | The PNG is missing or unreadable. |
could not register file asset 'X' from 'P' | The file doesn't exist. |
actor asset 'X' contains actor named 'Y' | Make the registry name match the actor file's name. |
UI-only asset registries may contain images, sounds, files, actors, and fonts, ... | UI-only apps (such as those run with bt-ui) can't use shaders, materials or animations. |