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.
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);
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.
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";
---- OR ----
Import directly with a jsr specifier
import * as wfc_tiles from "jsr:@daemon/wfc-tiles";
Add Package
npx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
yarn dlx jsr add @daemon/wfc-tiles
Import symbol
import * as wfc_tiles from "@daemon/wfc-tiles";
Add Package
pnpm dlx 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";