moxzi
Docs / moxzi.game / Assets

Assetspreview

Models, materials, graphics settings and sounds, and how Motoko code refers to them.

Assets live in the directories listed in asset_roots. Each asset file has a .meta.yaml file beside it that gives it a permanent id and the name your code uses.

Asset metadata#

assets/blue.material.yaml.meta.yaml
format_version: 1
uuid: 11111111-0000-4000-8000-000000000003
address: material/blue
importer: copy
importer_version: 1
kind: material
binding: blue
FieldMeaning
uuidThe asset's permanent id. Saves and packages refer to it. Never change it
kindmodel, material, audio, ui, or bytes for anything else
bindingThe Motoko name. Letters, digits and underscores
addressOptional unique path. The player finds ui/main and settings/graphics by address
importer, importer_versioncopy, 1

moxzi-game init-assets . creates missing metadata files with kind: bytes and a binding taken from the file name. Edit them, then commit them with the assets. To move or rename an asset, move its .meta.yaml file with it; the id and binding stay the same.

Using assets in Motoko#

The build generates a module, mo:game-assets/Assets, from the metadata:

// Generated by Moxzi. Edit source metadata, not this file.
import Asset "mo:moxzi/Asset";
module {
  public let asset_blue : Asset.Material = #material("11111111-0000-4000-8000-000000000003");
  public let asset_controls : Asset.Ui = #ui("11111111-0000-4000-8000-000000000005");
  public let asset_cube : Asset.Model = #model("11111111-0000-4000-8000-000000000001");
  public let asset_graphics : Asset.Bytes = #bytes("11111111-0000-4000-8000-000000000006");
  public let asset_grey : Asset.Material = #material("11111111-0000-4000-8000-000000000004");
  public let asset_ground : Asset.Model = #model("11111111-0000-4000-8000-000000000002");
  public let asset_sound_click : Asset.Audio = #audio("11111111-0000-4000-8000-000000000007");
  public let material_blue : Nat32 = 1;
  public let material_grey : Nat32 = 2;
  public let mesh_cube : Nat32 = 1;
  public let mesh_ground : Nat32 = 2;
};
ConstantTypeUse
mesh_BINDINGNat32mesh in a Render.Entity
material_BINDINGNat32material in a Render.Entity
asset_BINDINGAsset.Model, Asset.Audio, …Typed references, for example in Audio.play

Using a name that doesn't exist is a compile error. Two assets can't share a binding.

Models#

A model is a primitive shape in YAML, or a .glb file.

cube.model.yaml
version: 1
primitive:
  shape: cuboid
  size: [1, 1, 1]
shapeParameters
cuboidsize: [x, y, z] in metres
sphereradius in metres

.glb files are supported with limits: one mesh, transforms already applied, no textures, skins or animations.

Materials#

blue.material.yaml
version: 1
base_color_linear: [0.05, 0.3, 0.9, 1]
metallic: 0.1
roughness: 0.5
emissive_linear: [0.0, 0.0, 0.0]
FieldMeaning
base_color_linearColour as linear RGBA, each 0 to 1
metallic0 (not metal) to 1 (metal)
roughness0 (mirror) to 1 (matte)
emissive_linearLight the surface gives off, linear RGB. Values above 0 glow, and bloom if enabled

Colours are linear, not sRGB. To convert an sRGB value c between 0 and 1, use ((c + 0.055) / 1.055) ^ 2.4 (or c / 12.92 for values below 0.04).

Graphics settings#

graphics.yaml
version: 1
bloom: false
shadows: true

Give this file kind: bytes and address: settings/graphics. To let players turn effects down, add a button with local: reduced_effects (see Controls).

The scene#

The scene is built in Motoko from mo:moxzi/Render:

TypeFields
Entityid (your own Nat64), mesh, material, transform, visible
Transformtranslation (metres), rotation (quaternion x, y, z, w), scale. Start from Render.identity
Cameratransform, fov (radians), near, far, exposure
Lightid, kind (#directional, #point { range }, #spot { range; inner; outer }), transform, color, intensity, shadows

moxzi_snapshot returns the whole scene with Render.snapshot. Each tick, return only the changes, built from Render.empty:

Delta fieldUse
created, destroyedEntities that appeared or were removed
transformsNew positions, as (id, Transform)
materialsNew materials, as (id, material)
visibilityShow or hide, as (id, Bool)
lights, removed_lightsLights added or changed, and removed
cameraA new camera position, or null to keep it

Between ticks, the player interpolates entity positions, so movement looks smooth at any frame rate.

Sounds#

Sounds are WAV files with kind: audio:

LimitValue
Format16-bit PCM, mono or stereo, 8 to 96 kHz
Length10 seconds, 4 MiB
Cues per tick32

Return sounds from moxzi_advance in the audio field, created with Audio.play. See Writing a game. Sounds are presentation only: they aren't saved, and they're skipped if they arrive more than half a second late.

To let players change the volume, return audio_gain = ?g (0 to 1) in your replies, as Pong does.

Limitations#

Not supported yet
Textures and images on modelsUse materials and emissive colour
Animated or skinned modelsMove entities from Motoko instead
Music, compressed audio, 3D positional sound
On this pageAsset metadataUsing assets in MotokoModelsMaterialsGraphics settingsThe sceneSoundsLimitations