wfc-tiles
This is a fork of https://github.com/Arkyris/blazinwfc, an implementation of the Wave Function Collapse simple tiled model. It can be used to generate tilemaps procedurally.
Usage
Basic
import { WFC } from "@daemon/wfc-tiles"; const wfc = new WFC({ options: { saveInterval: 0.02, defaultWeight: 10 }, tiles: [ { edges: ["floor", "floor", "floor", "floor"], type: "t_floor", weight: 30 }, { edges: ["floor", "wall", "floor", "wall"], type: "t_wall", weight: 3 }, { edges: ["wall", "floor", "wall", "floor"], type: "t_wall", weight: 3 }, ], compareEdge(a: string, b: string) { return a === b; }, }); wfc.collapse(20);
Advanced
An advanced example with 33 tiles:
function symmetries(tile: TileDefinition<number, number>): TileDefinition<number, number>[] { const symmetries: TileDefinition<number, number>[] = []; for (let i = 0; i < 4; i++) { const rotate = (d: Direction) => (d + i) % 4; const exceptions = tile.exceptions ? directions.map(d => tile.exceptions![rotate(d)]) as any : undefined; symmetries.push({ edges: directions.map(d => tile.edges[rotate(d)]) as any, type: tile.type, weight: tile.weight, exceptions, }); } return symmetries; } enum Tile { Floor, Wall, Wall2, Wall3, Room, Break, Connect }; enum Edge { Floor, Wall, Wall2, Room, Break, Wall3 = 201 }; const tiles: TileDefinition<number, number>[] = [ { edges: [Edge.Floor, Edge.Floor, Edge.Floor, Edge.Floor], type: Tile.Floor, weight: 30 }, { edges: [Edge.Floor, Edge.Wall, Edge.Floor, Edge.Wall], type: Tile.Wall, weight: 3 }, { edges: [Edge.Wall, Edge.Floor, Edge.Wall, Edge.Floor], type: Tile.Wall, weight: 3 }, ...symmetries({ edges: [Edge.Wall, Edge.Floor, Edge.Floor, Edge.Wall], type: Tile.Wall, weight: 3 }), ...symmetries({ edges: [Edge.Floor, Edge.Wall, Edge.Wall, Edge.Wall], type: Tile.Wall, weight: 3 }), ...symmetries({ edges: [Edge.Floor, Edge.Wall2, Edge.Floor, Edge.Wall], type: Tile.Wall2, weight: 3 }), { edges: [Edge.Wall2, Edge.Floor, Edge.Wall2, Edge.Floor], type: Tile.Wall2, weight: 1 }, { edges: [Edge.Floor, Edge.Wall2, Edge.Floor, Edge.Wall2], type: Tile.Wall2, weight: 10 }, { edges: [Edge.Floor, Edge.Wall, Edge.Floor, Edge.Wall], type: Tile.Break, weight: 1, exceptions: { [Direction.Left]: [Tile.Break], [Direction.Right]: [Tile.Break] } }, ...symmetries({ edges: [Edge.Wall3, Edge.Floor, Edge.Floor, -Edge.Wall3], type: Tile.Wall3, weight: 3, exceptions: { [Direction.Right]: [Tile.Wall3], [Direction.Down]: [Tile.Wall3] } }), ...symmetries({ edges: [Edge.Room, Edge.Wall3, Edge.Floor, -Edge.Wall3], type: Tile.Wall3, weight: 3, exceptions: { [Direction.Down]: [Tile.Wall3] } }), { edges: [Edge.Room, Edge.Room, Edge.Room, Edge.Room], type: Tile.Room, weight: 5 }, ...symmetries({ edges: [-Edge.Wall3, Edge.Room, Edge.Room, Edge.Wall3], type: Tile.Wall3, weight: 1 }), { edges: [Edge.Wall3, Edge.Wall2, -Edge.Wall3, Edge.Room], type: Tile.Connect, weight: 1 }, { edges: [-Edge.Wall3, Edge.Room, Edge.Wall3, Edge.Wall2], type: Tile.Connect, weight: 1 }, ]; const wfc = new WFC({ options: { saveInterval: 0.02, defaultWeight: 10 }, tiles, compareEdge(a: number, b: number) { // edges over 200 (eg. Edge.Wall3) only match if they're the mirror // version of the other edge if (b > 200 || b < -200) return a === -b; return a === b; }, }); const output = wfc.collapse(50);
In this example, the Tile and Edge types are enums for fast comparisons, but
they are generic, so you can use whatever type you want to model your tile
interactions with. The symmetries function is a utility function that generates
four tile definitions, each rotated 90°. You can define each tile explicitly
instead, or use more complex definition generation logic, for example based on
metadata attached to your tileset images.
Documentation
You can read the original readme most of still applies, or see the type documentations.
Add Package
deno add jsr:@daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Import directly with a jsr specifier
import * as wfc_tiles from "jsr:@daemon/wfc-tiles";
Add Package
pnpm i jsr:@daemon/wfc-tiles
pnpm dlx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
yarn add jsr:@daemon/wfc-tiles
yarn dlx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
vlt install jsr:@daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
npx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
bunx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";