embed isometric
rooms with one
script tag.

Ducket Suites is a lightweight renderer for isometric rooms and animated furniture — inspired by classic hotel-style pixel worlds. Drop it on any page, no build step required.

PixiJS v8 ~145 KB gzipped zero config
install.sh
# via CDN — zero-config embed
<script src="https://docs.ducket.net/dist/ducket-suites.global.js"></script>

# or via npm
$ npm i @ducket/suites
live.demo open in dev →
loading…

quick start

Include the CDN script, create a container, and render your first room.

<!-- 1. add the script -->
<script src="https://docs.ducket.net/dist/ducket-suites.global.js"></script>

<div id="room" style="width:800px;height:500px"></div>

<script>
(async function() {
  // 2. boot pixi
  var app = new DucketSuites.Application();
  await app.init({
    resizeTo: document.getElementById("room"),
    background: 0x0b1019,
  });
  document.getElementById("room").appendChild(app.canvas);

  // 3. create a room
  var room = new DucketSuites.Room({
    tilemap: "xxxxx\nx0000\n00000\nx0000\nx0000",
    wallColor:  "#B5B7C4",
    floorColor: "#FBC02D",
  });
  app.stage.addChild(room);

  // 4. place furniture
  var catalog = new DucketSuites.FurniCatalog();
  await room.furnish([
    { type: "throne", x: 2, y: 2, z: 0, dir: 4 },
  ], catalog);
})();
</script>

api reference

class Room

The main container. Parses a tilemap string and renders isometric walls, tiles, stairs, and furniture.

constructor options

fieldtypedescription
tilemapstringTilemap string. x=void, 0-9=floor height
wallColorstring?Hex wall colour, e.g. "#B5B7C4"
floorColorstring?Hex floor colour

properties

nametypedescription
wallHeightnumberWall height px (default 116)
tileHeightnumberTile thickness px (default 8)
hideWallsbooleanToggle wall visibility
hideFloorbooleanToggle floor visibility
hideTileCursorbooleanToggle hover cursor
roomBounds{minX,maxX,minY,maxY}Bounds for centering

methods

signaturedescription
furnish(items, catalog?)Place an array of descriptors. Returns Promise<FloorFurniture[]>
addFloorFurniture(f)Add a single FloorFurniture
removeFloorFurniture(f)Remove a furniture piece
getScreenPosition(x,y,z)Convert room → screen pixel position
destroy()Clean up all resources

class FloorFurniture

A single piece of furniture — load from a .ducket URL or via the catalog.

constructor options

fieldtypedescription
roomXnumberColumn
roomYnumberRow
roomZnumberFloor height level
directionnumber0=N, 2=E, 4=S, 6=W
animationstring?Animation state id
colorstring | number?Palette colour id (from v.*.cl)

methods

signaturedescription
load(url)Load from a .ducket URL (returns a Promise)
loadFromDucket(bundle)Load from a pre-decoded DucketBundle

All constructor options are also read/write properties — e.g. assigning f.roomX = 5 moves the furniture live.

class FurniCatalog

Fetches furnidata.xml and resolves classnames ("throne") to download URLs.

signaturereturnsdescription
new FurniCatalog(opts?)Defaults to https://cdn.ducket.net
resolveUrl(classname)Promise<string>Classname → .ducket URL
search(query, limit?)FurniInfo[]Search by name or classname
ready()Promise<void>Resolves when furnidata is loaded

tilemaps

Tilemaps are multiline strings. Each character is a tile:

// simple flat room with door
var flat = [
  "xxxxx",
  "x0000",
  "00000",   // ← door row
  "x0000",
  "x0000",
].join("\n");

// raised platform — stairs auto-generated
var raised = [
  "xxxxxxxxx",
  "x00000000",
  "000000000",
  "x00111100",   // height 1 platform
  "x00111100",
  "x00000000",
].join("\n");

furniture

batch via catalog (recommended)

Pass an array of descriptors to room.furnish() — bundles are deduped and fetched in parallel.

var catalog = new DucketSuites.FurniCatalog();

await room.furnish([
  { type: "throne",              x: 3, y: 3, z: 0, dir: 4 },
  { type: "nft_h23_trippy_aloe", x: 1, y: 1, z: 0, dir: 2, anim: "0" },
  { type: "hc23_11",            x: 5, y: 2, z: 0, dir: 6, anim: "0" },
], catalog);

individual by direct URL

var f = new DucketSuites.FloorFurniture({
  roomX: 4, roomY: 3, roomZ: 0, direction: 2
});
await f.load("https://cdn.ducket.net/hof_furni/65456/throne.ducket");
room.addFloorFurniture(f);

// move it later — reactive setters
f.roomX = 6;
f.direction = 4;

FurnitureItemDescriptor

fieldtypedescription
typestringClassname from furnidata (needs FurniCatalog)
urlstringDirect .ducket URL (alt to type)
xnumberColumn
ynumberRow
znumberHeight level
dirnumberFacing: 0 N, 2 E, 4 S, 6 W
animstring?Animation state

events

Assign callback properties directly on the room instance:

room.onTileClick = function(pos) {
  console.log("clicked", pos.roomX, pos.roomY, pos.roomZ);
};

room.onTileOver = function(pos) {
  console.log("hover", pos.roomX, pos.roomY);
};

room.onTileOut = function() {
  console.log("left tiles");
};

room.onActiveWallChange = function(info) {
  if (info) console.log(info.wall, info.roomX, info.roomY);
};
eventcallback argdescription
onTileClick{ roomX, roomY, roomZ }User clicks a floor tile
onTileOver{ roomX, roomY, roomZ }Pointer enters a tile
onTileOut(none)Pointer leaves all tiles
onActiveWallChangeActiveWallInfo | undefinedPointer enters/leaves a wall