@mertdogar/phaser-procedural-walls 0.1.0 → 0.2.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.
- package/README.md +31 -3
- package/bin/cli.mjs +54 -0
- package/dist/editor/assets/index-DSUxG7JP.css +1 -0
- package/dist/editor/assets/index-JowJrAjF.js +7052 -0
- package/dist/editor/index.html +13 -0
- package/dist/geometry.js +65 -0
- package/dist/index.js +49 -108
- package/dist/types.d.ts +2 -0
- package/package.json +35 -11
|
@@ -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-JowJrAjF.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DSUxG7JP.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const H = { lipHeight: 0, windowInset: 0.6, sillHeight: 8 }, E = 8;
|
|
2
|
+
function L(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 P(t, y, h) {
|
|
18
|
+
const n = t >= Math.min(h.x1, h.x2) && t <= Math.max(h.x1, h.x2), s = y >= Math.min(h.y1, h.y2) && y <= Math.max(h.y1, h.y2);
|
|
19
|
+
return n && s;
|
|
20
|
+
}
|
|
21
|
+
function b(t, y, h, n) {
|
|
22
|
+
let s = 0;
|
|
23
|
+
for (const u of n)
|
|
24
|
+
u !== h && P(t, y, u) && (s = Math.max(s, u.thickness / 2));
|
|
25
|
+
return s;
|
|
26
|
+
}
|
|
27
|
+
function I(t, y, h) {
|
|
28
|
+
if (y.length === 0) return [t];
|
|
29
|
+
const n = [], s = t.x + t.w, u = t.y + t.h;
|
|
30
|
+
if (h) {
|
|
31
|
+
const o = Math.min(...y.map((i) => i.y)), f = Math.max(...y.map((i) => i.y + i.h));
|
|
32
|
+
o > t.y && n.push({ x: t.x, y: t.y, w: t.w, h: o - t.y }), f < u && n.push({ x: t.x, y: f, w: t.w, h: u - f });
|
|
33
|
+
let l = t.x;
|
|
34
|
+
for (const i of [...y].sort((x, p) => x.x - p.x))
|
|
35
|
+
i.x > l && n.push({ x: l, y: o, w: i.x - l, h: f - o }), l = i.x + i.w;
|
|
36
|
+
return l < s && n.push({ x: l, y: o, w: s - l, h: f - o }), n;
|
|
37
|
+
}
|
|
38
|
+
const e = Math.min(...y.map((o) => o.x)), c = Math.max(...y.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 [...y].sort((f, l) => f.y - l.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 < u && n.push({ x: e, y: a, w: c - e, h: u - a }), n;
|
|
44
|
+
}
|
|
45
|
+
function W(t, y) {
|
|
46
|
+
const h = t.map(L);
|
|
47
|
+
return h.map((n) => {
|
|
48
|
+
const s = y[n.preset];
|
|
49
|
+
if (!s) throw new Error(`Unknown wall preset "${n.preset}"`);
|
|
50
|
+
const u = n.height ?? s.lipHeight ?? H.lipHeight, e = s.windowInset ?? H.windowInset, c = s.sillHeight ?? H.sillHeight, a = n.thickness, o = a / 2, f = b(n.x1, n.y1, n, h), l = b(n.x2, n.y2, n, h), i = n.y1 === n.y2, x = i ? { x: n.x1 - f, y: n.y1 - o, w: n.x2 - n.x1 + f + l, h: a } : { x: n.x1 - o, y: n.y1 - f, w: a, h: n.y2 - n.y1 + f + l }, p = u <= 0 ? null : { x: x.x, y: x.y + x.h, w: x.w, h: u }, m = (n.windows ?? []).map((r) => {
|
|
51
|
+
if (!i) 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 p ? { x: d, y: Math.round(p.y + p.h * (1 - e) / 2), w: r.width, h: Math.round(p.h * e) } : { x: d, y: n.y1 - o * e, w: r.width, h: a * e };
|
|
54
|
+
}), g = i && p !== null, $ = g && 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
|
+
}) : [], S = I(x, g ? [] : m, i), k = p ? I(p, g ? m : [], !0) : [], M = x.y + x.h + (p ? p.h : 0), z = i ? { x: x.x, y: M - E, w: x.w, h: E } : { x: x.x, y: x.y, w: x.w, h: M - x.y };
|
|
58
|
+
return { spec: n, horizontal: i, body: x, lip: p, bodyPieces: S, lipPieces: k, windows: m, sills: $, collider: z, depth: n.depth ?? M };
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
I as cutRects,
|
|
63
|
+
b as endExtension,
|
|
64
|
+
W as resolveWalls
|
|
65
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,77 +1,18 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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(
|
|
74
|
-
return this.config = { ...this.config, walls:
|
|
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
|
|
84
|
-
for (const
|
|
85
|
-
this.containers = [], (
|
|
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:
|
|
89
|
-
|
|
90
|
-
for (const
|
|
91
|
-
this.containers.push(this.drawWall(
|
|
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(
|
|
94
|
-
const { body:
|
|
95
|
-
for (const
|
|
96
|
-
for (const
|
|
97
|
-
const
|
|
98
|
-
for (const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
for (const
|
|
102
|
-
for (const
|
|
103
|
-
if (
|
|
104
|
-
for (const
|
|
105
|
-
return
|
|
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(
|
|
108
|
-
if (!
|
|
109
|
-
|
|
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
|
|
113
|
-
|
|
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(
|
|
116
|
-
const { collider:
|
|
117
|
-
this.scene.physics.add.existing(
|
|
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
|
|
121
|
-
constructor(
|
|
122
|
-
super(
|
|
123
|
-
return new
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
69
|
+
R as WallMap,
|
|
70
|
+
P as WallMapPlugin,
|
|
71
|
+
p as resolveWalls
|
|
131
72
|
};
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mertdogar/phaser-procedural-walls",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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": {
|
|
@@ -45,22 +53,38 @@
|
|
|
45
53
|
"publishConfig": {
|
|
46
54
|
"access": "public"
|
|
47
55
|
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"dev": "vite",
|
|
50
|
-
"build": "vite build && tsc -p tsconfig.lib.json",
|
|
51
|
-
"test": "vitest run",
|
|
52
|
-
"typecheck": "tsc --noEmit",
|
|
53
|
-
"lint": "oxlint src demo tests",
|
|
54
|
-
"prepublishOnly": "pnpm typecheck && pnpm lint && pnpm test && pnpm build"
|
|
55
|
-
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"phaser": "^4.0.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
61
|
+
"@types/react": "^19.3.0",
|
|
62
|
+
"@types/react-dom": "^19.3.0",
|
|
63
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
60
64
|
"oxlint": "^1.0.0",
|
|
61
65
|
"phaser": "^4.2.1",
|
|
66
|
+
"tailwindcss": "^4.3.3",
|
|
62
67
|
"typescript": "^5.6.0",
|
|
63
68
|
"vite": "^6.0.0",
|
|
64
69
|
"vitest": "^3.0.0"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"class-variance-authority": "^0.7.1",
|
|
73
|
+
"clsx": "^2.1.1",
|
|
74
|
+
"cn": "^0.3.0",
|
|
75
|
+
"lucide-react": "^1.47.0",
|
|
76
|
+
"radix-ui": "^1.6.7",
|
|
77
|
+
"react": "^19.3.0",
|
|
78
|
+
"react-dom": "^19.3.0",
|
|
79
|
+
"tailwind-merge": "^3.7.0"
|
|
80
|
+
},
|
|
81
|
+
"scripts": {
|
|
82
|
+
"dev": "vite",
|
|
83
|
+
"build": "vite build && tsc -p tsconfig.lib.json && vite build --mode editor",
|
|
84
|
+
"editor": "node bin/cli.mjs editor",
|
|
85
|
+
"test:cli": "node --test tests/cli.test.mjs",
|
|
86
|
+
"test": "vitest run",
|
|
87
|
+
"typecheck": "tsc --noEmit",
|
|
88
|
+
"lint": "oxlint src demo tests bin"
|
|
65
89
|
}
|
|
66
|
-
}
|
|
90
|
+
}
|