@mertdogar/phaser-procedural-walls 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Wallcraft Prototype</title>
7
+ <script type="module" crossorigin src="/assets/index-DvPiYA-G.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-BVmRKDUb.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,65 @@
1
+ const g = { lipHeight: 0, windowInset: 0.6 };
2
+ function W(t) {
3
+ var n;
4
+ if (t.x1 !== t.x2 && t.y1 !== t.y2)
5
+ throw new Error(`Wall is not axis-aligned: (${t.x1},${t.y1})-(${t.x2},${t.y2})`);
6
+ if (!(t.x1 > t.x2 || t.y1 > t.y2)) return t;
7
+ const h = Math.abs(t.x2 - t.x1) + Math.abs(t.y2 - t.y1);
8
+ return {
9
+ ...t,
10
+ x1: t.x2,
11
+ y1: t.y2,
12
+ x2: t.x1,
13
+ y2: t.y1,
14
+ windows: (n = t.windows) == null ? void 0 : n.map((s) => ({ ...s, offset: h - s.offset - s.width }))
15
+ };
16
+ }
17
+ function L(t, i, h) {
18
+ const n = t >= Math.min(h.x1, h.x2) && t <= Math.max(h.x1, h.x2), s = i >= Math.min(h.y1, h.y2) && i <= Math.max(h.y1, h.y2);
19
+ return n && s;
20
+ }
21
+ function b(t, i, h, n) {
22
+ let s = 0;
23
+ for (const l of n)
24
+ l !== h && L(t, i, l) && (s = Math.max(s, l.thickness / 2));
25
+ return s;
26
+ }
27
+ function H(t, i, h) {
28
+ if (i.length === 0) return [t];
29
+ const n = [], s = t.x + t.w, l = t.y + t.h;
30
+ if (h) {
31
+ const o = Math.min(...i.map((x) => x.y)), f = Math.max(...i.map((x) => x.y + x.h));
32
+ o > t.y && n.push({ x: t.x, y: t.y, w: t.w, h: o - t.y }), f < l && n.push({ x: t.x, y: f, w: t.w, h: l - f });
33
+ let p = t.x;
34
+ for (const x of [...i].sort((u, y) => u.x - y.x))
35
+ x.x > p && n.push({ x: p, y: o, w: x.x - p, h: f - o }), p = x.x + x.w;
36
+ return p < s && n.push({ x: p, y: o, w: s - p, h: f - o }), n;
37
+ }
38
+ const e = Math.min(...i.map((o) => o.x)), c = Math.max(...i.map((o) => o.x + o.w));
39
+ e > t.x && n.push({ x: t.x, y: t.y, w: e - t.x, h: t.h }), c < s && n.push({ x: c, y: t.y, w: s - c, h: t.h });
40
+ let a = t.y;
41
+ for (const o of [...i].sort((f, p) => f.y - p.y))
42
+ o.y > a && n.push({ x: e, y: a, w: c - e, h: o.y - a }), a = o.y + o.h;
43
+ return a < l && n.push({ x: e, y: a, w: c - e, h: l - a }), n;
44
+ }
45
+ function P(t, i) {
46
+ const h = t.map(W);
47
+ return h.map((n) => {
48
+ const s = i[n.preset];
49
+ if (!s) throw new Error(`Unknown wall preset "${n.preset}"`);
50
+ const l = n.height ?? s.lipHeight ?? g.lipHeight, e = s.windowInset ?? g.windowInset, c = s.sillHeight ?? n.thickness, a = n.thickness, o = a / 2, f = b(n.x1, n.y1, n, h), p = b(n.x2, n.y2, n, h), x = n.y1 === n.y2, u = x ? { x: n.x1 - f, y: n.y1 - o, w: n.x2 - n.x1 + f + p, h: a } : { x: n.x1 - o, y: n.y1 - f, w: a, h: n.y2 - n.y1 + f + p }, y = l <= 0 ? null : { x: u.x, y: u.y + u.h, w: u.w, h: l }, m = (n.windows ?? []).map((r) => {
51
+ if (!x) return { x: n.x1 - o * e, y: n.y1 + r.offset, w: a * e, h: r.width };
52
+ const d = n.x1 + r.offset;
53
+ return y ? { x: d, y: Math.round(y.y + y.h * (1 - e) / 2), w: r.width, h: Math.round(y.h * e) } : { x: d, y: n.y1 - o * e, w: r.width, h: a * e };
54
+ }), M = x && y !== null, E = M && c > 0 ? m.map((r) => {
55
+ const d = Math.min(c, r.h);
56
+ return { x: r.x, y: r.y + r.h - d, w: r.w, h: d };
57
+ }) : [], $ = H(u, M ? [] : m, x), k = y ? H(y, M ? m : [], !0) : [], I = u.y + u.h + (y ? y.h : 0), z = { ...u, y: u.y + (y ? y.h : 0) };
58
+ return { spec: n, horizontal: x, body: u, lip: y, bodyPieces: $, lipPieces: k, windows: m, sills: E, collider: z, depth: n.depth ?? I };
59
+ });
60
+ }
61
+ export {
62
+ H as cutRects,
63
+ b as endExtension,
64
+ P as resolveWalls
65
+ };
package/dist/index.js CHANGED
@@ -1,77 +1,18 @@
1
- var F = Object.defineProperty;
2
- var z = (i, n, s) => n in i ? F(i, n, { enumerable: !0, configurable: !0, writable: !0, value: s }) : i[n] = s;
3
- var g = (i, n, s) => z(i, typeof n != "symbol" ? n + "" : n, s);
4
- import I from "phaser";
5
- const M = { lipHeight: 0, windowInset: 0.6, sillHeight: 8 }, S = 8;
6
- function $(i) {
7
- var t;
8
- if (i.x1 !== i.x2 && i.y1 !== i.y2)
9
- throw new Error(`Wall is not axis-aligned: (${i.x1},${i.y1})-(${i.x2},${i.y2})`);
10
- if (!(i.x1 > i.x2 || i.y1 > i.y2)) return i;
11
- const s = Math.abs(i.x2 - i.x1) + Math.abs(i.y2 - i.y1);
12
- return {
13
- ...i,
14
- x1: i.x2,
15
- y1: i.y2,
16
- x2: i.x1,
17
- y2: i.y1,
18
- windows: (t = i.windows) == null ? void 0 : t.map((e) => ({ ...e, offset: s - e.offset - e.width }))
19
- };
20
- }
21
- function T(i, n, s) {
22
- const t = i >= Math.min(s.x1, s.x2) && i <= Math.max(s.x1, s.x2), e = n >= Math.min(s.y1, s.y2) && n <= Math.max(s.y1, s.y2);
23
- return t && e;
24
- }
25
- function P(i, n, s, t) {
26
- let e = 0;
27
- for (const h of t)
28
- h !== s && T(i, n, h) && (e = Math.max(e, h.thickness / 2));
29
- return e;
30
- }
31
- function R(i, n, s) {
32
- if (n.length === 0) return [i];
33
- const t = [], e = i.x + i.w, h = i.y + i.h;
34
- if (s) {
35
- const l = Math.min(...n.map((d) => d.y)), a = Math.max(...n.map((d) => d.y + d.h));
36
- l > i.y && t.push({ x: i.x, y: i.y, w: i.w, h: l - i.y }), a < h && t.push({ x: i.x, y: a, w: i.w, h: h - a });
37
- let c = i.x;
38
- for (const d of [...n].sort((f, o) => f.x - o.x))
39
- d.x > c && t.push({ x: c, y: l, w: d.x - c, h: a - l }), c = d.x + d.w;
40
- return c < e && t.push({ x: c, y: l, w: e - c, h: a - l }), t;
41
- }
42
- const y = Math.min(...n.map((l) => l.x)), r = Math.max(...n.map((l) => l.x + l.w));
43
- y > i.x && t.push({ x: i.x, y: i.y, w: y - i.x, h: i.h }), r < e && t.push({ x: r, y: i.y, w: e - r, h: i.h });
44
- let x = i.y;
45
- for (const l of [...n].sort((a, c) => a.y - c.y))
46
- l.y > x && t.push({ x: y, y: x, w: r - y, h: l.y - x }), x = l.y + l.h;
47
- return x < h && t.push({ x: y, y: x, w: r - y, h: h - x }), t;
48
- }
49
- function v(i, n) {
50
- const s = i.map($);
51
- return s.map((t) => {
52
- const e = n[t.preset];
53
- if (!e) throw new Error(`Unknown wall preset "${t.preset}"`);
54
- const h = e.lipHeight ?? M.lipHeight, y = e.windowInset ?? M.windowInset, r = e.sillHeight ?? M.sillHeight, x = t.thickness, l = x / 2, a = P(t.x1, t.y1, t, s), c = P(t.x2, t.y2, t, s), d = t.y1 === t.y2, f = d ? { x: t.x1 - a, y: t.y1 - l, w: t.x2 - t.x1 + a + c, h: x } : { x: t.x1 - l, y: t.y1 - a, w: x, h: t.y2 - t.y1 + a + c }, o = h <= 0 ? null : { x: f.x, y: f.y + f.h, w: f.w, h }, m = (t.windows ?? []).map((u) => {
55
- if (!d) return { x: t.x1 - l * y, y: t.y1 + u.offset, w: x * y, h: u.width };
56
- const p = t.x1 + u.offset;
57
- return o ? { x: p, y: Math.round(o.y + o.h * (1 - y) / 2), w: u.width, h: Math.round(o.h * y) } : { x: p, y: t.y1 - l * y, w: u.width, h: x * y };
58
- }), w = d && o !== null, W = w && r > 0 ? m.map((u) => {
59
- const p = Math.min(r, u.h);
60
- return { x: u.x, y: u.y + u.h - p, w: u.w, h: p };
61
- }) : [], H = R(f, w ? [] : m, d), E = o ? R(o, w ? m : [], !0) : [], b = f.y + f.h + (o ? o.h : 0), k = d ? { x: f.x, y: b - S, w: f.w, h: S } : { x: f.x, y: f.y, w: f.w, h: b - f.y };
62
- return { spec: t, horizontal: d, body: f, lip: o, bodyPieces: H, lipPieces: E, windows: m, sills: W, collider: k, depth: b };
63
- });
64
- }
65
- class A {
66
- constructor(n, s) {
67
- g(this, "scene");
68
- g(this, "containers", []);
69
- g(this, "bodies", null);
70
- g(this, "config");
71
- this.scene = n, this.config = s, this.build();
1
+ var g = Object.defineProperty;
2
+ var x = (n, t, i) => t in n ? g(n, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : n[t] = i;
3
+ var a = (n, t, i) => x(n, typeof t != "symbol" ? t + "" : t, i);
4
+ import b from "phaser";
5
+ import { resolveWalls as p } from "./geometry.js";
6
+ class R {
7
+ constructor(t, i) {
8
+ a(this, "scene");
9
+ a(this, "containers", []);
10
+ a(this, "bodies", null);
11
+ a(this, "config");
12
+ this.scene = t, this.config = i, this.build();
72
13
  }
73
- setWalls(n) {
74
- return this.config = { ...this.config, walls: n }, this.clear(), this.build(), this;
14
+ setWalls(t) {
15
+ return this.config = { ...this.config, walls: t }, this.clear(), this.build(), this;
75
16
  }
76
17
  redraw() {
77
18
  return this.clear(), this.build(), this;
@@ -80,52 +21,52 @@ class A {
80
21
  this.clear();
81
22
  }
82
23
  clear() {
83
- var n;
84
- for (const s of this.containers) s.destroy();
85
- this.containers = [], (n = this.bodies) == null || n.destroy(!0), this.bodies = null;
24
+ var t;
25
+ for (const i of this.containers) i.destroy();
26
+ this.containers = [], (t = this.bodies) == null || t.destroy(!0), this.bodies = null;
86
27
  }
87
28
  build() {
88
- const { presets: n, walls: s, collide: t } = this.config, e = v(s, n);
89
- t && (this.bodies = this.scene.physics.add.staticGroup());
90
- for (const h of e)
91
- this.containers.push(this.drawWall(h, n[h.spec.preset])), this.bodies && this.addBody(h);
29
+ const { presets: t, walls: i, collide: s } = this.config, o = p(i, t);
30
+ s && (this.bodies = this.scene.physics.add.staticGroup());
31
+ for (const l of o)
32
+ this.containers.push(this.drawWall(l, t[l.spec.preset])), this.bodies && this.addBody(l);
92
33
  }
93
- drawWall(n, s) {
94
- const { body: t, lip: e, bodyPieces: h, lipPieces: y, windows: r, sills: x } = n, l = this.scene.add.container(0, 0), a = this.scene.add.graphics(), c = this.scene.add.graphics(), d = s.edgeWidth ?? 2;
95
- for (const o of h) this.fillRect(l, a, o, s.fill, s.texture);
96
- for (const o of y) this.fillRect(l, a, o, s.lipFill ?? s.fill, s.lipTexture);
97
- const f = s.windowFill ?? 4030344;
98
- for (const o of r)
99
- a.fillStyle(f, s.windowAlpha ?? 0.5), a.fillRect(o.x, o.y, o.w, o.h);
100
- l.add(a);
101
- for (const o of x) this.fillRect(l, c, o, s.fill, s.texture);
102
- for (const o of x) c.lineStyle(1, s.edge).lineBetween(o.x, o.y, o.x + o.w, o.y);
103
- if (s.windowFrame !== void 0)
104
- for (const o of r) c.lineStyle(1, s.windowFrame).strokeRect(o.x, o.y, o.w, o.h);
105
- return c.lineStyle(d, s.edge), c.strokeRect(t.x, t.y, t.w, t.h), e && c.lineStyle(d, s.edge).strokeRect(e.x, e.y, e.w, e.h), l.add(c), l.setDepth(n.depth), l;
34
+ drawWall(t, i) {
35
+ const { body: s, lip: o, bodyPieces: l, lipPieces: r, windows: f, sills: w } = t, c = this.scene.add.container(0, 0), h = this.scene.add.graphics(), d = this.scene.add.graphics(), y = i.edgeWidth ?? 2;
36
+ for (const e of l) this.fillRect(c, h, e, i.fill, i.texture);
37
+ for (const e of r) this.fillRect(c, h, e, i.lipFill ?? i.fill, i.lipTexture);
38
+ const u = i.windowFill ?? 4030344;
39
+ for (const e of f)
40
+ h.fillStyle(u, i.windowAlpha ?? 0.5), h.fillRect(e.x, e.y, e.w, e.h);
41
+ c.add(h);
42
+ for (const e of w) this.fillRect(c, d, e, i.fill, i.texture);
43
+ for (const e of w) d.lineStyle(1, i.edge).lineBetween(e.x, e.y, e.x + e.w, e.y);
44
+ if (i.windowFrame !== void 0)
45
+ for (const e of f) d.lineStyle(1, i.windowFrame).strokeRect(e.x, e.y, e.w, e.h);
46
+ return d.lineStyle(y, i.edge), d.strokeRect(s.x, s.y, s.w, s.h), o && d.lineStyle(y, i.edge).strokeRect(o.x, o.y, o.w, o.h), c.add(d), c.setDepth(t.depth), c;
106
47
  }
107
- fillRect(n, s, t, e, h) {
108
- if (!h) {
109
- s.fillStyle(e).fillRect(t.x, t.y, t.w, t.h);
48
+ fillRect(t, i, s, o, l) {
49
+ if (!l) {
50
+ i.fillStyle(o).fillRect(s.x, s.y, s.w, s.h);
110
51
  return;
111
52
  }
112
- const y = this.scene.add.tileSprite(t.x + t.w / 2, t.y + t.h / 2, t.w, t.h, h);
113
- y.setTilePosition(t.x, t.y), n.add(y);
53
+ const r = this.scene.add.tileSprite(s.x + s.w / 2, s.y + s.h / 2, s.w, s.h, l);
54
+ r.setTilePosition(s.x, s.y), t.add(r);
114
55
  }
115
- addBody(n) {
116
- const { collider: s } = n, t = this.scene.add.zone(s.x + s.w / 2, s.y + s.h / 2, s.w, s.h);
117
- this.scene.physics.add.existing(t, !0), this.bodies.add(t);
56
+ addBody(t) {
57
+ const { collider: i } = t, s = this.scene.add.zone(i.x + i.w / 2, i.y + i.h / 2, i.w, i.h);
58
+ this.scene.physics.add.existing(s, !0), this.bodies.add(s);
118
59
  }
119
60
  }
120
- class D extends I.Plugins.ScenePlugin {
121
- constructor(n, s, t) {
122
- super(n, s, t), typeof n.add.wallMap != "function" && s.registerGameObject("wallMap", function(e) {
123
- return new A(this.scene, e);
61
+ class P extends b.Plugins.ScenePlugin {
62
+ constructor(t, i, s) {
63
+ super(t, i, s), typeof t.add.wallMap != "function" && i.registerGameObject("wallMap", function(o) {
64
+ return new R(this.scene, o);
124
65
  });
125
66
  }
126
67
  }
127
68
  export {
128
- A as WallMap,
129
- D as WallMapPlugin,
130
- v as resolveWalls
69
+ R as WallMap,
70
+ P as WallMapPlugin,
71
+ p as resolveWalls
131
72
  };
package/dist/types.d.ts CHANGED
@@ -22,6 +22,8 @@ export interface WallSpec {
22
22
  x2: number;
23
23
  y2: number;
24
24
  thickness: number;
25
+ height?: number;
26
+ depth?: number;
25
27
  preset: string;
26
28
  windows?: WindowSpec[];
27
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mertdogar/phaser-procedural-walls",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Phaser 4 scene plugin that renders procedural top-down walls with faces, see-through windows, depth sorting and Arcade colliders from wall centerline data.",
5
5
  "keywords": [
6
6
  "phaser",
@@ -27,16 +27,24 @@
27
27
  "main": "./dist/index.js",
28
28
  "module": "./dist/index.js",
29
29
  "types": "./dist/index.d.ts",
30
+ "bin": {
31
+ "phaser-procedural-walls": "./bin/cli.mjs"
32
+ },
30
33
  "exports": {
31
34
  ".": {
32
35
  "types": "./dist/index.d.ts",
33
36
  "import": "./dist/index.js"
34
37
  },
35
- "./package.json": "./package.json"
38
+ "./package.json": "./package.json",
39
+ "./geometry": {
40
+ "types": "./dist/geometry.d.ts",
41
+ "import": "./dist/geometry.js"
42
+ }
36
43
  },
37
44
  "sideEffects": false,
38
45
  "files": [
39
46
  "dist",
47
+ "bin",
40
48
  "LICENSE"
41
49
  ],
42
50
  "engines": {
@@ -47,20 +55,38 @@
47
55
  },
48
56
  "scripts": {
49
57
  "dev": "vite",
50
- "build": "vite build && tsc -p tsconfig.lib.json",
58
+ "build": "vite build && tsc -p tsconfig.lib.json && vite build --mode editor",
59
+ "editor": "node bin/cli.mjs editor",
60
+ "test:cli": "node --test tests/cli.test.mjs",
51
61
  "test": "vitest run",
52
62
  "typecheck": "tsc --noEmit",
53
- "lint": "oxlint src demo tests",
54
- "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm test && pnpm build"
63
+ "lint": "oxlint src demo tests bin",
64
+ "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm test && pnpm build && pnpm test:cli"
55
65
  },
56
66
  "peerDependencies": {
57
67
  "phaser": "^4.0.0"
58
68
  },
59
69
  "devDependencies": {
70
+ "@tailwindcss/vite": "^4.3.3",
71
+ "@types/react": "^19.3.0",
72
+ "@types/react-dom": "^19.3.0",
73
+ "@vitejs/plugin-react": "^5.2.0",
60
74
  "oxlint": "^1.0.0",
61
75
  "phaser": "^4.2.1",
76
+ "tailwindcss": "^4.3.3",
62
77
  "typescript": "^5.6.0",
63
78
  "vite": "^6.0.0",
64
79
  "vitest": "^3.0.0"
80
+ },
81
+ "dependencies": {
82
+ "class-variance-authority": "^0.7.1",
83
+ "clsx": "^2.1.1",
84
+ "cn": "^0.3.0",
85
+ "lucide-react": "^1.47.0",
86
+ "radix-ui": "^1.6.7",
87
+ "react": "^19.3.0",
88
+ "react-dom": "^19.3.0",
89
+ "react-resizable-panels": "^4.12.4",
90
+ "tailwind-merge": "^3.7.0"
65
91
  }
66
92
  }