DUCKET
 SUITES

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 ~145KB gzipped Zero config
room renderer
=Ducket=
Tilemap: 13 × 11
Height levels: 0, 1, 2
Furniture: 20 items
Animated: yes
Door row: row 2
CDN: cloudflare
ready to embed
live demo
loading...
the room
a pixi container that renders tiles, walls, stairs, and handles events.
furniture
animated sprites loaded from .shroom bundles at any x/y/z position.
hover & click
every tile reports its room coords — build editors, games, or tools.

01QUICK START

drop in & render

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

<!-- 1. add the script -->
<script src="https://ducket-suites.pages.dev/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: 0x0b1938,
  });
  document.getElementById("room").appendChild(app.canvas);

  // 3. create a room
  var room = new DucketSuites.Room({
    tilemap: "xxxxx\nx0000\n00000\nx0000\nx0000",
    wallColor:  "#89B8CF",
    floorColor: "#FFD000",
  });
  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>

02API 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. "#89B8CF"
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 furniture 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 .shroom 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

methods

signaturedescription
load(url)Load from a .shroom URL (returns a Promise)
loadFromBundle(bundle)Load from a pre-fetched ShroomAssetBundle

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(resourcePath?)Defaults to https://ducket.net/resources
resolveUrl(classname)Promise<string>Classname → .shroom URL
search(query, limit?)FurniInfo[]Search by name or classname
ready()Promise<void>Resolves when furnidata is loaded

03TILEMAPS

string-based room layouts

Tilemaps are multiline strings. Each character is a tile:

  • x — void (no tile)
  • 09 — floor at that height level
  • A row with no leading x is the door row
  • Height transitions auto-generate stairs
// 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");

04FURNITURE

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://ducket.net/resources/hof_furni/12345/throne.shroom");
room.addFloorFurniture(f);

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

FurnitureItemDescriptor

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

05EVENTS

interaction callbacks

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