npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@argila/tilemap

v0.1.0

Published

Chunked tilemaps for argila: Tiled loading, Canvas2D and Pixi rendering, Matter.js and Rapier collisions

Readme

@argila/tilemap

Chunked tilemaps for argila: Tiled maps loaded into a tilemap component, drawn by core's Render (Canvas2D) or by @argila/pixi, colliding through Matter.js or Rapier.

  • Tilemap: layers and tilesets on one entity, the tiles kept in 16×16 chunks. Tilemap.fromTiled(json, textures) reads a Tiled JSON export (orthogonal or isometric), Tilemap.setTile and getTile edit and read it.
  • TilemapRender: pre-draws each chunk layer once to a canvas and shows it as a sprite, so Render sorts it with everything else. Chunks outside the camera are hidden.
  • TilemapPixiRender (@argila/tilemap/pixi): a mesh per chunk layer and tileset.
  • TilemapCollider (@argila/tilemap/matter): static bodies for the solid, one-way and sloped tiles, rebuilt per chunk when tiles change.
  • TilemapRapierCollider (@argila/tilemap/rapier): fixed Rapier boxes for the solid tiles, from each layer's elevation up one block, merged per chunk and rebuilt when tiles change (see @argila/rapier).
  • TileQuery: what is at a point (solid, floor below, liquid), asked straight from the tiles.
  • readTiledObjects and ObjectSpawner: the map's objects, spawned by type.
  • TilemapDebug (@argila/tilemap/debug): collider and chunk overlays for the debug views.
import { Assets, Entity, Render, Transform, World } from "@argila/core";
import { isTiledMap, Tilemap, TilemapRender } from "@argila/tilemap";

const json = await Assets.loadJSON("level.json", isTiledMap);
const map = Entity.create(world);
Transform.create(map, 0, 0);
Tilemap.create(map, Tilemap.fromTiled(json, { terrain: await Assets.load("terrain.png") }));
Render.create(map, "main");
World.addSystem(world, TilemapRender);

Isometric maps

An isometric (diamond) map is a top-down map drawn at a slant. It lives in ground space, a flat top-down plane: each cell is a tileheight × tileheight square there, which is Tiled's own convention for the object coordinates of isometric maps. The slant is the camera's view projection, applied only when drawing. So the colliders, TileQuery, Tilemap.worldToTile and the objects from readTiledObjects work exactly as on an orthogonal map, in ground pixels.

Tilemap.create(map, Tilemap.fromTiled(json, textures)); // orientation: "isometric"
Camera.configure(camera, { projection: Tilemap.projection(map), target: hero });
Render.setDepthSort(world, true); // props from the object layer sort by depth
  • Tilemap.projection(map) is the projection that shows the map as authored: Isometric.projection(tilewidth, tileheight) for an isometric map, undefined for an orthogonal one. The map records its orientation and its art tile size (artTileWidth, artTileHeight), while tileWidth and tileHeight are the ground cell.
  • The renderers draw each chunk as the camera sees it: the diamonds back to front, each picture standing on its diamond with its tileset's offset, as Tiled draws them. Each chunk is placed upright at its projected ground origin, so it lines up with its neighbours. Seen without a projection, the same map is drawn top-down, its diamonds flattened into ground squares. An orthogonal map seen through an isometric camera turns into diamonds.
  • Culling takes the camera's view back into ground space, so no visible chunk is hidden. Camera bounds are in view space: Projection.boundsInto(Tilemap.projection(map), 0, 0, width, height, bounds) gives the box around the map's diamond.
  • Tile layers are flat floors: each layer is drawn at one zIndex. Make walls you walk behind, trees and pillars entities from an object layer (ObjectSpawner), at the zIndex of the things that move among them, and turn on depth sorting (Render.setDepthSort(world, true)). Anchor tall sprites at their feet (Sprite.setAnchor(e, 0.5, 1)) so they sort by where they stand. A tall tile in a tile layer still draws, but over or under what moves near it as its whole layer does.
  • Slopes and tile collision polygons of an isometric map are read in the ground cell (a tileheight square, origin at its top-left corner), not in the tile's picture.
  • Isometric drawing assumes a map with a uniform scale and no rotation. Staggered and hexagonal maps are not supported.

Raised layers

A layer's elevation custom property (a number, in ground units, 0 by default) raises it: ground space is x and y on the ground, and elevation is z, up, as on transforms.

  • A tile layer with an elevation draws all of its chunks at that z (above the map entity's own), so layers stacked at rising elevations make raised ground: a terrace, a rooftop. Under an isometric camera one ground unit up is one view pixel up (Isometric.projection's rise); seen without a projection, elevation moves nothing. It is read once, into TileLayer.elevation, when the layer is made (properties: { elevation: 32 } for a layer built in code).
  • Culling accounts for it: the view is taken back into ground space on the planes of the lowest and the highest layer, so a raised chunk is shown where it is drawn.
  • An object layer's elevation is its objects' z (MapObject.z, from readTiledObjects): give the entity a spawn makes that z (Transform.setZ) to put it on the raised ground.
  • Only a layer's own property counts: a group's doesn't add to its layers'.
  • readElevation(properties) reads the property the way the renderers do (a finite number, else 0), for anything else that needs it, like colliders with heights.
  • The debug views draw at the elevations too: colliders and tile queries at the colliding layers' (the lowest when they differ), chunk outlines at each of their layers', objects at their z.
  • The colliders from @argila/tilemap/matter stay flat: Matter knows no heights. The ones from @argila/tilemap/rapier have them: each solid tile is a box from its layer's elevation up blockHeight, so stacked layers make ledges and stairs a Rapier character can climb.