Tile Maps via Tiled - bryanedds/Nu GitHub Wiki
Nu uses the TiledSharp library to load and render tile maps created in Tiled. Tile maps in Nu support various custom properties that allow you to define collision shapes, animations, elevation offsets, and custom metadata for individual tiles or layers.
- Create your tile map in Tiled Map Editor
- Export it as a
.tmxfile - Place the
.tmxfile in your Nu project'sAssetsdirectory - Reference it in your game using a
TileMap AssetTag
Nu provides two main ways to use tile maps:
- Purpose: For asset-defined tile maps
- Asset-based: Loads tile maps from TMX asset files
-
Properties:
-
TileMap- The asset tag reference to the TMX file -
TileLayerClearance- Spacing between layers (default: 2.0f) -
TileSizeDivisor- Divides tile size for scaling (default: 1) -
TileIndexOffset- Offset for tile indices -
TileIndexOffsetRange- Range of tiles to apply offset to -
BodyEnabled- Enable/disable physics body -
Friction,Restitution- Physics properties -
CollisionCategories,CollisionMask- Collision filtering
-
- Purpose: For user-defined tile maps
- Runtime-defined: Create and manipulate TmxMap objects programmatically
- Same properties as TileMapFacet
- Use case: Dynamic tile map generation or modification
- TileMapDispatcher: Entity dispatcher that includes TileMapFacet
- TmxMapDispatcher: Entity dispatcher that includes TmxMapFacet
Nu recognizes several custom properties that can be added to tiles and layers in Tiled. These properties are engine-defined and have specific meanings within Nu.
These properties are added to individual tiles in a tileset:
Property Name: C (defined in Constants.TileMap.CollisionPropertyName)
Defines the collision shape for a tile. This is the most commonly used property.
Values:
-
Empty string
"": Creates a full tile box collider -
"Top": Creates a half-height box on the top half of the tile -
"Bottom": Creates a half-height box on the bottom half of the tile -
"Left": Creates a half-width box on the left half of the tile -
"Right": Creates a half-width box on the right half of the tile -
"TopLeft": Creates a quarter-size box in the top-left corner -
"TopRight": Creates a quarter-size box in the top-right corner -
"BottomLeft": Creates a quarter-size box in the bottom-left corner -
"BottomRight": Creates a quarter-size box in the bottom-right corner -
Custom BodyShape: You can provide a serialized
BodyShapeexpression for complex collision shapes
Example in Tiled:
<tile id="0">
<properties>
<property name="C" value=""/>
</properties>
</tile>Optimization: Adjacent tiles with full collision (empty C value) on the same row are automatically combined into horizontal strips for better physics performance.
Property Name: A (defined in Constants.TileMap.AnimationPropertyName)
Defines animated tile behavior using a TileAnimationDescriptor.
Format: Serialized TileAnimationDescriptor object
Usage: Allows tiles to animate by cycling through different tile indices over time.
Property Name: I (defined in Constants.TileMap.InfoPropertyName)
Reserved for user-defined metadata. The engine defines this constant but does not use it internally. You can use this property to store any custom information about tiles that your game logic needs to access.
Use cases:
- Tile type identifiers
- Gameplay properties (damage, healing, etc.)
- Spawn point markers
- Custom tile behavior flags
These properties are added to entire tile layers:
Property Name: E (defined in Constants.TileMap.ElevationPropertyName)
Specifies the rendering elevation offset for a layer.
Format: Numeric value (float)
Behavior:
- If not specified, layers are automatically spaced using:
layerIndex * TileLayerClearance - When specified, the elevation is:
baseElevation + E_value - Allows precise control over layer depth ordering
Example in Tiled:
<layer id="1" name="Background" width="32" height="13">
<properties>
<property name="E" value="0.0"/>
</properties>
...
</layer>Property Name: Image (TileSet custom property)
Specifies the image asset to use for a tileset.
Format: [PackageName AssetName]
Behavior:
- If not specified, Nu attempts to infer the image asset from the tileset's image source filename
- If inference fails, a
TileSetPropertyNotFoundExceptionis thrown - This property ensures the correct image asset is loaded, especially when asset names differ from file names
Example in Tiled: Add a custom property to the tileset:
Property Name: Image
Property Type: string
Property Value: [Default RoadTileSet]
Tile Maps in Nu automatically generate static physics bodies based on the C property:
-
Tile Collision Detection: Each tile with a
Cproperty generates a collision shape - Shape Optimization: Adjacent full-tile boxes are merged into strips
- Static Bodies: Tile Map bodies are always static (non-moving)
-
Collision Categories: Use
CollisionCategoriesandCollisionMaskto filter collisions
Example: Setting up collision filtering
entity.SetCollisionCategories "1" world
entity.SetCollisionMask "2,3,4" world // Collides with categories 2, 3, and 4Tile Maps are rendered with:
- View culling: Only visible tiles are rendered
- Layer support: Multiple layers with parallax scrolling
- Color tinting: Apply color and emission via entity properties
- Clipping: Optional clipping region support
Parallax Scrolling: Layers automatically respect Tiled's parallax X/Y properties for depth effects.
Contains the core TmxMap functionality:
-
TmxMap.makeFromFilePath- Load from file -
TmxMap.makeFromText- Load from string -
TmxMap.makeFromStream- Load from stream -
TmxMap.getDescriptor- Get tile map descriptor -
TmxMap.getBodyProperties- Generate physics body properties -
TmxMap.getLayeredMessages2d- Generate rendering messages -
TmxMap.getTileLayerBodyShapes- Extract collision shapes from tiles
Defines TileMapFacet and TmxMapFacet:
- Handles entity registration and physics setup
- Manages tile map rendering
- Auto-calculates entity bounds from tile map size
Provides ready-to-use dispatchers:
-
TileMapDispatcher- Asset-based tile maps -
TmxMapDispatcher- User-defined tile maps
World.doTileMap "TileMap"
[Entity.Elevation .= 10.0f
Entity.TileLayerClearance .= 2.0f
Entity.TileMap .= Assets.Gameplay.MyTileMap]// access tile information at runtime
let tileMap = entity.GetTmxMap world
let tileLayer = tileMap.TileLayers |> Seq.head
let tileIndex = 0
let tile = tileLayer.Tiles.[tileIndex]
// get the tile from the tileset
let gid = tile.Gid
let tileset = tileMap.Tilesets |> Seq.find (fun ts -> ts.FirstGid <= gid)
let tileId = gid - tileset.FirstGid
let tilesetTile = tileset.Tiles.[tileId]
// read custom "I" property
match tilesetTile.Properties.TryGetValue "I" with
| (true, infoValue) ->
// use your custom info value
printfn "Tile info: %s" infoValue
| (false, _) -> ()// Scale down the tile map by 2x
World.doTileMap "TileMap"
[Entity.TileSizeDivisor .= 2 // Each 64x64 tile becomes 32x32
Entity.TileMap .= Assets.Gameplay.MyTileMap]-
Use Empty Collision Strings: For simple full-tile collision, use an empty string for the
Cproperty to allow optimization - Layer Naming: Use descriptive layer names in Tiled - they don't affect functionality but help with organization
- Tile Grouping: Group tiles with similar collision properties to make property assignment easier
-
Custom Info: Use the
Iproperty consistently across your project for custom tile metadata - Compression: See the note below about TiledSharp performance issues with compression
- Tiled Map Editor Documentation
- Nu Engine Documentation
- Example games using TileMaps:
-
Blaze Vector - Located in
Projects/Blaze Vector Mmcc/ -
Omni Blade - Check the Nu repository's
omni-bladebranch for Omni Blade examples
-
Blaze Vector - Located in