cubeforge 0.3.14 → 0.3.16
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/dist/index.d.ts +208 -11
- package/dist/index.js +1243 -293
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/Game.tsx
|
|
2
|
-
import { useEffect as
|
|
2
|
+
import { useEffect as useEffect4, useRef as useRef4, useState as useState2 } from "react";
|
|
3
3
|
|
|
4
4
|
// ../../packages/core/src/ecs/world.ts
|
|
5
5
|
var ECSWorld = class {
|
|
@@ -734,14 +734,95 @@ var ScriptSystem = class {
|
|
|
734
734
|
// ../../packages/core/src/tween.ts
|
|
735
735
|
var Ease = {
|
|
736
736
|
linear: (t) => t,
|
|
737
|
+
// Quad
|
|
737
738
|
easeInQuad: (t) => t * t,
|
|
738
739
|
easeOutQuad: (t) => t * (2 - t),
|
|
739
740
|
easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
|
|
741
|
+
// Cubic
|
|
742
|
+
easeInCubic: (t) => t * t * t,
|
|
743
|
+
easeOutCubic: (t) => {
|
|
744
|
+
const t1 = t - 1;
|
|
745
|
+
return t1 * t1 * t1 + 1;
|
|
746
|
+
},
|
|
747
|
+
easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
|
748
|
+
// Quart
|
|
749
|
+
easeInQuart: (t) => t * t * t * t,
|
|
750
|
+
easeOutQuart: (t) => {
|
|
751
|
+
const t1 = t - 1;
|
|
752
|
+
return 1 - t1 * t1 * t1 * t1;
|
|
753
|
+
},
|
|
754
|
+
easeInOutQuart: (t) => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (t - 1) * (t - 1) * (t - 1) * (t - 1),
|
|
755
|
+
// Quint
|
|
756
|
+
easeInQuint: (t) => t * t * t * t * t,
|
|
757
|
+
easeOutQuint: (t) => {
|
|
758
|
+
const t1 = t - 1;
|
|
759
|
+
return 1 + t1 * t1 * t1 * t1 * t1;
|
|
760
|
+
},
|
|
761
|
+
easeInOutQuint: (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (t - 1) * (t - 1) * (t - 1) * (t - 1) * (t - 1),
|
|
762
|
+
// Sine
|
|
763
|
+
easeInSine: (t) => 1 - Math.cos(t * Math.PI / 2),
|
|
764
|
+
easeOutSine: (t) => Math.sin(t * Math.PI / 2),
|
|
765
|
+
easeInOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2,
|
|
766
|
+
// Expo
|
|
767
|
+
easeInExpo: (t) => t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),
|
|
768
|
+
easeOutExpo: (t) => t === 1 ? 1 : 1 - Math.pow(2, -10 * t),
|
|
769
|
+
easeInOutExpo: (t) => {
|
|
770
|
+
if (t === 0) return 0;
|
|
771
|
+
if (t === 1) return 1;
|
|
772
|
+
return t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2;
|
|
773
|
+
},
|
|
774
|
+
// Circ
|
|
775
|
+
easeInCirc: (t) => 1 - Math.sqrt(1 - t * t),
|
|
776
|
+
easeOutCirc: (t) => Math.sqrt(1 - (t - 1) * (t - 1)),
|
|
777
|
+
easeInOutCirc: (t) => t < 0.5 ? (1 - Math.sqrt(1 - 4 * t * t)) / 2 : (Math.sqrt(1 - (-2 * t + 2) * (-2 * t + 2)) + 1) / 2,
|
|
778
|
+
// Back
|
|
779
|
+
easeInBack: (t) => {
|
|
780
|
+
const c1 = 1.70158;
|
|
781
|
+
const c3 = c1 + 1;
|
|
782
|
+
return c3 * t * t * t - c1 * t * t;
|
|
783
|
+
},
|
|
740
784
|
easeOutBack: (t) => {
|
|
741
785
|
const c1 = 1.70158;
|
|
742
786
|
const c3 = c1 + 1;
|
|
743
787
|
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
|
|
744
|
-
}
|
|
788
|
+
},
|
|
789
|
+
easeInOutBack: (t) => {
|
|
790
|
+
const c1 = 1.70158;
|
|
791
|
+
const c2 = c1 * 1.525;
|
|
792
|
+
return t < 0.5 ? 2 * t * (2 * t) * ((c2 + 1) * 2 * t - c2) / 2 : ((2 * t - 2) * (2 * t - 2) * ((c2 + 1) * (2 * t - 2) + c2) + 2) / 2;
|
|
793
|
+
},
|
|
794
|
+
// Elastic
|
|
795
|
+
easeInElastic: (t) => {
|
|
796
|
+
if (t === 0 || t === 1) return t;
|
|
797
|
+
return -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * (2 * Math.PI / 3));
|
|
798
|
+
},
|
|
799
|
+
easeOutElastic: (t) => {
|
|
800
|
+
if (t === 0 || t === 1) return t;
|
|
801
|
+
return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * (2 * Math.PI / 3)) + 1;
|
|
802
|
+
},
|
|
803
|
+
easeInOutElastic: (t) => {
|
|
804
|
+
if (t === 0 || t === 1) return t;
|
|
805
|
+
const c5 = 2 * Math.PI / 4.5;
|
|
806
|
+
return t < 0.5 ? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * c5)) / 2 : Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * c5) / 2 + 1;
|
|
807
|
+
},
|
|
808
|
+
// Bounce
|
|
809
|
+
easeOutBounce: (t) => {
|
|
810
|
+
const n1 = 7.5625;
|
|
811
|
+
const d1 = 2.75;
|
|
812
|
+
if (t < 1 / d1) return n1 * t * t;
|
|
813
|
+
if (t < 2 / d1) {
|
|
814
|
+
const t22 = t - 1.5 / d1;
|
|
815
|
+
return n1 * t22 * t22 + 0.75;
|
|
816
|
+
}
|
|
817
|
+
if (t < 2.5 / d1) {
|
|
818
|
+
const t22 = t - 2.25 / d1;
|
|
819
|
+
return n1 * t22 * t22 + 0.9375;
|
|
820
|
+
}
|
|
821
|
+
const t2 = t - 2.625 / d1;
|
|
822
|
+
return n1 * t2 * t2 + 0.984375;
|
|
823
|
+
},
|
|
824
|
+
easeInBounce: (t) => 1 - Ease.easeOutBounce(1 - t),
|
|
825
|
+
easeInOutBounce: (t) => t < 0.5 ? (1 - Ease.easeOutBounce(1 - 2 * t)) / 2 : (1 + Ease.easeOutBounce(2 * t - 1)) / 2
|
|
745
826
|
};
|
|
746
827
|
function tween(from, to, duration, ease = Ease.linear, onUpdate, onComplete) {
|
|
747
828
|
let elapsed = 0;
|
|
@@ -767,6 +848,87 @@ function tween(from, to, duration, ease = Ease.linear, onUpdate, onComplete) {
|
|
|
767
848
|
};
|
|
768
849
|
}
|
|
769
850
|
|
|
851
|
+
// ../../packages/core/src/tweenTimeline.ts
|
|
852
|
+
function createTimeline() {
|
|
853
|
+
const entries = [];
|
|
854
|
+
let running = false;
|
|
855
|
+
let currentTween = null;
|
|
856
|
+
let delayTimer = null;
|
|
857
|
+
let rafId = null;
|
|
858
|
+
let lastTime = 0;
|
|
859
|
+
function clearCurrent() {
|
|
860
|
+
if (currentTween) {
|
|
861
|
+
currentTween.stop();
|
|
862
|
+
currentTween = null;
|
|
863
|
+
}
|
|
864
|
+
if (delayTimer !== null) {
|
|
865
|
+
clearTimeout(delayTimer);
|
|
866
|
+
delayTimer = null;
|
|
867
|
+
}
|
|
868
|
+
if (rafId !== null) {
|
|
869
|
+
cancelAnimationFrame(rafId);
|
|
870
|
+
rafId = null;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
function tick(now) {
|
|
874
|
+
if (!running || !currentTween) return;
|
|
875
|
+
const dt = (now - lastTime) / 1e3;
|
|
876
|
+
lastTime = now;
|
|
877
|
+
currentTween.update(dt);
|
|
878
|
+
if (!currentTween.isComplete) {
|
|
879
|
+
rafId = requestAnimationFrame(tick);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
function playEntry(index) {
|
|
883
|
+
if (index >= entries.length) {
|
|
884
|
+
running = false;
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
const entry = entries[index];
|
|
888
|
+
const delay = entry.delay ?? 0;
|
|
889
|
+
const startTween = () => {
|
|
890
|
+
if (!running) return;
|
|
891
|
+
currentTween = tween(
|
|
892
|
+
entry.from,
|
|
893
|
+
entry.to,
|
|
894
|
+
entry.duration,
|
|
895
|
+
entry.ease ?? Ease.linear,
|
|
896
|
+
entry.onUpdate,
|
|
897
|
+
() => {
|
|
898
|
+
entry.onComplete?.();
|
|
899
|
+
playEntry(index + 1);
|
|
900
|
+
}
|
|
901
|
+
);
|
|
902
|
+
lastTime = performance.now();
|
|
903
|
+
rafId = requestAnimationFrame(tick);
|
|
904
|
+
};
|
|
905
|
+
if (delay > 0) {
|
|
906
|
+
delayTimer = setTimeout(startTween, delay * 1e3);
|
|
907
|
+
} else {
|
|
908
|
+
startTween();
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
const timeline = {
|
|
912
|
+
add(entry) {
|
|
913
|
+
entries.push(entry);
|
|
914
|
+
return timeline;
|
|
915
|
+
},
|
|
916
|
+
start() {
|
|
917
|
+
clearCurrent();
|
|
918
|
+
running = true;
|
|
919
|
+
playEntry(0);
|
|
920
|
+
},
|
|
921
|
+
stop() {
|
|
922
|
+
running = false;
|
|
923
|
+
clearCurrent();
|
|
924
|
+
},
|
|
925
|
+
isRunning() {
|
|
926
|
+
return running;
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
return timeline;
|
|
930
|
+
}
|
|
931
|
+
|
|
770
932
|
// ../../packages/core/src/timer.ts
|
|
771
933
|
function createTimer(duration, onComplete, autoStart = false) {
|
|
772
934
|
let _duration = duration;
|
|
@@ -831,6 +993,48 @@ function hotReloadPlugin(engine, oldPlugin, newPlugin, oldSystems) {
|
|
|
831
993
|
newPlugin.onInit?.(engine);
|
|
832
994
|
}
|
|
833
995
|
|
|
996
|
+
// ../../packages/core/src/tilemapMerge.ts
|
|
997
|
+
function mergeTileColliders(solidGrid, tileWidth, tileHeight, originX, originY) {
|
|
998
|
+
const rows = solidGrid.length;
|
|
999
|
+
if (rows === 0) return [];
|
|
1000
|
+
const cols = solidGrid[0].length;
|
|
1001
|
+
const visited = [];
|
|
1002
|
+
for (let r = 0; r < rows; r++) {
|
|
1003
|
+
visited[r] = new Array(cols).fill(false);
|
|
1004
|
+
}
|
|
1005
|
+
const rects = [];
|
|
1006
|
+
for (let row = 0; row < rows; row++) {
|
|
1007
|
+
for (let col = 0; col < cols; col++) {
|
|
1008
|
+
if (!solidGrid[row][col] || visited[row][col]) continue;
|
|
1009
|
+
let maxCol = col;
|
|
1010
|
+
while (maxCol + 1 < cols && solidGrid[row][maxCol + 1] && !visited[row][maxCol + 1]) {
|
|
1011
|
+
maxCol++;
|
|
1012
|
+
}
|
|
1013
|
+
let maxRow = row;
|
|
1014
|
+
outer:
|
|
1015
|
+
for (let r = row + 1; r < rows; r++) {
|
|
1016
|
+
for (let c = col; c <= maxCol; c++) {
|
|
1017
|
+
if (!solidGrid[r][c] || visited[r][c]) break outer;
|
|
1018
|
+
}
|
|
1019
|
+
maxRow = r;
|
|
1020
|
+
}
|
|
1021
|
+
for (let r = row; r <= maxRow; r++) {
|
|
1022
|
+
for (let c = col; c <= maxCol; c++) {
|
|
1023
|
+
visited[r][c] = true;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
const spanCols = maxCol - col + 1;
|
|
1027
|
+
const spanRows = maxRow - row + 1;
|
|
1028
|
+
const width = spanCols * tileWidth;
|
|
1029
|
+
const height = spanRows * tileHeight;
|
|
1030
|
+
const x = originX + col * tileWidth + width / 2;
|
|
1031
|
+
const y = originY + row * tileHeight + height / 2;
|
|
1032
|
+
rects.push({ x, y, width, height });
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
return rects;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
834
1038
|
// ../../packages/input/src/keyboard.ts
|
|
835
1039
|
var Keyboard = class {
|
|
836
1040
|
held = /* @__PURE__ */ new Set();
|
|
@@ -1156,13 +1360,36 @@ function createSprite(opts) {
|
|
|
1156
1360
|
zIndex: 0,
|
|
1157
1361
|
visible: true,
|
|
1158
1362
|
flipX: false,
|
|
1363
|
+
flipY: false,
|
|
1159
1364
|
anchorX: 0.5,
|
|
1160
1365
|
anchorY: 0.5,
|
|
1161
1366
|
frameIndex: 0,
|
|
1367
|
+
blendMode: "normal",
|
|
1368
|
+
layer: "default",
|
|
1162
1369
|
...opts
|
|
1163
1370
|
};
|
|
1164
1371
|
}
|
|
1165
1372
|
|
|
1373
|
+
// ../../packages/renderer/src/renderLayers.ts
|
|
1374
|
+
var defaultLayers = [
|
|
1375
|
+
{ name: "background", order: -100 },
|
|
1376
|
+
{ name: "default", order: 0 },
|
|
1377
|
+
{ name: "foreground", order: 100 },
|
|
1378
|
+
{ name: "ui", order: 200 }
|
|
1379
|
+
];
|
|
1380
|
+
function createRenderLayerManager(layers = defaultLayers) {
|
|
1381
|
+
const map = /* @__PURE__ */ new Map();
|
|
1382
|
+
for (const l of layers) map.set(l.name, l.order);
|
|
1383
|
+
return {
|
|
1384
|
+
addLayer(name, order) {
|
|
1385
|
+
map.set(name, order);
|
|
1386
|
+
},
|
|
1387
|
+
getOrder(name) {
|
|
1388
|
+
return map.get(name) ?? 0;
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1166
1393
|
// ../../packages/renderer/src/textureFilter.ts
|
|
1167
1394
|
var TextureFilter = {
|
|
1168
1395
|
/** Nearest-neighbor — sharp pixels, ideal for pixel art */
|
|
@@ -1269,8 +1496,9 @@ layout(location = 4) in float i_rot;
|
|
|
1269
1496
|
layout(location = 5) in vec2 i_anchor;
|
|
1270
1497
|
layout(location = 6) in vec2 i_offset;
|
|
1271
1498
|
layout(location = 7) in float i_flipX;
|
|
1272
|
-
layout(location = 8) in
|
|
1273
|
-
layout(location = 9) in vec4
|
|
1499
|
+
layout(location = 8) in float i_flipY;
|
|
1500
|
+
layout(location = 9) in vec4 i_color;
|
|
1501
|
+
layout(location = 10) in vec4 i_uvRect;
|
|
1274
1502
|
|
|
1275
1503
|
uniform vec2 u_camPos;
|
|
1276
1504
|
uniform float u_zoom;
|
|
@@ -1286,6 +1514,8 @@ void main() {
|
|
|
1286
1514
|
|
|
1287
1515
|
// Horizontal flip
|
|
1288
1516
|
if (i_flipX > 0.5) local.x = -local.x;
|
|
1517
|
+
// Vertical flip
|
|
1518
|
+
if (i_flipY > 0.5) local.y = -local.y;
|
|
1289
1519
|
|
|
1290
1520
|
// Rotate around local origin
|
|
1291
1521
|
float c = cos(i_rot);
|
|
@@ -1397,9 +1627,9 @@ function parseCSSColor(css) {
|
|
|
1397
1627
|
}
|
|
1398
1628
|
|
|
1399
1629
|
// ../../packages/renderer/src/webglRenderSystem.ts
|
|
1400
|
-
var FLOATS_PER_INSTANCE =
|
|
1401
|
-
var MAX_INSTANCES =
|
|
1402
|
-
var MAX_SPRITE_TEXTURES =
|
|
1630
|
+
var FLOATS_PER_INSTANCE = 19;
|
|
1631
|
+
var MAX_INSTANCES = 16384;
|
|
1632
|
+
var MAX_SPRITE_TEXTURES = 1024;
|
|
1403
1633
|
var MAX_TEXT_CACHE = 200;
|
|
1404
1634
|
function compileShader(gl, type, src) {
|
|
1405
1635
|
const shader = gl.createShader(type);
|
|
@@ -1531,8 +1761,9 @@ var RenderSystem = class {
|
|
|
1531
1761
|
addAttr(5, 2);
|
|
1532
1762
|
addAttr(6, 2);
|
|
1533
1763
|
addAttr(7, 1);
|
|
1534
|
-
addAttr(8,
|
|
1764
|
+
addAttr(8, 1);
|
|
1535
1765
|
addAttr(9, 4);
|
|
1766
|
+
addAttr(10, 4);
|
|
1536
1767
|
gl.bindVertexArray(null);
|
|
1537
1768
|
gl.useProgram(this.program);
|
|
1538
1769
|
this.uCamPos = gl.getUniformLocation(this.program, "u_camPos");
|
|
@@ -1604,6 +1835,8 @@ var RenderSystem = class {
|
|
|
1604
1835
|
textureCache = /* @__PURE__ */ new Map();
|
|
1605
1836
|
/** Insertion-order key list for LRU-style eviction. */
|
|
1606
1837
|
textureCacheKeys = [];
|
|
1838
|
+
// ── Render layer manager ────────────────────────────────────────────────
|
|
1839
|
+
layers = createRenderLayerManager();
|
|
1607
1840
|
// ── Texture sampling ────────────────────────────────────────────────────
|
|
1608
1841
|
_defaultSampling = DEFAULT_SAMPLING;
|
|
1609
1842
|
/** Set the global default texture sampling mode for all sprites that don't specify their own. */
|
|
@@ -1768,10 +2001,29 @@ var RenderSystem = class {
|
|
|
1768
2001
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, toGLMinFilter(gl, min));
|
|
1769
2002
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, toGLMagFilter(gl, mag));
|
|
1770
2003
|
}
|
|
2004
|
+
// ── Blend mode helper ────────────────────────────────────────────────────
|
|
2005
|
+
applyBlendMode(mode) {
|
|
2006
|
+
const { gl } = this;
|
|
2007
|
+
switch (mode) {
|
|
2008
|
+
case "additive":
|
|
2009
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
|
2010
|
+
break;
|
|
2011
|
+
case "multiply":
|
|
2012
|
+
gl.blendFunc(gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA);
|
|
2013
|
+
break;
|
|
2014
|
+
case "screen":
|
|
2015
|
+
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_COLOR);
|
|
2016
|
+
break;
|
|
2017
|
+
default:
|
|
2018
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
2019
|
+
break;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
1771
2022
|
// ── Instanced draw call ────────────────────────────────────────────────────
|
|
1772
|
-
flush(count, textureKey, sampling) {
|
|
2023
|
+
flush(count, textureKey, sampling, blendMode) {
|
|
1773
2024
|
if (count === 0) return;
|
|
1774
2025
|
const { gl } = this;
|
|
2026
|
+
if (blendMode && blendMode !== "normal") this.applyBlendMode(blendMode);
|
|
1775
2027
|
const isColor = textureKey.startsWith("__color__");
|
|
1776
2028
|
const tex = isColor ? this.whiteTexture : this.loadTexture(textureKey);
|
|
1777
2029
|
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
@@ -1781,6 +2033,7 @@ var RenderSystem = class {
|
|
|
1781
2033
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.instanceBuffer);
|
|
1782
2034
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.instanceData, 0, count * FLOATS_PER_INSTANCE);
|
|
1783
2035
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, count);
|
|
2036
|
+
if (blendMode && blendMode !== "normal") this.applyBlendMode("normal");
|
|
1784
2037
|
}
|
|
1785
2038
|
flushWithTex(count, tex, useTexture) {
|
|
1786
2039
|
if (count === 0) return;
|
|
@@ -1793,7 +2046,7 @@ var RenderSystem = class {
|
|
|
1793
2046
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, count);
|
|
1794
2047
|
}
|
|
1795
2048
|
// ── Write one sprite instance into instanceData ───────────────────────────
|
|
1796
|
-
writeInstance(base, x, y, w, h, rot, anchorX, anchorY, offsetX, offsetY, flipX, r, g, b, a, u, v, uw, vh) {
|
|
2049
|
+
writeInstance(base, x, y, w, h, rot, anchorX, anchorY, offsetX, offsetY, flipX, flipY, r, g, b, a, u, v, uw, vh) {
|
|
1797
2050
|
const d = this.instanceData;
|
|
1798
2051
|
d[base + 0] = x;
|
|
1799
2052
|
d[base + 1] = y;
|
|
@@ -1805,14 +2058,15 @@ var RenderSystem = class {
|
|
|
1805
2058
|
d[base + 7] = offsetX;
|
|
1806
2059
|
d[base + 8] = offsetY;
|
|
1807
2060
|
d[base + 9] = flipX ? 1 : 0;
|
|
1808
|
-
d[base + 10] =
|
|
1809
|
-
d[base + 11] =
|
|
1810
|
-
d[base + 12] =
|
|
1811
|
-
d[base + 13] =
|
|
1812
|
-
d[base + 14] =
|
|
1813
|
-
d[base + 15] =
|
|
1814
|
-
d[base + 16] =
|
|
1815
|
-
d[base + 17] =
|
|
2061
|
+
d[base + 10] = flipY ? 1 : 0;
|
|
2062
|
+
d[base + 11] = r;
|
|
2063
|
+
d[base + 12] = g;
|
|
2064
|
+
d[base + 13] = b;
|
|
2065
|
+
d[base + 14] = a;
|
|
2066
|
+
d[base + 15] = u;
|
|
2067
|
+
d[base + 16] = v;
|
|
2068
|
+
d[base + 17] = uw;
|
|
2069
|
+
d[base + 18] = vh;
|
|
1816
2070
|
}
|
|
1817
2071
|
// ── Main update loop ───────────────────────────────────────────────────────
|
|
1818
2072
|
update(world, dt) {
|
|
@@ -1872,9 +2126,47 @@ var RenderSystem = class {
|
|
|
1872
2126
|
camY = cam.y;
|
|
1873
2127
|
zoom = cam.zoom;
|
|
1874
2128
|
}
|
|
2129
|
+
for (const id of world.query("Animator", "AnimationState")) {
|
|
2130
|
+
const animator = world.getComponent(id, "Animator");
|
|
2131
|
+
const anim = world.getComponent(id, "AnimationState");
|
|
2132
|
+
if (!animator.playing) continue;
|
|
2133
|
+
if (!animator.states[animator.currentState]) {
|
|
2134
|
+
animator.currentState = animator.initialState;
|
|
2135
|
+
animator._entered = false;
|
|
2136
|
+
}
|
|
2137
|
+
const stateDef = animator.states[animator.currentState];
|
|
2138
|
+
if (!stateDef) continue;
|
|
2139
|
+
if (!animator._entered) {
|
|
2140
|
+
anim.currentClip = stateDef.clip;
|
|
2141
|
+
animator._entered = true;
|
|
2142
|
+
stateDef.onEnter?.();
|
|
2143
|
+
}
|
|
2144
|
+
if (stateDef.transitions && stateDef.transitions.length > 0) {
|
|
2145
|
+
const sorted = [...stateDef.transitions].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
2146
|
+
for (const trans of sorted) {
|
|
2147
|
+
if (trans.exitTime != null && anim.frames.length > 0) {
|
|
2148
|
+
const progress = anim.currentIndex / anim.frames.length;
|
|
2149
|
+
if (progress < trans.exitTime) continue;
|
|
2150
|
+
}
|
|
2151
|
+
if (evaluateConditions(trans.when, animator.params)) {
|
|
2152
|
+
stateDef.onExit?.();
|
|
2153
|
+
animator.currentState = trans.to;
|
|
2154
|
+
animator._entered = false;
|
|
2155
|
+
break;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
1875
2160
|
for (const id of world.query("AnimationState", "Sprite")) {
|
|
1876
2161
|
const anim = world.getComponent(id, "AnimationState");
|
|
1877
2162
|
const sprite = world.getComponent(id, "Sprite");
|
|
2163
|
+
if (anim.clips && anim.currentClip && anim._resolvedClip !== anim.currentClip) {
|
|
2164
|
+
const clip = anim.clips[anim.currentClip];
|
|
2165
|
+
if (clip) {
|
|
2166
|
+
resolveClip(anim, clip);
|
|
2167
|
+
anim._resolvedClip = anim.currentClip;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
1878
2170
|
if (!anim.playing || anim.frames.length === 0) continue;
|
|
1879
2171
|
anim.timer += dt;
|
|
1880
2172
|
const frameDuration = 1 / anim.fps;
|
|
@@ -1882,8 +2174,24 @@ var RenderSystem = class {
|
|
|
1882
2174
|
anim.timer -= frameDuration;
|
|
1883
2175
|
anim.currentIndex++;
|
|
1884
2176
|
if (anim.currentIndex >= anim.frames.length) {
|
|
1885
|
-
|
|
2177
|
+
if (anim.loop) {
|
|
2178
|
+
anim.currentIndex = 0;
|
|
2179
|
+
} else {
|
|
2180
|
+
anim.currentIndex = anim.frames.length - 1;
|
|
2181
|
+
anim.playing = false;
|
|
2182
|
+
if (anim.onComplete && !anim._completed) {
|
|
2183
|
+
anim._completed = true;
|
|
2184
|
+
anim.onComplete();
|
|
2185
|
+
}
|
|
2186
|
+
if (anim.clips && anim.currentClip) {
|
|
2187
|
+
const currentClipDef = anim.clips[anim.currentClip];
|
|
2188
|
+
if (currentClipDef?.next && anim.clips[currentClipDef.next]) {
|
|
2189
|
+
anim.currentClip = currentClipDef.next;
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
1886
2193
|
}
|
|
2194
|
+
anim.frameEvents?.[anim.currentIndex]?.();
|
|
1887
2195
|
}
|
|
1888
2196
|
sprite.frameIndex = anim.frames[anim.currentIndex];
|
|
1889
2197
|
}
|
|
@@ -1947,6 +2255,8 @@ var RenderSystem = class {
|
|
|
1947
2255
|
renderables.sort((a, b) => {
|
|
1948
2256
|
const sa = world.getComponent(a, "Sprite");
|
|
1949
2257
|
const sb = world.getComponent(b, "Sprite");
|
|
2258
|
+
const ld = this.layers.getOrder(sa.layer) - this.layers.getOrder(sb.layer);
|
|
2259
|
+
if (ld !== 0) return ld;
|
|
1950
2260
|
const zd = sa.zIndex - sb.zIndex;
|
|
1951
2261
|
if (zd !== 0) return zd;
|
|
1952
2262
|
const ka = getTextureKey(sa), kb = getTextureKey(sb);
|
|
@@ -1955,9 +2265,10 @@ var RenderSystem = class {
|
|
|
1955
2265
|
let batchCount = 0;
|
|
1956
2266
|
let batchKey = "";
|
|
1957
2267
|
let batchSampling;
|
|
2268
|
+
let batchBlendMode = "normal";
|
|
1958
2269
|
for (let i = 0; i <= renderables.length; i++) {
|
|
1959
2270
|
if (i === renderables.length) {
|
|
1960
|
-
this.flush(batchCount, batchKey, batchSampling);
|
|
2271
|
+
this.flush(batchCount, batchKey, batchSampling, batchBlendMode);
|
|
1961
2272
|
break;
|
|
1962
2273
|
}
|
|
1963
2274
|
const id = renderables[i];
|
|
@@ -2006,12 +2317,14 @@ var RenderSystem = class {
|
|
|
2006
2317
|
sprite.image = img;
|
|
2007
2318
|
}
|
|
2008
2319
|
const key = getTextureKey(sprite);
|
|
2009
|
-
|
|
2010
|
-
|
|
2320
|
+
const spriteBlend = sprite.blendMode ?? "normal";
|
|
2321
|
+
if ((key !== batchKey || spriteBlend !== batchBlendMode) && batchCount > 0 || batchCount >= MAX_INSTANCES) {
|
|
2322
|
+
this.flush(batchCount, batchKey, batchSampling, batchBlendMode);
|
|
2011
2323
|
batchCount = 0;
|
|
2012
2324
|
}
|
|
2013
2325
|
batchKey = key;
|
|
2014
2326
|
batchSampling = sprite.sampling;
|
|
2327
|
+
batchBlendMode = spriteBlend;
|
|
2015
2328
|
const ss = world.getComponent(id, "SquashStretch");
|
|
2016
2329
|
const scaleXMod = ss ? ss.currentScaleX : 1;
|
|
2017
2330
|
const scaleYMod = ss ? ss.currentScaleY : 1;
|
|
@@ -2030,6 +2343,7 @@ var RenderSystem = class {
|
|
|
2030
2343
|
sprite.offsetX,
|
|
2031
2344
|
sprite.offsetY,
|
|
2032
2345
|
sprite.flipX,
|
|
2346
|
+
sprite.flipY ?? false,
|
|
2033
2347
|
r,
|
|
2034
2348
|
g,
|
|
2035
2349
|
b,
|
|
@@ -2053,10 +2367,11 @@ var RenderSystem = class {
|
|
|
2053
2367
|
if (!text.visible) continue;
|
|
2054
2368
|
const entry = this.getOrCreateTextTexture(text);
|
|
2055
2369
|
if (!entry) continue;
|
|
2056
|
-
this.flush(batchCount, batchKey, batchSampling);
|
|
2370
|
+
this.flush(batchCount, batchKey, batchSampling, batchBlendMode);
|
|
2057
2371
|
batchCount = 0;
|
|
2058
2372
|
batchKey = "";
|
|
2059
2373
|
batchSampling = void 0;
|
|
2374
|
+
batchBlendMode = "normal";
|
|
2060
2375
|
this.writeInstance(
|
|
2061
2376
|
0,
|
|
2062
2377
|
transform.x + text.offsetX,
|
|
@@ -2070,6 +2385,9 @@ var RenderSystem = class {
|
|
|
2070
2385
|
0,
|
|
2071
2386
|
0,
|
|
2072
2387
|
false,
|
|
2388
|
+
// flipX
|
|
2389
|
+
false,
|
|
2390
|
+
// flipY
|
|
2073
2391
|
1,
|
|
2074
2392
|
1,
|
|
2075
2393
|
1,
|
|
@@ -2093,15 +2411,33 @@ var RenderSystem = class {
|
|
|
2093
2411
|
return p.life > 0;
|
|
2094
2412
|
});
|
|
2095
2413
|
if (pool.active && pool.particles.length < pool.maxParticles) {
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2414
|
+
let spawnCount;
|
|
2415
|
+
if (pool.burstCount != null && pool.burstCount > 0) {
|
|
2416
|
+
spawnCount = pool.burstCount;
|
|
2417
|
+
pool.active = false;
|
|
2418
|
+
} else {
|
|
2419
|
+
pool.timer += dt;
|
|
2420
|
+
spawnCount = Math.floor(pool.timer * pool.rate);
|
|
2421
|
+
pool.timer -= spawnCount / pool.rate;
|
|
2422
|
+
}
|
|
2099
2423
|
for (let i = 0; i < spawnCount && pool.particles.length < pool.maxParticles; i++) {
|
|
2100
2424
|
const angle = pool.angle + (world.rng() - 0.5) * pool.spread;
|
|
2101
2425
|
const speed = pool.speed * (0.5 + world.rng() * 0.5);
|
|
2426
|
+
let ox = 0;
|
|
2427
|
+
let oy = 0;
|
|
2428
|
+
const shape = pool.emitShape ?? "point";
|
|
2429
|
+
if (shape === "circle") {
|
|
2430
|
+
const r = (pool.emitRadius ?? 0) * Math.sqrt(world.rng());
|
|
2431
|
+
const a = world.rng() * Math.PI * 2;
|
|
2432
|
+
ox = Math.cos(a) * r;
|
|
2433
|
+
oy = Math.sin(a) * r;
|
|
2434
|
+
} else if (shape === "box") {
|
|
2435
|
+
ox = (world.rng() - 0.5) * (pool.emitWidth ?? 0);
|
|
2436
|
+
oy = (world.rng() - 0.5) * (pool.emitHeight ?? 0);
|
|
2437
|
+
}
|
|
2102
2438
|
pool.particles.push({
|
|
2103
|
-
x: t.x,
|
|
2104
|
-
y: t.y,
|
|
2439
|
+
x: t.x + ox,
|
|
2440
|
+
y: t.y + oy,
|
|
2105
2441
|
vx: Math.cos(angle) * speed,
|
|
2106
2442
|
vy: Math.sin(angle) * speed,
|
|
2107
2443
|
life: pool.particleLife,
|
|
@@ -2133,6 +2469,7 @@ var RenderSystem = class {
|
|
|
2133
2469
|
0,
|
|
2134
2470
|
0,
|
|
2135
2471
|
false,
|
|
2472
|
+
false,
|
|
2136
2473
|
r,
|
|
2137
2474
|
g,
|
|
2138
2475
|
b,
|
|
@@ -2173,6 +2510,7 @@ var RenderSystem = class {
|
|
|
2173
2510
|
0,
|
|
2174
2511
|
0,
|
|
2175
2512
|
false,
|
|
2513
|
+
false,
|
|
2176
2514
|
tr,
|
|
2177
2515
|
tg,
|
|
2178
2516
|
tb,
|
|
@@ -2210,6 +2548,7 @@ var RenderSystem = class {
|
|
|
2210
2548
|
0,
|
|
2211
2549
|
0,
|
|
2212
2550
|
false,
|
|
2551
|
+
false,
|
|
2213
2552
|
walkable ? 0 : 1,
|
|
2214
2553
|
walkable ? 1 : 0,
|
|
2215
2554
|
0,
|
|
@@ -2243,6 +2582,7 @@ var RenderSystem = class {
|
|
|
2243
2582
|
0,
|
|
2244
2583
|
0,
|
|
2245
2584
|
false,
|
|
2585
|
+
false,
|
|
2246
2586
|
1,
|
|
2247
2587
|
0.3,
|
|
2248
2588
|
0.3,
|
|
@@ -2266,6 +2606,110 @@ var RenderSystem = class {
|
|
|
2266
2606
|
this.lastTimestamp = now;
|
|
2267
2607
|
}
|
|
2268
2608
|
};
|
|
2609
|
+
function resolveClip(anim, clip) {
|
|
2610
|
+
anim.frames = clip.frames;
|
|
2611
|
+
anim.fps = clip.fps ?? 12;
|
|
2612
|
+
anim.loop = clip.loop ?? true;
|
|
2613
|
+
anim.onComplete = clip.onComplete;
|
|
2614
|
+
anim.frameEvents = clip.frameEvents;
|
|
2615
|
+
anim.currentIndex = 0;
|
|
2616
|
+
anim.timer = 0;
|
|
2617
|
+
anim._completed = false;
|
|
2618
|
+
anim.playing = true;
|
|
2619
|
+
}
|
|
2620
|
+
function evaluateConditions(conditions, params) {
|
|
2621
|
+
for (const cond of conditions) {
|
|
2622
|
+
const val = params[cond.param];
|
|
2623
|
+
if (val === void 0) return false;
|
|
2624
|
+
switch (cond.op) {
|
|
2625
|
+
case "==":
|
|
2626
|
+
if (val !== cond.value) return false;
|
|
2627
|
+
break;
|
|
2628
|
+
case "!=":
|
|
2629
|
+
if (val === cond.value) return false;
|
|
2630
|
+
break;
|
|
2631
|
+
case ">":
|
|
2632
|
+
if (val <= cond.value) return false;
|
|
2633
|
+
break;
|
|
2634
|
+
case ">=":
|
|
2635
|
+
if (val < cond.value) return false;
|
|
2636
|
+
break;
|
|
2637
|
+
case "<":
|
|
2638
|
+
if (val >= cond.value) return false;
|
|
2639
|
+
break;
|
|
2640
|
+
case "<=":
|
|
2641
|
+
if (val > cond.value) return false;
|
|
2642
|
+
break;
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
return true;
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
// ../../packages/renderer/src/postProcess.ts
|
|
2649
|
+
function createPostProcessStack() {
|
|
2650
|
+
const effects = [];
|
|
2651
|
+
return {
|
|
2652
|
+
add(effect) {
|
|
2653
|
+
if (!effects.includes(effect)) {
|
|
2654
|
+
effects.push(effect);
|
|
2655
|
+
}
|
|
2656
|
+
},
|
|
2657
|
+
remove(effect) {
|
|
2658
|
+
const idx = effects.indexOf(effect);
|
|
2659
|
+
if (idx !== -1) effects.splice(idx, 1);
|
|
2660
|
+
},
|
|
2661
|
+
apply(ctx, width, height, dt) {
|
|
2662
|
+
for (const effect of effects) {
|
|
2663
|
+
ctx.save();
|
|
2664
|
+
effect(ctx, width, height, dt);
|
|
2665
|
+
ctx.restore();
|
|
2666
|
+
}
|
|
2667
|
+
},
|
|
2668
|
+
clear() {
|
|
2669
|
+
effects.length = 0;
|
|
2670
|
+
}
|
|
2671
|
+
};
|
|
2672
|
+
}
|
|
2673
|
+
function vignetteEffect(intensity = 0.4) {
|
|
2674
|
+
return (ctx, width, height) => {
|
|
2675
|
+
const cx = width / 2;
|
|
2676
|
+
const cy = height / 2;
|
|
2677
|
+
const radius = Math.sqrt(cx * cx + cy * cy);
|
|
2678
|
+
const gradient = ctx.createRadialGradient(cx, cy, radius * 0.3, cx, cy, radius);
|
|
2679
|
+
gradient.addColorStop(0, "rgba(0,0,0,0)");
|
|
2680
|
+
gradient.addColorStop(1, `rgba(0,0,0,${intensity})`);
|
|
2681
|
+
ctx.fillStyle = gradient;
|
|
2682
|
+
ctx.fillRect(0, 0, width, height);
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
function scanlineEffect(gap = 3, opacity = 0.15) {
|
|
2686
|
+
return (ctx, width, height) => {
|
|
2687
|
+
ctx.fillStyle = `rgba(0,0,0,${opacity})`;
|
|
2688
|
+
for (let y = 0; y < height; y += gap) {
|
|
2689
|
+
ctx.fillRect(0, y, width, 1);
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
}
|
|
2693
|
+
function chromaticAberrationEffect(offset = 2) {
|
|
2694
|
+
return (ctx, width, height) => {
|
|
2695
|
+
if (width === 0 || height === 0) return;
|
|
2696
|
+
const imageData = ctx.getImageData(0, 0, width, height);
|
|
2697
|
+
const { data } = imageData;
|
|
2698
|
+
const copy = new Uint8ClampedArray(data);
|
|
2699
|
+
for (let y = 0; y < height; y++) {
|
|
2700
|
+
for (let x = 0; x < width; x++) {
|
|
2701
|
+
const i = (y * width + x) * 4;
|
|
2702
|
+
const srcR = Math.min(x + offset, width - 1);
|
|
2703
|
+
const iR = (y * width + srcR) * 4;
|
|
2704
|
+
data[i] = copy[iR];
|
|
2705
|
+
const srcB = Math.max(x - offset, 0);
|
|
2706
|
+
const iB = (y * width + srcB) * 4;
|
|
2707
|
+
data[i + 2] = copy[iB + 2];
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
ctx.putImageData(imageData, 0, 0);
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2269
2713
|
|
|
2270
2714
|
// ../../packages/renderer/src/canvas2d.ts
|
|
2271
2715
|
var Canvas2DRenderer = class {
|
|
@@ -2310,6 +2754,9 @@ function createRigidBody(opts) {
|
|
|
2310
2754
|
isKinematic: false,
|
|
2311
2755
|
dropThrough: 0,
|
|
2312
2756
|
ccd: false,
|
|
2757
|
+
angularVelocity: 0,
|
|
2758
|
+
angularDamping: 0,
|
|
2759
|
+
linearDamping: 0,
|
|
2313
2760
|
...opts
|
|
2314
2761
|
};
|
|
2315
2762
|
}
|
|
@@ -2644,6 +3091,15 @@ var PhysicsSystem = class {
|
|
|
2644
3091
|
if (!rb.lockY) rb.vy += this.gravity * rb.gravityScale * dt;
|
|
2645
3092
|
if (rb.lockX) rb.vx = 0;
|
|
2646
3093
|
if (rb.lockY) rb.vy = 0;
|
|
3094
|
+
if (rb.linearDamping > 0) {
|
|
3095
|
+
rb.vx *= 1 - rb.linearDamping;
|
|
3096
|
+
rb.vy *= 1 - rb.linearDamping;
|
|
3097
|
+
}
|
|
3098
|
+
if (rb.angularVelocity !== 0) {
|
|
3099
|
+
const transform = world.getComponent(id, "Transform");
|
|
3100
|
+
transform.rotation += rb.angularVelocity * dt;
|
|
3101
|
+
if (rb.angularDamping > 0) rb.angularVelocity *= 1 - rb.angularDamping;
|
|
3102
|
+
}
|
|
2647
3103
|
if (rb.dropThrough > 0) rb.dropThrough--;
|
|
2648
3104
|
}
|
|
2649
3105
|
const ccdPrev = /* @__PURE__ */ new Map();
|
|
@@ -2662,6 +3118,15 @@ var PhysicsSystem = class {
|
|
|
2662
3118
|
if (!rb.lockY) rb.vy += this.gravity * rb.gravityScale * dt;
|
|
2663
3119
|
if (rb.lockX) rb.vx = 0;
|
|
2664
3120
|
if (rb.lockY) rb.vy = 0;
|
|
3121
|
+
if (rb.linearDamping > 0) {
|
|
3122
|
+
rb.vx *= 1 - rb.linearDamping;
|
|
3123
|
+
rb.vy *= 1 - rb.linearDamping;
|
|
3124
|
+
}
|
|
3125
|
+
if (rb.angularVelocity !== 0) {
|
|
3126
|
+
const transform = world.getComponent(id, "Transform");
|
|
3127
|
+
transform.rotation += rb.angularVelocity * dt;
|
|
3128
|
+
if (rb.angularDamping > 0) rb.angularVelocity *= 1 - rb.angularDamping;
|
|
3129
|
+
}
|
|
2665
3130
|
if (rb.dropThrough > 0) rb.dropThrough--;
|
|
2666
3131
|
}
|
|
2667
3132
|
for (const id of dynamics) {
|
|
@@ -3543,10 +4008,48 @@ function useCircleStay(handler, opts) {
|
|
|
3543
4008
|
useContactEvent("circleStay", handler, opts);
|
|
3544
4009
|
}
|
|
3545
4010
|
|
|
4011
|
+
// ../context/src/useCollidingWith.ts
|
|
4012
|
+
import { useContext as useContext2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
4013
|
+
function useCollidingWith() {
|
|
4014
|
+
const engine = useContext2(EngineContext);
|
|
4015
|
+
const entityId = useContext2(EntityContext);
|
|
4016
|
+
if (!engine) throw new Error("useCollidingWith hook must be used inside <Game>");
|
|
4017
|
+
if (entityId === null) throw new Error("useCollidingWith hook must be used inside <Entity>");
|
|
4018
|
+
const setRef = useRef2(/* @__PURE__ */ new Set());
|
|
4019
|
+
useEffect2(() => {
|
|
4020
|
+
const set = setRef.current;
|
|
4021
|
+
function handleEnter({ a, b }) {
|
|
4022
|
+
const isA = a === entityId;
|
|
4023
|
+
const isB = b === entityId;
|
|
4024
|
+
if (!isA && !isB) return;
|
|
4025
|
+
set.add(isA ? b : a);
|
|
4026
|
+
}
|
|
4027
|
+
function handleExit({ a, b }) {
|
|
4028
|
+
const isA = a === entityId;
|
|
4029
|
+
const isB = b === entityId;
|
|
4030
|
+
if (!isA && !isB) return;
|
|
4031
|
+
set.delete(isA ? b : a);
|
|
4032
|
+
}
|
|
4033
|
+
const unsubs = [
|
|
4034
|
+
engine.events.on("collisionEnter", handleEnter),
|
|
4035
|
+
engine.events.on("collisionExit", handleExit),
|
|
4036
|
+
engine.events.on("triggerEnter", handleEnter),
|
|
4037
|
+
engine.events.on("triggerExit", handleExit),
|
|
4038
|
+
engine.events.on("circleEnter", handleEnter),
|
|
4039
|
+
engine.events.on("circleExit", handleExit)
|
|
4040
|
+
];
|
|
4041
|
+
return () => {
|
|
4042
|
+
unsubs.forEach((unsub) => unsub());
|
|
4043
|
+
set.clear();
|
|
4044
|
+
};
|
|
4045
|
+
}, [engine.events, entityId]);
|
|
4046
|
+
return setRef.current;
|
|
4047
|
+
}
|
|
4048
|
+
|
|
3546
4049
|
// ../devtools/src/DevTools.tsx
|
|
3547
4050
|
import React from "react";
|
|
3548
4051
|
import { createPortal } from "react-dom";
|
|
3549
|
-
import { useState, useEffect as
|
|
4052
|
+
import { useState, useEffect as useEffect3, useCallback, useRef as useRef3 } from "react";
|
|
3550
4053
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3551
4054
|
var MAX_DEVTOOLS_FRAMES = 600;
|
|
3552
4055
|
var C = {
|
|
@@ -3710,8 +4213,8 @@ function DevToolsOverlay({ handle, loop, ecs, engine }) {
|
|
|
3710
4213
|
const [contactLog, setContactLog] = useState([]);
|
|
3711
4214
|
const [showNavGrid, setShowNavGrid] = useState(false);
|
|
3712
4215
|
const [showContactFlash, setShowContactFlash] = useState(false);
|
|
3713
|
-
const frameRef =
|
|
3714
|
-
|
|
4216
|
+
const frameRef = useRef3(0);
|
|
4217
|
+
useEffect3(() => {
|
|
3715
4218
|
handle.onFrame = () => {
|
|
3716
4219
|
frameRef.current++;
|
|
3717
4220
|
if (!paused) {
|
|
@@ -3723,7 +4226,7 @@ function DevToolsOverlay({ handle, loop, ecs, engine }) {
|
|
|
3723
4226
|
handle.onFrame = void 0;
|
|
3724
4227
|
};
|
|
3725
4228
|
}, [handle, paused]);
|
|
3726
|
-
|
|
4229
|
+
useEffect3(() => {
|
|
3727
4230
|
if (!engine) return;
|
|
3728
4231
|
const events = engine.events;
|
|
3729
4232
|
const types = ["triggerEnter", "triggerExit", "collisionEnter", "collisionExit", "circleEnter", "circleExit"];
|
|
@@ -4234,13 +4737,13 @@ function Game({
|
|
|
4234
4737
|
className,
|
|
4235
4738
|
children
|
|
4236
4739
|
}) {
|
|
4237
|
-
const canvasRef =
|
|
4238
|
-
const debugCanvasRef =
|
|
4239
|
-
const wrapperRef =
|
|
4740
|
+
const canvasRef = useRef4(null);
|
|
4741
|
+
const debugCanvasRef = useRef4(null);
|
|
4742
|
+
const wrapperRef = useRef4(null);
|
|
4240
4743
|
const [engine, setEngine] = useState2(null);
|
|
4241
4744
|
const [assetsReady, setAssetsReady] = useState2(asyncAssets);
|
|
4242
|
-
const devtoolsHandle =
|
|
4243
|
-
|
|
4745
|
+
const devtoolsHandle = useRef4({ buffer: [] });
|
|
4746
|
+
useEffect4(() => {
|
|
4244
4747
|
const canvas = canvasRef.current;
|
|
4245
4748
|
const ecs = new ECSWorld();
|
|
4246
4749
|
if (deterministic) ecs.setDeterministicSeed(seed);
|
|
@@ -4283,6 +4786,7 @@ function Game({
|
|
|
4283
4786
|
handle.onFrame?.();
|
|
4284
4787
|
}
|
|
4285
4788
|
}, deterministic ? { fixedDt: 1 / 60 } : void 0);
|
|
4789
|
+
const postProcessStack = createPostProcessStack();
|
|
4286
4790
|
const state = {
|
|
4287
4791
|
ecs,
|
|
4288
4792
|
input,
|
|
@@ -4293,7 +4797,8 @@ function Game({
|
|
|
4293
4797
|
loop,
|
|
4294
4798
|
canvas,
|
|
4295
4799
|
entityIds,
|
|
4296
|
-
systemTimings
|
|
4800
|
+
systemTimings,
|
|
4801
|
+
postProcessStack
|
|
4297
4802
|
};
|
|
4298
4803
|
setEngine(state);
|
|
4299
4804
|
if (plugins) {
|
|
@@ -4355,7 +4860,7 @@ function Game({
|
|
|
4355
4860
|
}
|
|
4356
4861
|
};
|
|
4357
4862
|
}, []);
|
|
4358
|
-
|
|
4863
|
+
useEffect4(() => {
|
|
4359
4864
|
if (!engine) return;
|
|
4360
4865
|
let cancelled = false;
|
|
4361
4866
|
if (asyncAssets) {
|
|
@@ -4373,13 +4878,13 @@ function Game({
|
|
|
4373
4878
|
cancelled = true;
|
|
4374
4879
|
};
|
|
4375
4880
|
}, [engine]);
|
|
4376
|
-
|
|
4881
|
+
useEffect4(() => {
|
|
4377
4882
|
if (!engine) return;
|
|
4378
4883
|
const canvas = engine.canvas;
|
|
4379
4884
|
if (canvas.width !== width) canvas.width = width;
|
|
4380
4885
|
if (canvas.height !== height) canvas.height = height;
|
|
4381
4886
|
}, [width, height, engine]);
|
|
4382
|
-
|
|
4887
|
+
useEffect4(() => {
|
|
4383
4888
|
engine?.physics.setGravity(gravity);
|
|
4384
4889
|
}, [gravity, engine]);
|
|
4385
4890
|
const canvasStyle = {
|
|
@@ -4460,15 +4965,15 @@ function Game({
|
|
|
4460
4965
|
}
|
|
4461
4966
|
|
|
4462
4967
|
// src/components/World.tsx
|
|
4463
|
-
import { useEffect as
|
|
4968
|
+
import { useEffect as useEffect5, useContext as useContext3 } from "react";
|
|
4464
4969
|
import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
|
|
4465
4970
|
function World({ gravity, background = "#1a1a2e", children }) {
|
|
4466
|
-
const engine =
|
|
4467
|
-
|
|
4971
|
+
const engine = useContext3(EngineContext);
|
|
4972
|
+
useEffect5(() => {
|
|
4468
4973
|
if (!engine) return;
|
|
4469
4974
|
if (gravity !== void 0) engine.physics.setGravity(gravity);
|
|
4470
4975
|
}, [gravity, engine]);
|
|
4471
|
-
|
|
4976
|
+
useEffect5(() => {
|
|
4472
4977
|
if (!engine) return;
|
|
4473
4978
|
const camId = engine.ecs.queryOne("Camera2D");
|
|
4474
4979
|
if (camId !== void 0) {
|
|
@@ -4482,12 +4987,17 @@ function World({ gravity, background = "#1a1a2e", children }) {
|
|
|
4482
4987
|
}
|
|
4483
4988
|
|
|
4484
4989
|
// src/components/Entity.tsx
|
|
4485
|
-
import { useEffect as
|
|
4990
|
+
import { useEffect as useEffect6, useContext as useContext4, useState as useState3 } from "react";
|
|
4486
4991
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
4487
4992
|
function Entity({ id, tags = [], children }) {
|
|
4488
|
-
const engine =
|
|
4993
|
+
const engine = useContext4(EngineContext);
|
|
4489
4994
|
const [entityId, setEntityId] = useState3(null);
|
|
4490
|
-
|
|
4995
|
+
if (process.env.NODE_ENV !== "production") {
|
|
4996
|
+
if (!engine) {
|
|
4997
|
+
console.warn("[Cubeforge] <Entity> must be inside a <World>. No EngineContext found.");
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
useEffect6(() => {
|
|
4491
5001
|
const eid = engine.ecs.createEntity();
|
|
4492
5002
|
if (id) {
|
|
4493
5003
|
if (engine.entityIds.has(id)) {
|
|
@@ -4507,15 +5017,15 @@ function Entity({ id, tags = [], children }) {
|
|
|
4507
5017
|
}
|
|
4508
5018
|
|
|
4509
5019
|
// src/components/Transform.tsx
|
|
4510
|
-
import { useEffect as
|
|
5020
|
+
import { useEffect as useEffect7, useContext as useContext5 } from "react";
|
|
4511
5021
|
function Transform({ x = 0, y = 0, rotation = 0, scaleX = 1, scaleY = 1 }) {
|
|
4512
|
-
const engine =
|
|
4513
|
-
const entityId =
|
|
4514
|
-
|
|
5022
|
+
const engine = useContext5(EngineContext);
|
|
5023
|
+
const entityId = useContext5(EntityContext);
|
|
5024
|
+
useEffect7(() => {
|
|
4515
5025
|
engine.ecs.addComponent(entityId, createTransform(x, y, rotation, scaleX, scaleY));
|
|
4516
5026
|
return () => engine.ecs.removeComponent(entityId, "Transform");
|
|
4517
5027
|
}, []);
|
|
4518
|
-
|
|
5028
|
+
useEffect7(() => {
|
|
4519
5029
|
const comp = engine.ecs.getComponent(entityId, "Transform");
|
|
4520
5030
|
if (comp) {
|
|
4521
5031
|
comp.x = x;
|
|
@@ -4529,7 +5039,7 @@ function Transform({ x = 0, y = 0, rotation = 0, scaleX = 1, scaleY = 1 }) {
|
|
|
4529
5039
|
}
|
|
4530
5040
|
|
|
4531
5041
|
// src/components/Sprite.tsx
|
|
4532
|
-
import { useEffect as
|
|
5042
|
+
import { useEffect as useEffect8, useContext as useContext6 } from "react";
|
|
4533
5043
|
function Sprite({
|
|
4534
5044
|
width,
|
|
4535
5045
|
height,
|
|
@@ -4540,6 +5050,7 @@ function Sprite({
|
|
|
4540
5050
|
zIndex = 0,
|
|
4541
5051
|
visible = true,
|
|
4542
5052
|
flipX = false,
|
|
5053
|
+
flipY = false,
|
|
4543
5054
|
anchorX = 0.5,
|
|
4544
5055
|
anchorY = 0.5,
|
|
4545
5056
|
frameIndex = 0,
|
|
@@ -4552,12 +5063,22 @@ function Sprite({
|
|
|
4552
5063
|
tileY,
|
|
4553
5064
|
tileSizeX,
|
|
4554
5065
|
tileSizeY,
|
|
4555
|
-
sampling
|
|
5066
|
+
sampling,
|
|
5067
|
+
blendMode = "normal",
|
|
5068
|
+
layer = "default"
|
|
4556
5069
|
}) {
|
|
4557
5070
|
const resolvedFrameIndex = atlas && frame != null ? atlas[frame] ?? 0 : frameIndex;
|
|
4558
|
-
const engine =
|
|
4559
|
-
const entityId =
|
|
4560
|
-
|
|
5071
|
+
const engine = useContext6(EngineContext);
|
|
5072
|
+
const entityId = useContext6(EntityContext);
|
|
5073
|
+
if (process.env.NODE_ENV !== "production") {
|
|
5074
|
+
if (entityId === null) {
|
|
5075
|
+
console.warn("[Cubeforge] <Sprite> must be inside an <Entity>. No EntityContext found.");
|
|
5076
|
+
}
|
|
5077
|
+
if ((frameWidth != null || frameHeight != null || frameColumns != null) && !src) {
|
|
5078
|
+
console.warn("[Cubeforge] <Sprite> has frameWidth/frameHeight/frameColumns but no `src`. Sprite-sheet props require an image source.");
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
useEffect8(() => {
|
|
4561
5082
|
const comp = createSprite({
|
|
4562
5083
|
width,
|
|
4563
5084
|
height,
|
|
@@ -4568,6 +5089,7 @@ function Sprite({
|
|
|
4568
5089
|
zIndex,
|
|
4569
5090
|
visible,
|
|
4570
5091
|
flipX,
|
|
5092
|
+
flipY,
|
|
4571
5093
|
anchorX,
|
|
4572
5094
|
anchorY,
|
|
4573
5095
|
frameIndex: resolvedFrameIndex,
|
|
@@ -4578,7 +5100,9 @@ function Sprite({
|
|
|
4578
5100
|
tileY,
|
|
4579
5101
|
tileSizeX,
|
|
4580
5102
|
tileSizeY,
|
|
4581
|
-
sampling
|
|
5103
|
+
sampling,
|
|
5104
|
+
blendMode,
|
|
5105
|
+
layer
|
|
4582
5106
|
});
|
|
4583
5107
|
engine.ecs.addComponent(entityId, comp);
|
|
4584
5108
|
if (src) {
|
|
@@ -4592,20 +5116,23 @@ function Sprite({
|
|
|
4592
5116
|
}
|
|
4593
5117
|
return () => engine.ecs.removeComponent(entityId, "Sprite");
|
|
4594
5118
|
}, []);
|
|
4595
|
-
|
|
5119
|
+
useEffect8(() => {
|
|
4596
5120
|
const comp = engine.ecs.getComponent(entityId, "Sprite");
|
|
4597
5121
|
if (!comp) return;
|
|
4598
5122
|
comp.color = color;
|
|
4599
5123
|
comp.visible = visible;
|
|
4600
5124
|
comp.flipX = flipX;
|
|
5125
|
+
comp.flipY = flipY;
|
|
4601
5126
|
comp.zIndex = zIndex;
|
|
4602
5127
|
comp.frameIndex = resolvedFrameIndex;
|
|
4603
|
-
|
|
5128
|
+
comp.blendMode = blendMode;
|
|
5129
|
+
comp.layer = layer;
|
|
5130
|
+
}, [color, visible, flipX, flipY, zIndex, resolvedFrameIndex, blendMode, layer, engine, entityId]);
|
|
4604
5131
|
return null;
|
|
4605
5132
|
}
|
|
4606
5133
|
|
|
4607
5134
|
// src/components/Text.tsx
|
|
4608
|
-
import { useEffect as
|
|
5135
|
+
import { useEffect as useEffect9, useContext as useContext7 } from "react";
|
|
4609
5136
|
function Text({
|
|
4610
5137
|
text,
|
|
4611
5138
|
fontSize = 16,
|
|
@@ -4619,9 +5146,9 @@ function Text({
|
|
|
4619
5146
|
offsetX = 0,
|
|
4620
5147
|
offsetY = 0
|
|
4621
5148
|
}) {
|
|
4622
|
-
const engine =
|
|
4623
|
-
const entityId =
|
|
4624
|
-
|
|
5149
|
+
const engine = useContext7(EngineContext);
|
|
5150
|
+
const entityId = useContext7(EntityContext);
|
|
5151
|
+
useEffect9(() => {
|
|
4625
5152
|
const comp = {
|
|
4626
5153
|
type: "Text",
|
|
4627
5154
|
text,
|
|
@@ -4639,7 +5166,7 @@ function Text({
|
|
|
4639
5166
|
engine.ecs.addComponent(entityId, comp);
|
|
4640
5167
|
return () => engine.ecs.removeComponent(entityId, "Text");
|
|
4641
5168
|
}, []);
|
|
4642
|
-
|
|
5169
|
+
useEffect9(() => {
|
|
4643
5170
|
const comp = engine.ecs.getComponent(entityId, "Text");
|
|
4644
5171
|
if (!comp) return;
|
|
4645
5172
|
comp.text = text;
|
|
@@ -4651,7 +5178,7 @@ function Text({
|
|
|
4651
5178
|
}
|
|
4652
5179
|
|
|
4653
5180
|
// src/components/RigidBody.tsx
|
|
4654
|
-
import { useEffect as
|
|
5181
|
+
import { useEffect as useEffect10, useContext as useContext8 } from "react";
|
|
4655
5182
|
function RigidBody({
|
|
4656
5183
|
mass = 1,
|
|
4657
5184
|
gravityScale = 1,
|
|
@@ -4662,19 +5189,27 @@ function RigidBody({
|
|
|
4662
5189
|
vy = 0,
|
|
4663
5190
|
lockX = false,
|
|
4664
5191
|
lockY = false,
|
|
4665
|
-
ccd = false
|
|
5192
|
+
ccd = false,
|
|
5193
|
+
angularVelocity = 0,
|
|
5194
|
+
angularDamping = 0,
|
|
5195
|
+
linearDamping = 0
|
|
4666
5196
|
}) {
|
|
4667
|
-
const engine =
|
|
4668
|
-
const entityId =
|
|
4669
|
-
|
|
4670
|
-
|
|
5197
|
+
const engine = useContext8(EngineContext);
|
|
5198
|
+
const entityId = useContext8(EntityContext);
|
|
5199
|
+
if (process.env.NODE_ENV !== "production") {
|
|
5200
|
+
if (entityId === null) {
|
|
5201
|
+
console.warn("[Cubeforge] <RigidBody> must be inside an <Entity>. No EntityContext found.");
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
useEffect10(() => {
|
|
5205
|
+
engine.ecs.addComponent(entityId, createRigidBody({ mass, gravityScale, isStatic, bounce, friction, vx, vy, lockX, lockY, ccd, angularVelocity, angularDamping, linearDamping }));
|
|
4671
5206
|
return () => engine.ecs.removeComponent(entityId, "RigidBody");
|
|
4672
5207
|
}, []);
|
|
4673
5208
|
return null;
|
|
4674
5209
|
}
|
|
4675
5210
|
|
|
4676
5211
|
// src/components/BoxCollider.tsx
|
|
4677
|
-
import { useEffect as
|
|
5212
|
+
import { useEffect as useEffect11, useContext as useContext9 } from "react";
|
|
4678
5213
|
function BoxCollider({
|
|
4679
5214
|
width,
|
|
4680
5215
|
height,
|
|
@@ -4685,13 +5220,18 @@ function BoxCollider({
|
|
|
4685
5220
|
mask = "*",
|
|
4686
5221
|
oneWay = false
|
|
4687
5222
|
}) {
|
|
4688
|
-
const engine =
|
|
4689
|
-
const entityId =
|
|
4690
|
-
|
|
5223
|
+
const engine = useContext9(EngineContext);
|
|
5224
|
+
const entityId = useContext9(EntityContext);
|
|
5225
|
+
useEffect11(() => {
|
|
4691
5226
|
engine.ecs.addComponent(entityId, createBoxCollider(width, height, { offsetX, offsetY, isTrigger, layer, mask, oneWay }));
|
|
4692
5227
|
const checkId = setTimeout(() => {
|
|
4693
|
-
if (
|
|
4694
|
-
|
|
5228
|
+
if (process.env.NODE_ENV !== "production") {
|
|
5229
|
+
if (engine.ecs.hasEntity(entityId) && !engine.ecs.hasComponent(entityId, "Transform")) {
|
|
5230
|
+
console.warn(`[Cubeforge] BoxCollider on entity ${entityId} has no Transform. Physics requires Transform.`);
|
|
5231
|
+
}
|
|
5232
|
+
if (engine.ecs.hasEntity(entityId) && !engine.ecs.hasComponent(entityId, "RigidBody")) {
|
|
5233
|
+
console.warn(`[Cubeforge] BoxCollider on entity ${entityId} has no RigidBody. Add a <RigidBody> sibling for physics to work.`);
|
|
5234
|
+
}
|
|
4695
5235
|
}
|
|
4696
5236
|
}, 0);
|
|
4697
5237
|
return () => {
|
|
@@ -4703,7 +5243,7 @@ function BoxCollider({
|
|
|
4703
5243
|
}
|
|
4704
5244
|
|
|
4705
5245
|
// src/components/CircleCollider.tsx
|
|
4706
|
-
import { useEffect as
|
|
5246
|
+
import { useEffect as useEffect12, useContext as useContext10 } from "react";
|
|
4707
5247
|
function CircleCollider({
|
|
4708
5248
|
radius,
|
|
4709
5249
|
offsetX = 0,
|
|
@@ -4712,9 +5252,9 @@ function CircleCollider({
|
|
|
4712
5252
|
layer = "default",
|
|
4713
5253
|
mask = "*"
|
|
4714
5254
|
}) {
|
|
4715
|
-
const engine =
|
|
4716
|
-
const entityId =
|
|
4717
|
-
|
|
5255
|
+
const engine = useContext10(EngineContext);
|
|
5256
|
+
const entityId = useContext10(EntityContext);
|
|
5257
|
+
useEffect12(() => {
|
|
4718
5258
|
engine.ecs.addComponent(entityId, createCircleCollider(radius, { offsetX, offsetY, isTrigger, layer, mask }));
|
|
4719
5259
|
return () => engine.ecs.removeComponent(entityId, "CircleCollider");
|
|
4720
5260
|
}, []);
|
|
@@ -4722,7 +5262,7 @@ function CircleCollider({
|
|
|
4722
5262
|
}
|
|
4723
5263
|
|
|
4724
5264
|
// src/components/CapsuleCollider.tsx
|
|
4725
|
-
import { useEffect as
|
|
5265
|
+
import { useEffect as useEffect13, useContext as useContext11 } from "react";
|
|
4726
5266
|
function CapsuleCollider({
|
|
4727
5267
|
width,
|
|
4728
5268
|
height,
|
|
@@ -4732,9 +5272,9 @@ function CapsuleCollider({
|
|
|
4732
5272
|
layer = "default",
|
|
4733
5273
|
mask = "*"
|
|
4734
5274
|
}) {
|
|
4735
|
-
const engine =
|
|
4736
|
-
const entityId =
|
|
4737
|
-
|
|
5275
|
+
const engine = useContext11(EngineContext);
|
|
5276
|
+
const entityId = useContext11(EntityContext);
|
|
5277
|
+
useEffect13(() => {
|
|
4738
5278
|
engine.ecs.addComponent(entityId, createCapsuleCollider(width, height, { offsetX, offsetY, isTrigger, layer, mask }));
|
|
4739
5279
|
return () => engine.ecs.removeComponent(entityId, "CapsuleCollider");
|
|
4740
5280
|
}, []);
|
|
@@ -4742,16 +5282,16 @@ function CapsuleCollider({
|
|
|
4742
5282
|
}
|
|
4743
5283
|
|
|
4744
5284
|
// src/components/CompoundCollider.tsx
|
|
4745
|
-
import { useEffect as
|
|
5285
|
+
import { useEffect as useEffect14, useContext as useContext12 } from "react";
|
|
4746
5286
|
function CompoundCollider({
|
|
4747
5287
|
shapes,
|
|
4748
5288
|
isTrigger = false,
|
|
4749
5289
|
layer = "default",
|
|
4750
5290
|
mask = "*"
|
|
4751
5291
|
}) {
|
|
4752
|
-
const engine =
|
|
4753
|
-
const entityId =
|
|
4754
|
-
|
|
5292
|
+
const engine = useContext12(EngineContext);
|
|
5293
|
+
const entityId = useContext12(EntityContext);
|
|
5294
|
+
useEffect14(() => {
|
|
4755
5295
|
engine.ecs.addComponent(entityId, createCompoundCollider(shapes, { isTrigger, layer, mask }));
|
|
4756
5296
|
const checkId = setTimeout(() => {
|
|
4757
5297
|
if (engine.ecs.hasEntity(entityId) && !engine.ecs.hasComponent(entityId, "Transform")) {
|
|
@@ -4767,15 +5307,20 @@ function CompoundCollider({
|
|
|
4767
5307
|
}
|
|
4768
5308
|
|
|
4769
5309
|
// src/components/Script.tsx
|
|
4770
|
-
import { useEffect as
|
|
5310
|
+
import { useEffect as useEffect15, useContext as useContext13, useRef as useRef5 } from "react";
|
|
4771
5311
|
function Script({ init, update }) {
|
|
4772
|
-
const engine =
|
|
4773
|
-
const entityId =
|
|
4774
|
-
|
|
5312
|
+
const engine = useContext13(EngineContext);
|
|
5313
|
+
const entityId = useContext13(EntityContext);
|
|
5314
|
+
if (process.env.NODE_ENV !== "production") {
|
|
5315
|
+
if (entityId === null) {
|
|
5316
|
+
console.warn("[Cubeforge] <Script> must be inside an <Entity>. No EntityContext found.");
|
|
5317
|
+
}
|
|
5318
|
+
}
|
|
5319
|
+
const initRef = useRef5(init);
|
|
4775
5320
|
initRef.current = init;
|
|
4776
|
-
const updateRef =
|
|
5321
|
+
const updateRef = useRef5(update);
|
|
4777
5322
|
updateRef.current = update;
|
|
4778
|
-
|
|
5323
|
+
useEffect15(() => {
|
|
4779
5324
|
if (initRef.current) {
|
|
4780
5325
|
try {
|
|
4781
5326
|
initRef.current(entityId, engine.ecs);
|
|
@@ -4791,7 +5336,7 @@ function Script({ init, update }) {
|
|
|
4791
5336
|
}
|
|
4792
5337
|
|
|
4793
5338
|
// src/components/Camera2D.tsx
|
|
4794
|
-
import { useEffect as
|
|
5339
|
+
import { useEffect as useEffect16, useContext as useContext14 } from "react";
|
|
4795
5340
|
function Camera2D({
|
|
4796
5341
|
followEntity,
|
|
4797
5342
|
x = 0,
|
|
@@ -4804,8 +5349,8 @@ function Camera2D({
|
|
|
4804
5349
|
followOffsetX = 0,
|
|
4805
5350
|
followOffsetY = 0
|
|
4806
5351
|
}) {
|
|
4807
|
-
const engine =
|
|
4808
|
-
|
|
5352
|
+
const engine = useContext14(EngineContext);
|
|
5353
|
+
useEffect16(() => {
|
|
4809
5354
|
const entityId = engine.ecs.createEntity();
|
|
4810
5355
|
engine.ecs.addComponent(entityId, createCamera2D({
|
|
4811
5356
|
followEntityId: followEntity,
|
|
@@ -4821,7 +5366,7 @@ function Camera2D({
|
|
|
4821
5366
|
}));
|
|
4822
5367
|
return () => engine.ecs.destroyEntity(entityId);
|
|
4823
5368
|
}, []);
|
|
4824
|
-
|
|
5369
|
+
useEffect16(() => {
|
|
4825
5370
|
const camId = engine.ecs.queryOne("Camera2D");
|
|
4826
5371
|
if (camId === void 0) return;
|
|
4827
5372
|
const cam = engine.ecs.getComponent(camId, "Camera2D");
|
|
@@ -4840,11 +5385,11 @@ function Camera2D({
|
|
|
4840
5385
|
}
|
|
4841
5386
|
|
|
4842
5387
|
// src/components/Animation.tsx
|
|
4843
|
-
import { useEffect as
|
|
5388
|
+
import { useEffect as useEffect17, useContext as useContext15 } from "react";
|
|
4844
5389
|
function Animation({ frames, fps = 12, loop = true, playing = true, onComplete, frameEvents }) {
|
|
4845
|
-
const engine =
|
|
4846
|
-
const entityId =
|
|
4847
|
-
|
|
5390
|
+
const engine = useContext15(EngineContext);
|
|
5391
|
+
const entityId = useContext15(EntityContext);
|
|
5392
|
+
useEffect17(() => {
|
|
4848
5393
|
const state = {
|
|
4849
5394
|
type: "AnimationState",
|
|
4850
5395
|
frames,
|
|
@@ -4862,7 +5407,7 @@ function Animation({ frames, fps = 12, loop = true, playing = true, onComplete,
|
|
|
4862
5407
|
engine.ecs.removeComponent(entityId, "AnimationState");
|
|
4863
5408
|
};
|
|
4864
5409
|
}, []);
|
|
4865
|
-
|
|
5410
|
+
useEffect17(() => {
|
|
4866
5411
|
const anim = engine.ecs.getComponent(entityId, "AnimationState");
|
|
4867
5412
|
if (!anim) return;
|
|
4868
5413
|
const wasFramesChanged = anim.frames !== frames;
|
|
@@ -4881,12 +5426,162 @@ function Animation({ frames, fps = 12, loop = true, playing = true, onComplete,
|
|
|
4881
5426
|
return null;
|
|
4882
5427
|
}
|
|
4883
5428
|
|
|
5429
|
+
// src/components/AnimatedSprite.tsx
|
|
5430
|
+
import { useEffect as useEffect18, useContext as useContext16 } from "react";
|
|
5431
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
5432
|
+
function defineAnimations(clips) {
|
|
5433
|
+
return clips;
|
|
5434
|
+
}
|
|
5435
|
+
function AnimatedSprite(props) {
|
|
5436
|
+
const {
|
|
5437
|
+
width,
|
|
5438
|
+
height,
|
|
5439
|
+
src,
|
|
5440
|
+
color,
|
|
5441
|
+
offsetX,
|
|
5442
|
+
offsetY,
|
|
5443
|
+
zIndex,
|
|
5444
|
+
visible,
|
|
5445
|
+
flipX,
|
|
5446
|
+
flipY,
|
|
5447
|
+
anchorX,
|
|
5448
|
+
anchorY,
|
|
5449
|
+
frameWidth,
|
|
5450
|
+
frameHeight,
|
|
5451
|
+
frameColumns,
|
|
5452
|
+
atlas,
|
|
5453
|
+
frame,
|
|
5454
|
+
tileX,
|
|
5455
|
+
tileY,
|
|
5456
|
+
tileSizeX,
|
|
5457
|
+
tileSizeY,
|
|
5458
|
+
sampling,
|
|
5459
|
+
blendMode
|
|
5460
|
+
} = props;
|
|
5461
|
+
const spriteEl = /* @__PURE__ */ jsx5(
|
|
5462
|
+
Sprite,
|
|
5463
|
+
{
|
|
5464
|
+
width,
|
|
5465
|
+
height,
|
|
5466
|
+
src,
|
|
5467
|
+
color,
|
|
5468
|
+
offsetX,
|
|
5469
|
+
offsetY,
|
|
5470
|
+
zIndex,
|
|
5471
|
+
visible,
|
|
5472
|
+
flipX,
|
|
5473
|
+
flipY,
|
|
5474
|
+
anchorX,
|
|
5475
|
+
anchorY,
|
|
5476
|
+
frameWidth,
|
|
5477
|
+
frameHeight,
|
|
5478
|
+
frameColumns,
|
|
5479
|
+
atlas,
|
|
5480
|
+
frame,
|
|
5481
|
+
tileX,
|
|
5482
|
+
tileY,
|
|
5483
|
+
tileSizeX,
|
|
5484
|
+
tileSizeY,
|
|
5485
|
+
sampling,
|
|
5486
|
+
blendMode
|
|
5487
|
+
}
|
|
5488
|
+
);
|
|
5489
|
+
if (props.animations) {
|
|
5490
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
5491
|
+
spriteEl,
|
|
5492
|
+
/* @__PURE__ */ jsx5(
|
|
5493
|
+
MultiClipAnimation,
|
|
5494
|
+
{
|
|
5495
|
+
animations: props.animations,
|
|
5496
|
+
current: props.current
|
|
5497
|
+
}
|
|
5498
|
+
)
|
|
5499
|
+
] });
|
|
5500
|
+
}
|
|
5501
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
5502
|
+
spriteEl,
|
|
5503
|
+
/* @__PURE__ */ jsx5(
|
|
5504
|
+
Animation,
|
|
5505
|
+
{
|
|
5506
|
+
frames: props.frames,
|
|
5507
|
+
fps: props.fps,
|
|
5508
|
+
loop: props.loop,
|
|
5509
|
+
playing: props.playing,
|
|
5510
|
+
onComplete: props.onComplete,
|
|
5511
|
+
frameEvents: props.frameEvents
|
|
5512
|
+
}
|
|
5513
|
+
)
|
|
5514
|
+
] });
|
|
5515
|
+
}
|
|
5516
|
+
function MultiClipAnimation({ animations, current }) {
|
|
5517
|
+
const engine = useContext16(EngineContext);
|
|
5518
|
+
const entityId = useContext16(EntityContext);
|
|
5519
|
+
useEffect18(() => {
|
|
5520
|
+
const clip = animations[current] ?? Object.values(animations)[0];
|
|
5521
|
+
const state = {
|
|
5522
|
+
type: "AnimationState",
|
|
5523
|
+
clips: animations,
|
|
5524
|
+
currentClip: current,
|
|
5525
|
+
_resolvedClip: current,
|
|
5526
|
+
frames: clip.frames,
|
|
5527
|
+
fps: clip.fps ?? 12,
|
|
5528
|
+
loop: clip.loop ?? true,
|
|
5529
|
+
playing: true,
|
|
5530
|
+
currentIndex: 0,
|
|
5531
|
+
timer: 0,
|
|
5532
|
+
_completed: false,
|
|
5533
|
+
onComplete: clip.onComplete
|
|
5534
|
+
};
|
|
5535
|
+
engine.ecs.addComponent(entityId, state);
|
|
5536
|
+
return () => engine.ecs.removeComponent(entityId, "AnimationState");
|
|
5537
|
+
}, []);
|
|
5538
|
+
useEffect18(() => {
|
|
5539
|
+
const anim = engine.ecs.getComponent(entityId, "AnimationState");
|
|
5540
|
+
if (!anim) return;
|
|
5541
|
+
anim.clips = animations;
|
|
5542
|
+
anim.currentClip = current;
|
|
5543
|
+
}, [current, animations, engine, entityId]);
|
|
5544
|
+
return null;
|
|
5545
|
+
}
|
|
5546
|
+
|
|
5547
|
+
// src/components/Animator.tsx
|
|
5548
|
+
import { useEffect as useEffect19, useContext as useContext17 } from "react";
|
|
5549
|
+
function Animator({ initial, states, params = {}, playing = true }) {
|
|
5550
|
+
const engine = useContext17(EngineContext);
|
|
5551
|
+
const entityId = useContext17(EntityContext);
|
|
5552
|
+
useEffect19(() => {
|
|
5553
|
+
const comp = {
|
|
5554
|
+
type: "Animator",
|
|
5555
|
+
initialState: initial,
|
|
5556
|
+
currentState: initial,
|
|
5557
|
+
states,
|
|
5558
|
+
params: { ...params },
|
|
5559
|
+
playing,
|
|
5560
|
+
_entered: false
|
|
5561
|
+
};
|
|
5562
|
+
engine.ecs.addComponent(entityId, comp);
|
|
5563
|
+
return () => engine.ecs.removeComponent(entityId, "Animator");
|
|
5564
|
+
}, []);
|
|
5565
|
+
useEffect19(() => {
|
|
5566
|
+
const comp = engine.ecs.getComponent(entityId, "Animator");
|
|
5567
|
+
if (!comp) return;
|
|
5568
|
+
Object.assign(comp.params, params);
|
|
5569
|
+
comp.playing = playing;
|
|
5570
|
+
}, [params, playing, engine, entityId]);
|
|
5571
|
+
useEffect19(() => {
|
|
5572
|
+
const comp = engine.ecs.getComponent(entityId, "Animator");
|
|
5573
|
+
if (!comp) return;
|
|
5574
|
+
comp.states = states;
|
|
5575
|
+
}, [states, engine, entityId]);
|
|
5576
|
+
return null;
|
|
5577
|
+
}
|
|
5578
|
+
|
|
4884
5579
|
// src/components/SquashStretch.tsx
|
|
4885
|
-
import { useEffect as
|
|
5580
|
+
import { useEffect as useEffect20, useContext as useContext18 } from "react";
|
|
4886
5581
|
function SquashStretch({ intensity = 0.2, recovery = 8 }) {
|
|
4887
|
-
const engine =
|
|
4888
|
-
const entityId =
|
|
4889
|
-
|
|
5582
|
+
const engine = useContext18(EngineContext);
|
|
5583
|
+
const entityId = useContext18(EntityContext);
|
|
5584
|
+
useEffect20(() => {
|
|
4890
5585
|
engine.ecs.addComponent(entityId, {
|
|
4891
5586
|
type: "SquashStretch",
|
|
4892
5587
|
intensity,
|
|
@@ -4900,7 +5595,7 @@ function SquashStretch({ intensity = 0.2, recovery = 8 }) {
|
|
|
4900
5595
|
}
|
|
4901
5596
|
|
|
4902
5597
|
// src/components/ParticleEmitter.tsx
|
|
4903
|
-
import { useEffect as
|
|
5598
|
+
import { useEffect as useEffect21, useContext as useContext19 } from "react";
|
|
4904
5599
|
|
|
4905
5600
|
// src/components/particlePresets.ts
|
|
4906
5601
|
var PARTICLE_PRESETS = {
|
|
@@ -4973,7 +5668,12 @@ function ParticleEmitter({
|
|
|
4973
5668
|
particleSize,
|
|
4974
5669
|
color,
|
|
4975
5670
|
gravity,
|
|
4976
|
-
maxParticles
|
|
5671
|
+
maxParticles,
|
|
5672
|
+
burstCount,
|
|
5673
|
+
emitShape,
|
|
5674
|
+
emitRadius,
|
|
5675
|
+
emitWidth,
|
|
5676
|
+
emitHeight
|
|
4977
5677
|
}) {
|
|
4978
5678
|
const presetConfig = preset ? PARTICLE_PRESETS[preset] : {};
|
|
4979
5679
|
const resolvedRate = rate ?? presetConfig.rate ?? 20;
|
|
@@ -4985,9 +5685,9 @@ function ParticleEmitter({
|
|
|
4985
5685
|
const resolvedColor = color ?? presetConfig.color ?? "#ffffff";
|
|
4986
5686
|
const resolvedGravity = gravity ?? presetConfig.gravity ?? 200;
|
|
4987
5687
|
const resolvedMaxParticles = maxParticles ?? presetConfig.maxParticles ?? 100;
|
|
4988
|
-
const engine =
|
|
4989
|
-
const entityId =
|
|
4990
|
-
|
|
5688
|
+
const engine = useContext19(EngineContext);
|
|
5689
|
+
const entityId = useContext19(EntityContext);
|
|
5690
|
+
useEffect21(() => {
|
|
4991
5691
|
engine.ecs.addComponent(entityId, {
|
|
4992
5692
|
type: "ParticlePool",
|
|
4993
5693
|
particles: [],
|
|
@@ -5001,11 +5701,16 @@ function ParticleEmitter({
|
|
|
5001
5701
|
particleLife: resolvedParticleLife,
|
|
5002
5702
|
particleSize: resolvedParticleSize,
|
|
5003
5703
|
color: resolvedColor,
|
|
5004
|
-
gravity: resolvedGravity
|
|
5704
|
+
gravity: resolvedGravity,
|
|
5705
|
+
burstCount,
|
|
5706
|
+
emitShape,
|
|
5707
|
+
emitRadius,
|
|
5708
|
+
emitWidth,
|
|
5709
|
+
emitHeight
|
|
5005
5710
|
});
|
|
5006
5711
|
return () => engine.ecs.removeComponent(entityId, "ParticlePool");
|
|
5007
5712
|
}, []);
|
|
5008
|
-
|
|
5713
|
+
useEffect21(() => {
|
|
5009
5714
|
const pool = engine.ecs.getComponent(entityId, "ParticlePool");
|
|
5010
5715
|
if (!pool) return;
|
|
5011
5716
|
pool.active = active;
|
|
@@ -5014,7 +5719,7 @@ function ParticleEmitter({
|
|
|
5014
5719
|
}
|
|
5015
5720
|
|
|
5016
5721
|
// src/components/VirtualJoystick.tsx
|
|
5017
|
-
import { useRef as
|
|
5722
|
+
import { useRef as useRef6 } from "react";
|
|
5018
5723
|
|
|
5019
5724
|
// src/hooks/useVirtualInput.ts
|
|
5020
5725
|
var _axes = { x: 0, y: 0 };
|
|
@@ -5039,7 +5744,7 @@ function useVirtualInput() {
|
|
|
5039
5744
|
}
|
|
5040
5745
|
|
|
5041
5746
|
// src/components/VirtualJoystick.tsx
|
|
5042
|
-
import { Fragment as
|
|
5747
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
5043
5748
|
function VirtualJoystick({
|
|
5044
5749
|
size = 120,
|
|
5045
5750
|
position = "left",
|
|
@@ -5048,10 +5753,10 @@ function VirtualJoystick({
|
|
|
5048
5753
|
actionLabel = "A",
|
|
5049
5754
|
actionName = "action"
|
|
5050
5755
|
}) {
|
|
5051
|
-
const baseRef =
|
|
5052
|
-
const stickRef =
|
|
5053
|
-
const activePtr =
|
|
5054
|
-
const baseCenterRef =
|
|
5756
|
+
const baseRef = useRef6(null);
|
|
5757
|
+
const stickRef = useRef6(null);
|
|
5758
|
+
const activePtr = useRef6(null);
|
|
5759
|
+
const baseCenterRef = useRef6({ x: 0, y: 0 });
|
|
5055
5760
|
const radius = size / 2 - 16;
|
|
5056
5761
|
const applyStickPosition = (dx, dy) => {
|
|
5057
5762
|
if (!stickRef.current) return;
|
|
@@ -5096,8 +5801,8 @@ function VirtualJoystick({
|
|
|
5096
5801
|
};
|
|
5097
5802
|
const cornerStyle = position === "left" ? { left: 24, bottom: 24 } : { right: 24, bottom: 24 };
|
|
5098
5803
|
const actionCorner = position === "left" ? { right: 24, bottom: 24 } : { left: 24, bottom: 24 };
|
|
5099
|
-
return /* @__PURE__ */
|
|
5100
|
-
/* @__PURE__ */
|
|
5804
|
+
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
5805
|
+
/* @__PURE__ */ jsx6(
|
|
5101
5806
|
"div",
|
|
5102
5807
|
{
|
|
5103
5808
|
onPointerDown: handlePointerDown,
|
|
@@ -5118,7 +5823,7 @@ function VirtualJoystick({
|
|
|
5118
5823
|
...style
|
|
5119
5824
|
},
|
|
5120
5825
|
ref: baseRef,
|
|
5121
|
-
children: /* @__PURE__ */
|
|
5826
|
+
children: /* @__PURE__ */ jsx6(
|
|
5122
5827
|
"div",
|
|
5123
5828
|
{
|
|
5124
5829
|
ref: stickRef,
|
|
@@ -5138,7 +5843,7 @@ function VirtualJoystick({
|
|
|
5138
5843
|
)
|
|
5139
5844
|
}
|
|
5140
5845
|
),
|
|
5141
|
-
actionButton && /* @__PURE__ */
|
|
5846
|
+
actionButton && /* @__PURE__ */ jsx6(
|
|
5142
5847
|
"div",
|
|
5143
5848
|
{
|
|
5144
5849
|
onPointerDown: (e) => {
|
|
@@ -5173,7 +5878,7 @@ function VirtualJoystick({
|
|
|
5173
5878
|
}
|
|
5174
5879
|
|
|
5175
5880
|
// src/components/MovingPlatform.tsx
|
|
5176
|
-
import { jsx as
|
|
5881
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
5177
5882
|
var platformPhases = /* @__PURE__ */ new Map();
|
|
5178
5883
|
function MovingPlatform({
|
|
5179
5884
|
x1,
|
|
@@ -5185,12 +5890,12 @@ function MovingPlatform({
|
|
|
5185
5890
|
duration = 3,
|
|
5186
5891
|
color = "#37474f"
|
|
5187
5892
|
}) {
|
|
5188
|
-
return /* @__PURE__ */
|
|
5189
|
-
/* @__PURE__ */
|
|
5190
|
-
/* @__PURE__ */
|
|
5191
|
-
/* @__PURE__ */
|
|
5192
|
-
/* @__PURE__ */
|
|
5193
|
-
/* @__PURE__ */
|
|
5893
|
+
return /* @__PURE__ */ jsxs5(Entity, { children: [
|
|
5894
|
+
/* @__PURE__ */ jsx7(Transform, { x: x1, y: y1 }),
|
|
5895
|
+
/* @__PURE__ */ jsx7(Sprite, { width, height, color, zIndex: 5 }),
|
|
5896
|
+
/* @__PURE__ */ jsx7(RigidBody, { isStatic: true }),
|
|
5897
|
+
/* @__PURE__ */ jsx7(BoxCollider, { width, height }),
|
|
5898
|
+
/* @__PURE__ */ jsx7(
|
|
5194
5899
|
Script,
|
|
5195
5900
|
{
|
|
5196
5901
|
init: () => {
|
|
@@ -5212,7 +5917,7 @@ function MovingPlatform({
|
|
|
5212
5917
|
|
|
5213
5918
|
// src/components/Checkpoint.tsx
|
|
5214
5919
|
import { useState as useState4 } from "react";
|
|
5215
|
-
import { jsx as
|
|
5920
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
5216
5921
|
function CheckpointActivator({ onActivate }) {
|
|
5217
5922
|
const [used, setUsed] = useState4(false);
|
|
5218
5923
|
useTriggerEnter(() => {
|
|
@@ -5230,17 +5935,17 @@ function Checkpoint({
|
|
|
5230
5935
|
color = "#ffd54f",
|
|
5231
5936
|
onActivate
|
|
5232
5937
|
}) {
|
|
5233
|
-
return /* @__PURE__ */
|
|
5234
|
-
/* @__PURE__ */
|
|
5235
|
-
/* @__PURE__ */
|
|
5236
|
-
/* @__PURE__ */
|
|
5237
|
-
/* @__PURE__ */
|
|
5938
|
+
return /* @__PURE__ */ jsxs6(Entity, { tags: ["checkpoint"], children: [
|
|
5939
|
+
/* @__PURE__ */ jsx8(Transform, { x, y }),
|
|
5940
|
+
/* @__PURE__ */ jsx8(Sprite, { width, height, color, zIndex: 5 }),
|
|
5941
|
+
/* @__PURE__ */ jsx8(BoxCollider, { width, height, isTrigger: true }),
|
|
5942
|
+
/* @__PURE__ */ jsx8(CheckpointActivator, { onActivate })
|
|
5238
5943
|
] });
|
|
5239
5944
|
}
|
|
5240
5945
|
|
|
5241
5946
|
// src/components/Tilemap.tsx
|
|
5242
|
-
import { useEffect as
|
|
5243
|
-
import { Fragment as
|
|
5947
|
+
import { useEffect as useEffect22, useState as useState5, useContext as useContext20 } from "react";
|
|
5948
|
+
import { Fragment as Fragment5, jsx as jsx9 } from "react/jsx-runtime";
|
|
5244
5949
|
var animatedTiles = /* @__PURE__ */ new Map();
|
|
5245
5950
|
function getProperty(props, name) {
|
|
5246
5951
|
return props?.find((p) => p.name === name)?.value;
|
|
@@ -5262,11 +5967,12 @@ function Tilemap({
|
|
|
5262
5967
|
collisionLayer = "collision",
|
|
5263
5968
|
triggerLayer: triggerLayerName = "triggers",
|
|
5264
5969
|
onTileProperty,
|
|
5265
|
-
navGrid
|
|
5970
|
+
navGrid,
|
|
5971
|
+
mergeColliders = true
|
|
5266
5972
|
}) {
|
|
5267
|
-
const engine =
|
|
5973
|
+
const engine = useContext20(EngineContext);
|
|
5268
5974
|
const [spawnedNodes, setSpawnedNodes] = useState5([]);
|
|
5269
|
-
|
|
5975
|
+
useEffect22(() => {
|
|
5270
5976
|
if (!engine) return;
|
|
5271
5977
|
const createdEntities = [];
|
|
5272
5978
|
async function load() {
|
|
@@ -5334,32 +6040,54 @@ function Tilemap({
|
|
|
5334
6040
|
}
|
|
5335
6041
|
}
|
|
5336
6042
|
if (collision || trigger) {
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
col++;
|
|
5344
|
-
continue;
|
|
6043
|
+
if (mergeColliders) {
|
|
6044
|
+
const solidGrid = [];
|
|
6045
|
+
for (let row = 0; row < mapData.height; row++) {
|
|
6046
|
+
solidGrid[row] = [];
|
|
6047
|
+
for (let col = 0; col < mapData.width; col++) {
|
|
6048
|
+
solidGrid[row][col] = layer.data[row * mapData.width + col] !== 0;
|
|
5345
6049
|
}
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
}
|
|
5350
|
-
const runWidth = runLength * tilewidth;
|
|
5351
|
-
const x = col * tilewidth + runWidth / 2;
|
|
5352
|
-
const y = row * tileheight + tileheight / 2;
|
|
6050
|
+
}
|
|
6051
|
+
const merged = mergeTileColliders(solidGrid, tilewidth, tileheight, 0, 0);
|
|
6052
|
+
for (const rect of merged) {
|
|
5353
6053
|
const eid = engine.ecs.createEntity();
|
|
5354
6054
|
createdEntities.push(eid);
|
|
5355
|
-
engine.ecs.addComponent(eid, createTransform(x, y));
|
|
6055
|
+
engine.ecs.addComponent(eid, createTransform(rect.x, rect.y));
|
|
5356
6056
|
if (collision) {
|
|
5357
6057
|
engine.ecs.addComponent(eid, createRigidBody({ isStatic: true }));
|
|
5358
|
-
engine.ecs.addComponent(eid, createBoxCollider(
|
|
6058
|
+
engine.ecs.addComponent(eid, createBoxCollider(rect.width, rect.height));
|
|
5359
6059
|
} else {
|
|
5360
|
-
engine.ecs.addComponent(eid, createBoxCollider(
|
|
6060
|
+
engine.ecs.addComponent(eid, createBoxCollider(rect.width, rect.height, { isTrigger: true }));
|
|
6061
|
+
}
|
|
6062
|
+
}
|
|
6063
|
+
} else {
|
|
6064
|
+
for (let row = 0; row < mapData.height; row++) {
|
|
6065
|
+
let col = 0;
|
|
6066
|
+
while (col < mapData.width) {
|
|
6067
|
+
const i = row * mapData.width + col;
|
|
6068
|
+
const gid = layer.data[i];
|
|
6069
|
+
if (gid === 0) {
|
|
6070
|
+
col++;
|
|
6071
|
+
continue;
|
|
6072
|
+
}
|
|
6073
|
+
let runLength = 1;
|
|
6074
|
+
while (col + runLength < mapData.width && layer.data[row * mapData.width + col + runLength] !== 0) {
|
|
6075
|
+
runLength++;
|
|
6076
|
+
}
|
|
6077
|
+
const runWidth = runLength * tilewidth;
|
|
6078
|
+
const x = col * tilewidth + runWidth / 2;
|
|
6079
|
+
const y = row * tileheight + tileheight / 2;
|
|
6080
|
+
const eid = engine.ecs.createEntity();
|
|
6081
|
+
createdEntities.push(eid);
|
|
6082
|
+
engine.ecs.addComponent(eid, createTransform(x, y));
|
|
6083
|
+
if (collision) {
|
|
6084
|
+
engine.ecs.addComponent(eid, createRigidBody({ isStatic: true }));
|
|
6085
|
+
engine.ecs.addComponent(eid, createBoxCollider(runWidth, tileheight));
|
|
6086
|
+
} else {
|
|
6087
|
+
engine.ecs.addComponent(eid, createBoxCollider(runWidth, tileheight, { isTrigger: true }));
|
|
6088
|
+
}
|
|
6089
|
+
col += runLength;
|
|
5361
6090
|
}
|
|
5362
|
-
col += runLength;
|
|
5363
6091
|
}
|
|
5364
6092
|
}
|
|
5365
6093
|
} else {
|
|
@@ -5453,12 +6181,12 @@ function Tilemap({
|
|
|
5453
6181
|
};
|
|
5454
6182
|
}, [src]);
|
|
5455
6183
|
if (spawnedNodes.length === 0) return null;
|
|
5456
|
-
return /* @__PURE__ */
|
|
6184
|
+
return /* @__PURE__ */ jsx9(Fragment5, { children: spawnedNodes });
|
|
5457
6185
|
}
|
|
5458
6186
|
|
|
5459
6187
|
// src/components/ParallaxLayer.tsx
|
|
5460
|
-
import { useEffect as
|
|
5461
|
-
import { jsx as
|
|
6188
|
+
import { useEffect as useEffect23, useContext as useContext21 } from "react";
|
|
6189
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5462
6190
|
function ParallaxLayerInner({
|
|
5463
6191
|
src,
|
|
5464
6192
|
speedX,
|
|
@@ -5469,9 +6197,9 @@ function ParallaxLayerInner({
|
|
|
5469
6197
|
offsetX,
|
|
5470
6198
|
offsetY
|
|
5471
6199
|
}) {
|
|
5472
|
-
const engine =
|
|
5473
|
-
const entityId =
|
|
5474
|
-
|
|
6200
|
+
const engine = useContext21(EngineContext);
|
|
6201
|
+
const entityId = useContext21(EntityContext);
|
|
6202
|
+
useEffect23(() => {
|
|
5475
6203
|
engine.ecs.addComponent(entityId, {
|
|
5476
6204
|
type: "ParallaxLayer",
|
|
5477
6205
|
src,
|
|
@@ -5487,7 +6215,7 @@ function ParallaxLayerInner({
|
|
|
5487
6215
|
});
|
|
5488
6216
|
return () => engine.ecs.removeComponent(entityId, "ParallaxLayer");
|
|
5489
6217
|
}, []);
|
|
5490
|
-
|
|
6218
|
+
useEffect23(() => {
|
|
5491
6219
|
const layer = engine.ecs.getComponent(entityId, "ParallaxLayer");
|
|
5492
6220
|
if (!layer) return;
|
|
5493
6221
|
layer.src = src;
|
|
@@ -5511,9 +6239,9 @@ function ParallaxLayer({
|
|
|
5511
6239
|
offsetX = 0,
|
|
5512
6240
|
offsetY = 0
|
|
5513
6241
|
}) {
|
|
5514
|
-
return /* @__PURE__ */
|
|
5515
|
-
/* @__PURE__ */
|
|
5516
|
-
/* @__PURE__ */
|
|
6242
|
+
return /* @__PURE__ */ jsxs7(Entity, { children: [
|
|
6243
|
+
/* @__PURE__ */ jsx10(Transform, { x: 0, y: 0 }),
|
|
6244
|
+
/* @__PURE__ */ jsx10(
|
|
5517
6245
|
ParallaxLayerInner,
|
|
5518
6246
|
{
|
|
5519
6247
|
src,
|
|
@@ -5530,10 +6258,10 @@ function ParallaxLayer({
|
|
|
5530
6258
|
}
|
|
5531
6259
|
|
|
5532
6260
|
// src/components/ScreenFlash.tsx
|
|
5533
|
-
import { forwardRef, useImperativeHandle, useRef as
|
|
5534
|
-
import { jsx as
|
|
6261
|
+
import { forwardRef, useImperativeHandle, useRef as useRef7 } from "react";
|
|
6262
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
5535
6263
|
var ScreenFlash = forwardRef((_, ref) => {
|
|
5536
|
-
const divRef =
|
|
6264
|
+
const divRef = useRef7(null);
|
|
5537
6265
|
useImperativeHandle(ref, () => ({
|
|
5538
6266
|
flash(color, duration) {
|
|
5539
6267
|
const el = divRef.current;
|
|
@@ -5551,7 +6279,7 @@ var ScreenFlash = forwardRef((_, ref) => {
|
|
|
5551
6279
|
});
|
|
5552
6280
|
}
|
|
5553
6281
|
}));
|
|
5554
|
-
return /* @__PURE__ */
|
|
6282
|
+
return /* @__PURE__ */ jsx11(
|
|
5555
6283
|
"div",
|
|
5556
6284
|
{
|
|
5557
6285
|
ref: divRef,
|
|
@@ -5569,8 +6297,8 @@ var ScreenFlash = forwardRef((_, ref) => {
|
|
|
5569
6297
|
ScreenFlash.displayName = "ScreenFlash";
|
|
5570
6298
|
|
|
5571
6299
|
// src/components/CameraZone.tsx
|
|
5572
|
-
import { useEffect as
|
|
5573
|
-
import { Fragment as
|
|
6300
|
+
import { useEffect as useEffect24, useContext as useContext22, useRef as useRef8 } from "react";
|
|
6301
|
+
import { Fragment as Fragment6, jsx as jsx12 } from "react/jsx-runtime";
|
|
5574
6302
|
function CameraZone({
|
|
5575
6303
|
x,
|
|
5576
6304
|
y,
|
|
@@ -5581,10 +6309,10 @@ function CameraZone({
|
|
|
5581
6309
|
targetY,
|
|
5582
6310
|
children
|
|
5583
6311
|
}) {
|
|
5584
|
-
const engine =
|
|
5585
|
-
const prevFollowRef =
|
|
5586
|
-
const activeRef =
|
|
5587
|
-
|
|
6312
|
+
const engine = useContext22(EngineContext);
|
|
6313
|
+
const prevFollowRef = useRef8(void 0);
|
|
6314
|
+
const activeRef = useRef8(false);
|
|
6315
|
+
useEffect24(() => {
|
|
5588
6316
|
const eid = engine.ecs.createEntity();
|
|
5589
6317
|
engine.ecs.addComponent(eid, createScript(() => {
|
|
5590
6318
|
const cam = engine.ecs.queryOne("Camera2D");
|
|
@@ -5627,15 +6355,15 @@ function CameraZone({
|
|
|
5627
6355
|
if (engine.ecs.hasEntity(eid)) engine.ecs.destroyEntity(eid);
|
|
5628
6356
|
};
|
|
5629
6357
|
}, [engine.ecs, x, y, width, height, watchTag, targetX, targetY]);
|
|
5630
|
-
return /* @__PURE__ */
|
|
6358
|
+
return /* @__PURE__ */ jsx12(Fragment6, { children: children ?? null });
|
|
5631
6359
|
}
|
|
5632
6360
|
|
|
5633
6361
|
// src/components/Trail.tsx
|
|
5634
|
-
import { useEffect as
|
|
6362
|
+
import { useEffect as useEffect25, useContext as useContext23 } from "react";
|
|
5635
6363
|
function Trail({ length = 20, color = "#ffffff", width = 3 }) {
|
|
5636
|
-
const engine =
|
|
5637
|
-
const entityId =
|
|
5638
|
-
|
|
6364
|
+
const engine = useContext23(EngineContext);
|
|
6365
|
+
const entityId = useContext23(EntityContext);
|
|
6366
|
+
useEffect25(() => {
|
|
5639
6367
|
engine.ecs.addComponent(entityId, createTrail({ length, color, width }));
|
|
5640
6368
|
return () => engine.ecs.removeComponent(entityId, "Trail");
|
|
5641
6369
|
}, []);
|
|
@@ -5643,7 +6371,7 @@ function Trail({ length = 20, color = "#ffffff", width = 3 }) {
|
|
|
5643
6371
|
}
|
|
5644
6372
|
|
|
5645
6373
|
// src/components/NineSlice.tsx
|
|
5646
|
-
import { useEffect as
|
|
6374
|
+
import { useEffect as useEffect26, useContext as useContext24 } from "react";
|
|
5647
6375
|
function NineSlice({
|
|
5648
6376
|
src,
|
|
5649
6377
|
width,
|
|
@@ -5654,9 +6382,9 @@ function NineSlice({
|
|
|
5654
6382
|
borderLeft = 8,
|
|
5655
6383
|
zIndex = 0
|
|
5656
6384
|
}) {
|
|
5657
|
-
const engine =
|
|
5658
|
-
const entityId =
|
|
5659
|
-
|
|
6385
|
+
const engine = useContext24(EngineContext);
|
|
6386
|
+
const entityId = useContext24(EntityContext);
|
|
6387
|
+
useEffect26(() => {
|
|
5660
6388
|
engine.ecs.addComponent(
|
|
5661
6389
|
entityId,
|
|
5662
6390
|
createNineSlice(src, width, height, {
|
|
@@ -5673,14 +6401,14 @@ function NineSlice({
|
|
|
5673
6401
|
}
|
|
5674
6402
|
|
|
5675
6403
|
// src/components/AssetLoader.tsx
|
|
5676
|
-
import { useEffect as
|
|
6404
|
+
import { useEffect as useEffect28 } from "react";
|
|
5677
6405
|
|
|
5678
6406
|
// src/hooks/usePreload.ts
|
|
5679
|
-
import { useState as useState6, useEffect as
|
|
6407
|
+
import { useState as useState6, useEffect as useEffect27, useContext as useContext25 } from "react";
|
|
5680
6408
|
function usePreload(assets) {
|
|
5681
|
-
const engine =
|
|
6409
|
+
const engine = useContext25(EngineContext);
|
|
5682
6410
|
const [state, setState] = useState6({ progress: assets.length === 0 ? 1 : 0, loaded: assets.length === 0, error: null });
|
|
5683
|
-
|
|
6411
|
+
useEffect27(() => {
|
|
5684
6412
|
if (assets.length === 0) {
|
|
5685
6413
|
setState({ progress: 1, loaded: true, error: null });
|
|
5686
6414
|
return;
|
|
@@ -5708,22 +6436,22 @@ function usePreload(assets) {
|
|
|
5708
6436
|
}
|
|
5709
6437
|
|
|
5710
6438
|
// src/components/AssetLoader.tsx
|
|
5711
|
-
import { Fragment as
|
|
6439
|
+
import { Fragment as Fragment7, jsx as jsx13 } from "react/jsx-runtime";
|
|
5712
6440
|
function AssetLoader({ assets, fallback = null, onError, children }) {
|
|
5713
6441
|
const { loaded, error } = usePreload(assets);
|
|
5714
|
-
|
|
6442
|
+
useEffect28(() => {
|
|
5715
6443
|
if (error && onError) onError(error);
|
|
5716
6444
|
}, [error, onError]);
|
|
5717
6445
|
if (!loaded) {
|
|
5718
|
-
return /* @__PURE__ */
|
|
6446
|
+
return /* @__PURE__ */ jsx13(Fragment7, { children: fallback });
|
|
5719
6447
|
}
|
|
5720
|
-
return /* @__PURE__ */
|
|
6448
|
+
return /* @__PURE__ */ jsx13(Fragment7, { children });
|
|
5721
6449
|
}
|
|
5722
6450
|
|
|
5723
6451
|
// src/hooks/useGame.ts
|
|
5724
|
-
import { useContext as
|
|
6452
|
+
import { useContext as useContext26 } from "react";
|
|
5725
6453
|
function useGame() {
|
|
5726
|
-
const engine =
|
|
6454
|
+
const engine = useContext26(EngineContext);
|
|
5727
6455
|
if (!engine) throw new Error("useGame must be used inside <Game>");
|
|
5728
6456
|
return engine;
|
|
5729
6457
|
}
|
|
@@ -5780,18 +6508,18 @@ function useSnapshot() {
|
|
|
5780
6508
|
}
|
|
5781
6509
|
|
|
5782
6510
|
// src/hooks/useEntity.ts
|
|
5783
|
-
import { useContext as
|
|
6511
|
+
import { useContext as useContext27 } from "react";
|
|
5784
6512
|
function useEntity() {
|
|
5785
|
-
const id =
|
|
6513
|
+
const id = useContext27(EntityContext);
|
|
5786
6514
|
if (id === null) throw new Error("useEntity must be used inside <Entity>");
|
|
5787
6515
|
return id;
|
|
5788
6516
|
}
|
|
5789
6517
|
|
|
5790
6518
|
// src/hooks/useDestroyEntity.ts
|
|
5791
|
-
import { useCallback as useCallback2, useContext as
|
|
6519
|
+
import { useCallback as useCallback2, useContext as useContext28 } from "react";
|
|
5792
6520
|
function useDestroyEntity() {
|
|
5793
|
-
const engine =
|
|
5794
|
-
const entityId =
|
|
6521
|
+
const engine = useContext28(EngineContext);
|
|
6522
|
+
const entityId = useContext28(EntityContext);
|
|
5795
6523
|
if (!engine) throw new Error("useDestroyEntity must be used inside <Game>");
|
|
5796
6524
|
if (entityId === null) throw new Error("useDestroyEntity must be used inside <Entity>");
|
|
5797
6525
|
return useCallback2(() => {
|
|
@@ -5802,9 +6530,9 @@ function useDestroyEntity() {
|
|
|
5802
6530
|
}
|
|
5803
6531
|
|
|
5804
6532
|
// src/hooks/useInput.ts
|
|
5805
|
-
import { useContext as
|
|
6533
|
+
import { useContext as useContext29 } from "react";
|
|
5806
6534
|
function useInput() {
|
|
5807
|
-
const engine =
|
|
6535
|
+
const engine = useContext29(EngineContext);
|
|
5808
6536
|
if (!engine) throw new Error("useInput must be used inside <Game>");
|
|
5809
6537
|
return engine.input;
|
|
5810
6538
|
}
|
|
@@ -5824,25 +6552,25 @@ function useInputMap(bindings) {
|
|
|
5824
6552
|
}
|
|
5825
6553
|
|
|
5826
6554
|
// src/hooks/useEvents.ts
|
|
5827
|
-
import { useContext as
|
|
6555
|
+
import { useContext as useContext30, useEffect as useEffect29, useRef as useRef9 } from "react";
|
|
5828
6556
|
function useEvents() {
|
|
5829
|
-
const engine =
|
|
6557
|
+
const engine = useContext30(EngineContext);
|
|
5830
6558
|
if (!engine) throw new Error("useEvents must be used inside <Game>");
|
|
5831
6559
|
return engine.events;
|
|
5832
6560
|
}
|
|
5833
6561
|
function useEvent(event, handler) {
|
|
5834
6562
|
const events = useEvents();
|
|
5835
|
-
const handlerRef =
|
|
6563
|
+
const handlerRef = useRef9(handler);
|
|
5836
6564
|
handlerRef.current = handler;
|
|
5837
|
-
|
|
6565
|
+
useEffect29(() => {
|
|
5838
6566
|
return events.on(event, (data) => handlerRef.current(data));
|
|
5839
6567
|
}, [events, event]);
|
|
5840
6568
|
}
|
|
5841
6569
|
|
|
5842
6570
|
// src/hooks/useCoordinates.ts
|
|
5843
|
-
import { useCallback as useCallback3, useContext as
|
|
6571
|
+
import { useCallback as useCallback3, useContext as useContext31 } from "react";
|
|
5844
6572
|
function useCoordinates() {
|
|
5845
|
-
const engine =
|
|
6573
|
+
const engine = useContext31(EngineContext);
|
|
5846
6574
|
const worldToScreen = useCallback3((wx, wy) => {
|
|
5847
6575
|
const canvas = engine.canvas;
|
|
5848
6576
|
const camId = engine.ecs.queryOne("Camera2D");
|
|
@@ -5869,9 +6597,9 @@ function useCoordinates() {
|
|
|
5869
6597
|
}
|
|
5870
6598
|
|
|
5871
6599
|
// src/hooks/useInputContext.ts
|
|
5872
|
-
import { useEffect as
|
|
6600
|
+
import { useEffect as useEffect30, useMemo as useMemo4 } from "react";
|
|
5873
6601
|
function useInputContext(ctx) {
|
|
5874
|
-
|
|
6602
|
+
useEffect30(() => {
|
|
5875
6603
|
if (!ctx) return;
|
|
5876
6604
|
globalInputContext.push(ctx);
|
|
5877
6605
|
return () => globalInputContext.pop(ctx);
|
|
@@ -5910,12 +6638,12 @@ function useInputRecorder() {
|
|
|
5910
6638
|
}
|
|
5911
6639
|
|
|
5912
6640
|
// src/hooks/useGamepad.ts
|
|
5913
|
-
import { useEffect as
|
|
6641
|
+
import { useEffect as useEffect31, useRef as useRef10, useState as useState7 } from "react";
|
|
5914
6642
|
var EMPTY_STATE = { connected: false, axes: [], buttons: [] };
|
|
5915
6643
|
function useGamepad(playerIndex = 0) {
|
|
5916
6644
|
const [state, setState] = useState7(EMPTY_STATE);
|
|
5917
|
-
const rafRef =
|
|
5918
|
-
|
|
6645
|
+
const rafRef = useRef10(0);
|
|
6646
|
+
useEffect31(() => {
|
|
5919
6647
|
const poll = () => {
|
|
5920
6648
|
const gp = navigator.getGamepads()[playerIndex];
|
|
5921
6649
|
if (gp) {
|
|
@@ -5936,9 +6664,9 @@ function useGamepad(playerIndex = 0) {
|
|
|
5936
6664
|
}
|
|
5937
6665
|
|
|
5938
6666
|
// src/hooks/usePause.ts
|
|
5939
|
-
import { useContext as
|
|
6667
|
+
import { useContext as useContext32, useState as useState8, useCallback as useCallback4 } from "react";
|
|
5940
6668
|
function usePause() {
|
|
5941
|
-
const engine =
|
|
6669
|
+
const engine = useContext32(EngineContext);
|
|
5942
6670
|
const [paused, setPaused] = useState8(false);
|
|
5943
6671
|
const pause = useCallback4(() => {
|
|
5944
6672
|
engine.loop.pause();
|
|
@@ -5955,10 +6683,75 @@ function usePause() {
|
|
|
5955
6683
|
return { paused, pause, resume, toggle };
|
|
5956
6684
|
}
|
|
5957
6685
|
|
|
6686
|
+
// src/hooks/useProfiler.ts
|
|
6687
|
+
import { useContext as useContext33, useEffect as useEffect32, useRef as useRef11, useState as useState9 } from "react";
|
|
6688
|
+
var EMPTY = {
|
|
6689
|
+
fps: 0,
|
|
6690
|
+
frameTime: 0,
|
|
6691
|
+
entityCount: 0,
|
|
6692
|
+
systemTimings: /* @__PURE__ */ new Map()
|
|
6693
|
+
};
|
|
6694
|
+
function useProfiler() {
|
|
6695
|
+
const engine = useContext33(EngineContext);
|
|
6696
|
+
const [data, setData] = useState9(EMPTY);
|
|
6697
|
+
const frameTimesRef = useRef11([]);
|
|
6698
|
+
const lastUpdateRef = useRef11(0);
|
|
6699
|
+
const prevTimeRef = useRef11(0);
|
|
6700
|
+
useEffect32(() => {
|
|
6701
|
+
if (!engine) return;
|
|
6702
|
+
let rafId;
|
|
6703
|
+
const frameTimes = frameTimesRef.current;
|
|
6704
|
+
const sample = (now) => {
|
|
6705
|
+
if (prevTimeRef.current > 0) {
|
|
6706
|
+
frameTimes.push(now - prevTimeRef.current);
|
|
6707
|
+
}
|
|
6708
|
+
prevTimeRef.current = now;
|
|
6709
|
+
if (now - lastUpdateRef.current >= 500) {
|
|
6710
|
+
lastUpdateRef.current = now;
|
|
6711
|
+
let fps = 0;
|
|
6712
|
+
let avgFrameTime = 0;
|
|
6713
|
+
if (frameTimes.length > 0) {
|
|
6714
|
+
const sum = frameTimes.reduce((a, b) => a + b, 0);
|
|
6715
|
+
avgFrameTime = sum / frameTimes.length;
|
|
6716
|
+
fps = avgFrameTime > 0 ? 1e3 / avgFrameTime : 0;
|
|
6717
|
+
frameTimes.length = 0;
|
|
6718
|
+
}
|
|
6719
|
+
setData({
|
|
6720
|
+
fps: Math.round(fps * 10) / 10,
|
|
6721
|
+
frameTime: Math.round(avgFrameTime * 100) / 100,
|
|
6722
|
+
entityCount: engine.ecs.entityCount,
|
|
6723
|
+
systemTimings: new Map(engine.systemTimings)
|
|
6724
|
+
});
|
|
6725
|
+
}
|
|
6726
|
+
rafId = requestAnimationFrame(sample);
|
|
6727
|
+
};
|
|
6728
|
+
rafId = requestAnimationFrame(sample);
|
|
6729
|
+
return () => {
|
|
6730
|
+
cancelAnimationFrame(rafId);
|
|
6731
|
+
frameTimes.length = 0;
|
|
6732
|
+
prevTimeRef.current = 0;
|
|
6733
|
+
lastUpdateRef.current = 0;
|
|
6734
|
+
};
|
|
6735
|
+
}, [engine]);
|
|
6736
|
+
return data;
|
|
6737
|
+
}
|
|
6738
|
+
|
|
6739
|
+
// src/hooks/usePostProcess.ts
|
|
6740
|
+
import { useEffect as useEffect33 } from "react";
|
|
6741
|
+
function usePostProcess(effect) {
|
|
6742
|
+
const engine = useGame();
|
|
6743
|
+
useEffect33(() => {
|
|
6744
|
+
engine.postProcessStack.add(effect);
|
|
6745
|
+
return () => {
|
|
6746
|
+
engine.postProcessStack.remove(effect);
|
|
6747
|
+
};
|
|
6748
|
+
}, [engine, effect]);
|
|
6749
|
+
}
|
|
6750
|
+
|
|
5958
6751
|
// ../gameplay/src/hooks/useAnimationController.ts
|
|
5959
|
-
import { useState as
|
|
6752
|
+
import { useState as useState10, useCallback as useCallback5 } from "react";
|
|
5960
6753
|
function useAnimationController(states, initial) {
|
|
5961
|
-
const [stateName, setStateName] =
|
|
6754
|
+
const [stateName, setStateName] = useState10(initial);
|
|
5962
6755
|
const setState = useCallback5((next) => {
|
|
5963
6756
|
setStateName((prev) => prev === next ? prev : next);
|
|
5964
6757
|
}, []);
|
|
@@ -6007,19 +6800,19 @@ function useAISteering() {
|
|
|
6007
6800
|
}
|
|
6008
6801
|
|
|
6009
6802
|
// ../gameplay/src/hooks/useDamageZone.ts
|
|
6010
|
-
import { useContext as
|
|
6803
|
+
import { useContext as useContext34 } from "react";
|
|
6011
6804
|
function useDamageZone(damage, opts = {}) {
|
|
6012
|
-
const engine =
|
|
6805
|
+
const engine = useContext34(EngineContext);
|
|
6013
6806
|
useTriggerEnter((other) => {
|
|
6014
6807
|
engine.events.emit(`damage:${other}`, { amount: damage });
|
|
6015
6808
|
}, { tag: opts.tag, layer: opts.layer });
|
|
6016
6809
|
}
|
|
6017
6810
|
|
|
6018
6811
|
// ../gameplay/src/hooks/useDropThrough.ts
|
|
6019
|
-
import { useContext as
|
|
6812
|
+
import { useContext as useContext35, useCallback as useCallback7 } from "react";
|
|
6020
6813
|
function useDropThrough(frames = 8) {
|
|
6021
|
-
const engine =
|
|
6022
|
-
const entityId =
|
|
6814
|
+
const engine = useContext35(EngineContext);
|
|
6815
|
+
const entityId = useContext35(EntityContext);
|
|
6023
6816
|
const dropThrough = useCallback7(() => {
|
|
6024
6817
|
const rb = engine.ecs.getComponent(entityId, "RigidBody");
|
|
6025
6818
|
if (rb) rb.dropThrough = frames;
|
|
@@ -6028,14 +6821,14 @@ function useDropThrough(frames = 8) {
|
|
|
6028
6821
|
}
|
|
6029
6822
|
|
|
6030
6823
|
// ../gameplay/src/hooks/useGameStateMachine.ts
|
|
6031
|
-
import { useState as
|
|
6824
|
+
import { useState as useState11, useRef as useRef12, useCallback as useCallback8, useEffect as useEffect34, useContext as useContext36 } from "react";
|
|
6032
6825
|
function useGameStateMachine(states, initial) {
|
|
6033
|
-
const engine =
|
|
6034
|
-
const [state, setState] =
|
|
6035
|
-
const stateRef =
|
|
6036
|
-
const statesRef =
|
|
6826
|
+
const engine = useContext36(EngineContext);
|
|
6827
|
+
const [state, setState] = useState11(initial);
|
|
6828
|
+
const stateRef = useRef12(initial);
|
|
6829
|
+
const statesRef = useRef12(states);
|
|
6037
6830
|
statesRef.current = states;
|
|
6038
|
-
|
|
6831
|
+
useEffect34(() => {
|
|
6039
6832
|
statesRef.current[initial]?.onEnter?.();
|
|
6040
6833
|
}, []);
|
|
6041
6834
|
const transition = useCallback8((to) => {
|
|
@@ -6046,7 +6839,7 @@ function useGameStateMachine(states, initial) {
|
|
|
6046
6839
|
setState(to);
|
|
6047
6840
|
statesRef.current[to]?.onEnter?.();
|
|
6048
6841
|
}, []);
|
|
6049
|
-
|
|
6842
|
+
useEffect34(() => {
|
|
6050
6843
|
const eid = engine.ecs.createEntity();
|
|
6051
6844
|
engine.ecs.addComponent(eid, createScript((_id, _world, _input, dt) => {
|
|
6052
6845
|
statesRef.current[stateRef.current]?.onUpdate?.(dt);
|
|
@@ -6059,22 +6852,22 @@ function useGameStateMachine(states, initial) {
|
|
|
6059
6852
|
}
|
|
6060
6853
|
|
|
6061
6854
|
// ../gameplay/src/hooks/useHealth.ts
|
|
6062
|
-
import { useRef as
|
|
6855
|
+
import { useRef as useRef13, useEffect as useEffect35, useContext as useContext37, useCallback as useCallback9 } from "react";
|
|
6063
6856
|
function useHealth(maxHp, opts = {}) {
|
|
6064
|
-
const engine =
|
|
6065
|
-
const entityId =
|
|
6066
|
-
const hpRef =
|
|
6067
|
-
const invincibleRef =
|
|
6857
|
+
const engine = useContext37(EngineContext);
|
|
6858
|
+
const entityId = useContext37(EntityContext);
|
|
6859
|
+
const hpRef = useRef13(maxHp);
|
|
6860
|
+
const invincibleRef = useRef13(false);
|
|
6068
6861
|
const iFrameDuration = opts.iFrames ?? 1;
|
|
6069
|
-
const onDeathRef =
|
|
6070
|
-
const onDamageRef =
|
|
6071
|
-
|
|
6862
|
+
const onDeathRef = useRef13(opts.onDeath);
|
|
6863
|
+
const onDamageRef = useRef13(opts.onDamage);
|
|
6864
|
+
useEffect35(() => {
|
|
6072
6865
|
onDeathRef.current = opts.onDeath;
|
|
6073
6866
|
});
|
|
6074
|
-
|
|
6867
|
+
useEffect35(() => {
|
|
6075
6868
|
onDamageRef.current = opts.onDamage;
|
|
6076
6869
|
});
|
|
6077
|
-
const timerRef =
|
|
6870
|
+
const timerRef = useRef13(
|
|
6078
6871
|
createTimer(iFrameDuration, () => {
|
|
6079
6872
|
invincibleRef.current = false;
|
|
6080
6873
|
})
|
|
@@ -6089,11 +6882,11 @@ function useHealth(maxHp, opts = {}) {
|
|
|
6089
6882
|
}
|
|
6090
6883
|
if (hpRef.current <= 0) onDeathRef.current?.();
|
|
6091
6884
|
}, [iFrameDuration]);
|
|
6092
|
-
const takeDamageRef =
|
|
6093
|
-
|
|
6885
|
+
const takeDamageRef = useRef13(takeDamage);
|
|
6886
|
+
useEffect35(() => {
|
|
6094
6887
|
takeDamageRef.current = takeDamage;
|
|
6095
6888
|
}, [takeDamage]);
|
|
6096
|
-
|
|
6889
|
+
useEffect35(() => {
|
|
6097
6890
|
return engine.events.on(`damage:${entityId}`, ({ amount }) => {
|
|
6098
6891
|
takeDamageRef.current(amount);
|
|
6099
6892
|
});
|
|
@@ -6128,10 +6921,10 @@ function useHealth(maxHp, opts = {}) {
|
|
|
6128
6921
|
}
|
|
6129
6922
|
|
|
6130
6923
|
// ../gameplay/src/hooks/useKinematicBody.ts
|
|
6131
|
-
import { useContext as
|
|
6924
|
+
import { useContext as useContext38, useCallback as useCallback10 } from "react";
|
|
6132
6925
|
function useKinematicBody() {
|
|
6133
|
-
const engine =
|
|
6134
|
-
const entityId =
|
|
6926
|
+
const engine = useContext38(EngineContext);
|
|
6927
|
+
const entityId = useContext38(EntityContext);
|
|
6135
6928
|
const moveAndCollide = useCallback10((dx, dy) => {
|
|
6136
6929
|
const transform = engine.ecs.getComponent(entityId, "Transform");
|
|
6137
6930
|
if (!transform) return { dx: 0, dy: 0 };
|
|
@@ -6176,11 +6969,11 @@ function useKinematicBody() {
|
|
|
6176
6969
|
}
|
|
6177
6970
|
|
|
6178
6971
|
// ../gameplay/src/hooks/useLevelTransition.ts
|
|
6179
|
-
import { useState as
|
|
6972
|
+
import { useState as useState12, useRef as useRef14, useCallback as useCallback11 } from "react";
|
|
6180
6973
|
function useLevelTransition(initial) {
|
|
6181
|
-
const [currentLevel, setCurrentLevel] =
|
|
6182
|
-
const [isTransitioning, setIsTransitioning] =
|
|
6183
|
-
const overlayRef =
|
|
6974
|
+
const [currentLevel, setCurrentLevel] = useState12(initial);
|
|
6975
|
+
const [isTransitioning, setIsTransitioning] = useState12(false);
|
|
6976
|
+
const overlayRef = useRef14(null);
|
|
6184
6977
|
const transitionTo = useCallback11((level, opts = {}) => {
|
|
6185
6978
|
const { duration = 0.4, type = "fade" } = opts;
|
|
6186
6979
|
if (type === "instant") {
|
|
@@ -6218,13 +7011,13 @@ function useLevelTransition(initial) {
|
|
|
6218
7011
|
}
|
|
6219
7012
|
|
|
6220
7013
|
// ../gameplay/src/hooks/usePlatformerController.ts
|
|
6221
|
-
import { useContext as
|
|
7014
|
+
import { useContext as useContext39, useEffect as useEffect36 } from "react";
|
|
6222
7015
|
function normalizeKeys(val, defaults) {
|
|
6223
7016
|
if (!val) return defaults;
|
|
6224
7017
|
return Array.isArray(val) ? val : [val];
|
|
6225
7018
|
}
|
|
6226
7019
|
function usePlatformerController(entityId, opts = {}) {
|
|
6227
|
-
const engine =
|
|
7020
|
+
const engine = useContext39(EngineContext);
|
|
6228
7021
|
const {
|
|
6229
7022
|
speed = 200,
|
|
6230
7023
|
jumpForce = -500,
|
|
@@ -6237,7 +7030,7 @@ function usePlatformerController(entityId, opts = {}) {
|
|
|
6237
7030
|
const leftKeys = normalizeKeys(bindings?.left, ["ArrowLeft", "KeyA", "a"]);
|
|
6238
7031
|
const rightKeys = normalizeKeys(bindings?.right, ["ArrowRight", "KeyD", "d"]);
|
|
6239
7032
|
const jumpKeys = normalizeKeys(bindings?.jump, ["Space", "ArrowUp", "KeyW", "w"]);
|
|
6240
|
-
|
|
7033
|
+
useEffect36(() => {
|
|
6241
7034
|
const state = {
|
|
6242
7035
|
coyoteTimer: 0,
|
|
6243
7036
|
jumpBuffer: 0,
|
|
@@ -6301,11 +7094,11 @@ function usePathfinding() {
|
|
|
6301
7094
|
}
|
|
6302
7095
|
|
|
6303
7096
|
// ../gameplay/src/hooks/usePersistedBindings.ts
|
|
6304
|
-
import { useState as
|
|
7097
|
+
import { useState as useState13, useCallback as useCallback13, useMemo as useMemo8, useContext as useContext40 } from "react";
|
|
6305
7098
|
function usePersistedBindings(storageKey, defaults) {
|
|
6306
|
-
const engine =
|
|
7099
|
+
const engine = useContext40(EngineContext);
|
|
6307
7100
|
const input = engine.input;
|
|
6308
|
-
const [bindings, setBindings] =
|
|
7101
|
+
const [bindings, setBindings] = useState13(() => {
|
|
6309
7102
|
try {
|
|
6310
7103
|
const stored = localStorage.getItem(storageKey);
|
|
6311
7104
|
if (stored) return { ...defaults, ...JSON.parse(stored) };
|
|
@@ -6349,9 +7142,9 @@ function usePersistedBindings(storageKey, defaults) {
|
|
|
6349
7142
|
}
|
|
6350
7143
|
|
|
6351
7144
|
// ../gameplay/src/hooks/useRestart.ts
|
|
6352
|
-
import { useState as
|
|
7145
|
+
import { useState as useState14, useCallback as useCallback14 } from "react";
|
|
6353
7146
|
function useRestart() {
|
|
6354
|
-
const [restartKey, setRestartKey] =
|
|
7147
|
+
const [restartKey, setRestartKey] = useState14(0);
|
|
6355
7148
|
const restart = useCallback14(() => {
|
|
6356
7149
|
setRestartKey((k) => k + 1);
|
|
6357
7150
|
}, []);
|
|
@@ -6359,10 +7152,10 @@ function useRestart() {
|
|
|
6359
7152
|
}
|
|
6360
7153
|
|
|
6361
7154
|
// ../gameplay/src/hooks/useSave.ts
|
|
6362
|
-
import { useCallback as useCallback15, useRef as
|
|
7155
|
+
import { useCallback as useCallback15, useRef as useRef15 } from "react";
|
|
6363
7156
|
function useSave(key, defaultValue, opts = {}) {
|
|
6364
7157
|
const version = opts.version ?? 1;
|
|
6365
|
-
const dataRef =
|
|
7158
|
+
const dataRef = useRef15(defaultValue);
|
|
6366
7159
|
const save = useCallback15((value) => {
|
|
6367
7160
|
dataRef.current = value;
|
|
6368
7161
|
const slot = { version, data: value };
|
|
@@ -6408,11 +7201,11 @@ function useSave(key, defaultValue, opts = {}) {
|
|
|
6408
7201
|
}
|
|
6409
7202
|
|
|
6410
7203
|
// ../gameplay/src/hooks/useTopDownMovement.ts
|
|
6411
|
-
import { useContext as
|
|
7204
|
+
import { useContext as useContext41, useEffect as useEffect37 } from "react";
|
|
6412
7205
|
function useTopDownMovement(entityId, opts = {}) {
|
|
6413
|
-
const engine =
|
|
7206
|
+
const engine = useContext41(EngineContext);
|
|
6414
7207
|
const { speed = 200, normalizeDiagonal = true } = opts;
|
|
6415
|
-
|
|
7208
|
+
useEffect37(() => {
|
|
6416
7209
|
const updateFn = (id, world, input) => {
|
|
6417
7210
|
if (!world.hasEntity(id)) return;
|
|
6418
7211
|
const rb = world.getComponent(id, "RigidBody");
|
|
@@ -6437,11 +7230,11 @@ function useTopDownMovement(entityId, opts = {}) {
|
|
|
6437
7230
|
}
|
|
6438
7231
|
|
|
6439
7232
|
// ../gameplay/src/hooks/useDialogue.ts
|
|
6440
|
-
import { useState as
|
|
7233
|
+
import { useState as useState15, useCallback as useCallback16, useRef as useRef16 } from "react";
|
|
6441
7234
|
function useDialogue() {
|
|
6442
|
-
const [active, setActive] =
|
|
6443
|
-
const [currentId, setCurrentId] =
|
|
6444
|
-
const scriptRef =
|
|
7235
|
+
const [active, setActive] = useState15(false);
|
|
7236
|
+
const [currentId, setCurrentId] = useState15(null);
|
|
7237
|
+
const scriptRef = useRef16(null);
|
|
6445
7238
|
const start = useCallback16((script, startId) => {
|
|
6446
7239
|
scriptRef.current = script;
|
|
6447
7240
|
const id = startId ?? Object.keys(script)[0];
|
|
@@ -6485,16 +7278,16 @@ function useDialogue() {
|
|
|
6485
7278
|
}
|
|
6486
7279
|
|
|
6487
7280
|
// ../gameplay/src/hooks/useCutscene.ts
|
|
6488
|
-
import { useState as
|
|
7281
|
+
import { useState as useState16, useCallback as useCallback17, useRef as useRef17, useEffect as useEffect38, useContext as useContext42 } from "react";
|
|
6489
7282
|
function useCutscene() {
|
|
6490
|
-
const engine =
|
|
6491
|
-
const [playing, setPlaying] =
|
|
6492
|
-
const [stepIndex, setStepIndex] =
|
|
6493
|
-
const stepsRef =
|
|
6494
|
-
const timerRef =
|
|
6495
|
-
const idxRef =
|
|
6496
|
-
const playingRef =
|
|
6497
|
-
const entityRef =
|
|
7283
|
+
const engine = useContext42(EngineContext);
|
|
7284
|
+
const [playing, setPlaying] = useState16(false);
|
|
7285
|
+
const [stepIndex, setStepIndex] = useState16(0);
|
|
7286
|
+
const stepsRef = useRef17([]);
|
|
7287
|
+
const timerRef = useRef17(0);
|
|
7288
|
+
const idxRef = useRef17(0);
|
|
7289
|
+
const playingRef = useRef17(false);
|
|
7290
|
+
const entityRef = useRef17(null);
|
|
6498
7291
|
const finish = useCallback17(() => {
|
|
6499
7292
|
playingRef.current = false;
|
|
6500
7293
|
setPlaying(false);
|
|
@@ -6572,7 +7365,7 @@ function useCutscene() {
|
|
|
6572
7365
|
}
|
|
6573
7366
|
finish();
|
|
6574
7367
|
}, [finish]);
|
|
6575
|
-
|
|
7368
|
+
useEffect38(() => {
|
|
6576
7369
|
return () => {
|
|
6577
7370
|
if (entityRef.current !== null && engine.ecs.hasEntity(entityRef.current)) {
|
|
6578
7371
|
engine.ecs.destroyEntity(entityRef.current);
|
|
@@ -6618,8 +7411,112 @@ function useGameStore(key, initialState) {
|
|
|
6618
7411
|
return [state, setState];
|
|
6619
7412
|
}
|
|
6620
7413
|
|
|
7414
|
+
// ../gameplay/src/hooks/useTween.ts
|
|
7415
|
+
import { useRef as useRef18, useCallback as useCallback19, useEffect as useEffect39 } from "react";
|
|
7416
|
+
function useTween(opts) {
|
|
7417
|
+
const rafRef = useRef18(null);
|
|
7418
|
+
const startTimeRef = useRef18(0);
|
|
7419
|
+
const runningRef = useRef18(false);
|
|
7420
|
+
const optsRef = useRef18(opts);
|
|
7421
|
+
optsRef.current = opts;
|
|
7422
|
+
const stop = useCallback19(() => {
|
|
7423
|
+
if (rafRef.current !== null) {
|
|
7424
|
+
cancelAnimationFrame(rafRef.current);
|
|
7425
|
+
rafRef.current = null;
|
|
7426
|
+
}
|
|
7427
|
+
runningRef.current = false;
|
|
7428
|
+
}, []);
|
|
7429
|
+
const start = useCallback19(() => {
|
|
7430
|
+
stop();
|
|
7431
|
+
runningRef.current = true;
|
|
7432
|
+
startTimeRef.current = performance.now();
|
|
7433
|
+
const tick = (now) => {
|
|
7434
|
+
if (!runningRef.current) return;
|
|
7435
|
+
const { from, to, duration, ease, onUpdate, onComplete } = optsRef.current;
|
|
7436
|
+
const easeFn = ease ?? Ease.linear;
|
|
7437
|
+
const elapsed = (now - startTimeRef.current) / 1e3;
|
|
7438
|
+
const t = duration > 0 ? Math.min(elapsed / duration, 1) : 1;
|
|
7439
|
+
const value = from + (to - from) * easeFn(t);
|
|
7440
|
+
onUpdate(value);
|
|
7441
|
+
if (t >= 1) {
|
|
7442
|
+
runningRef.current = false;
|
|
7443
|
+
rafRef.current = null;
|
|
7444
|
+
onComplete?.();
|
|
7445
|
+
} else {
|
|
7446
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
7447
|
+
}
|
|
7448
|
+
};
|
|
7449
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
7450
|
+
}, [stop]);
|
|
7451
|
+
useEffect39(() => {
|
|
7452
|
+
if (opts.autoStart) {
|
|
7453
|
+
start();
|
|
7454
|
+
}
|
|
7455
|
+
}, []);
|
|
7456
|
+
useEffect39(() => {
|
|
7457
|
+
return () => {
|
|
7458
|
+
if (rafRef.current !== null) {
|
|
7459
|
+
cancelAnimationFrame(rafRef.current);
|
|
7460
|
+
rafRef.current = null;
|
|
7461
|
+
}
|
|
7462
|
+
runningRef.current = false;
|
|
7463
|
+
};
|
|
7464
|
+
}, []);
|
|
7465
|
+
return {
|
|
7466
|
+
start,
|
|
7467
|
+
stop,
|
|
7468
|
+
get isRunning() {
|
|
7469
|
+
return runningRef.current;
|
|
7470
|
+
}
|
|
7471
|
+
};
|
|
7472
|
+
}
|
|
7473
|
+
|
|
7474
|
+
// ../gameplay/src/hooks/useObjectPool.ts
|
|
7475
|
+
import { useRef as useRef19, useMemo as useMemo9, useEffect as useEffect40 } from "react";
|
|
7476
|
+
function useObjectPool(factory, reset, initialSize) {
|
|
7477
|
+
const poolRef = useRef19([]);
|
|
7478
|
+
const activeRef = useRef19(0);
|
|
7479
|
+
const factoryRef = useRef19(factory);
|
|
7480
|
+
factoryRef.current = factory;
|
|
7481
|
+
const resetRef = useRef19(reset);
|
|
7482
|
+
resetRef.current = reset;
|
|
7483
|
+
useEffect40(() => {
|
|
7484
|
+
if (initialSize != null && initialSize > 0) {
|
|
7485
|
+
const pool = poolRef.current;
|
|
7486
|
+
for (let i = 0; i < initialSize; i++) {
|
|
7487
|
+
pool.push(factoryRef.current());
|
|
7488
|
+
}
|
|
7489
|
+
}
|
|
7490
|
+
}, []);
|
|
7491
|
+
return useMemo9(() => ({
|
|
7492
|
+
acquire() {
|
|
7493
|
+
activeRef.current++;
|
|
7494
|
+
if (poolRef.current.length > 0) {
|
|
7495
|
+
return poolRef.current.pop();
|
|
7496
|
+
}
|
|
7497
|
+
return factoryRef.current();
|
|
7498
|
+
},
|
|
7499
|
+
release(obj) {
|
|
7500
|
+
resetRef.current(obj);
|
|
7501
|
+
activeRef.current = Math.max(0, activeRef.current - 1);
|
|
7502
|
+
poolRef.current.push(obj);
|
|
7503
|
+
},
|
|
7504
|
+
prewarm(count) {
|
|
7505
|
+
for (let i = 0; i < count; i++) {
|
|
7506
|
+
poolRef.current.push(factoryRef.current());
|
|
7507
|
+
}
|
|
7508
|
+
},
|
|
7509
|
+
get activeCount() {
|
|
7510
|
+
return activeRef.current;
|
|
7511
|
+
},
|
|
7512
|
+
get poolSize() {
|
|
7513
|
+
return poolRef.current.length;
|
|
7514
|
+
}
|
|
7515
|
+
}), []);
|
|
7516
|
+
}
|
|
7517
|
+
|
|
6621
7518
|
// ../../packages/audio/src/useSound.ts
|
|
6622
|
-
import { useEffect as
|
|
7519
|
+
import { useEffect as useEffect41, useRef as useRef20 } from "react";
|
|
6623
7520
|
var _audioCtx = null;
|
|
6624
7521
|
function getAudioCtx() {
|
|
6625
7522
|
if (!_audioCtx) _audioCtx = new AudioContext();
|
|
@@ -6686,13 +7583,13 @@ async function loadBuffer(src) {
|
|
|
6686
7583
|
return buf;
|
|
6687
7584
|
}
|
|
6688
7585
|
function useSound(src, opts = {}) {
|
|
6689
|
-
const bufferRef =
|
|
6690
|
-
const sourceRef =
|
|
6691
|
-
const gainRef =
|
|
6692
|
-
const volRef =
|
|
6693
|
-
const loopRef =
|
|
6694
|
-
const groupRef =
|
|
6695
|
-
|
|
7586
|
+
const bufferRef = useRef20(null);
|
|
7587
|
+
const sourceRef = useRef20(null);
|
|
7588
|
+
const gainRef = useRef20(null);
|
|
7589
|
+
const volRef = useRef20(opts.volume ?? 1);
|
|
7590
|
+
const loopRef = useRef20(opts.loop ?? false);
|
|
7591
|
+
const groupRef = useRef20(opts.group);
|
|
7592
|
+
useEffect41(() => {
|
|
6696
7593
|
let cancelled = false;
|
|
6697
7594
|
loadBuffer(src).then((buf) => {
|
|
6698
7595
|
if (!cancelled) bufferRef.current = buf;
|
|
@@ -6714,7 +7611,7 @@ function useSound(src, opts = {}) {
|
|
|
6714
7611
|
};
|
|
6715
7612
|
}, [src]);
|
|
6716
7613
|
const getDestination = () => groupRef.current ? getGroupGainNode(groupRef.current) : getGroupGainNode("master");
|
|
6717
|
-
const play = () => {
|
|
7614
|
+
const play = (playOpts) => {
|
|
6718
7615
|
if (!bufferRef.current) return;
|
|
6719
7616
|
const ctx = getAudioCtx();
|
|
6720
7617
|
if (ctx.state === "suspended") void ctx.resume();
|
|
@@ -6733,7 +7630,12 @@ function useSound(src, opts = {}) {
|
|
|
6733
7630
|
source.buffer = bufferRef.current;
|
|
6734
7631
|
source.loop = loopRef.current;
|
|
6735
7632
|
source.connect(gain);
|
|
6736
|
-
|
|
7633
|
+
const delay = playOpts?.delay;
|
|
7634
|
+
if (delay && delay > 0) {
|
|
7635
|
+
source.start(ctx.currentTime + delay);
|
|
7636
|
+
} else {
|
|
7637
|
+
source.start();
|
|
7638
|
+
}
|
|
6737
7639
|
source.onended = () => {
|
|
6738
7640
|
sourceRef.current = null;
|
|
6739
7641
|
};
|
|
@@ -6827,8 +7729,38 @@ function createAtlas(names, _columns) {
|
|
|
6827
7729
|
});
|
|
6828
7730
|
return atlas;
|
|
6829
7731
|
}
|
|
7732
|
+
|
|
7733
|
+
// src/utils/animationHelpers.ts
|
|
7734
|
+
function playClip(world, entityId, clipName) {
|
|
7735
|
+
const anim = world.getComponent(entityId, "AnimationState");
|
|
7736
|
+
if (anim) anim.currentClip = clipName;
|
|
7737
|
+
}
|
|
7738
|
+
function setAnimationState(world, entityId, stateName) {
|
|
7739
|
+
const animator = world.getComponent(entityId, "Animator");
|
|
7740
|
+
if (animator) {
|
|
7741
|
+
animator.currentState = stateName;
|
|
7742
|
+
animator._entered = false;
|
|
7743
|
+
}
|
|
7744
|
+
}
|
|
7745
|
+
function setAnimatorParam(world, entityId, name, value) {
|
|
7746
|
+
const animator = world.getComponent(entityId, "Animator");
|
|
7747
|
+
if (animator) animator.params[name] = value;
|
|
7748
|
+
}
|
|
7749
|
+
|
|
7750
|
+
// src/utils/prefab.ts
|
|
7751
|
+
import { memo } from "react";
|
|
7752
|
+
function definePrefab(name, defaults, render) {
|
|
7753
|
+
const component = memo((props) => {
|
|
7754
|
+
const merged = { ...defaults, ...props };
|
|
7755
|
+
return render(merged);
|
|
7756
|
+
});
|
|
7757
|
+
component.displayName = name;
|
|
7758
|
+
return component;
|
|
7759
|
+
}
|
|
6830
7760
|
export {
|
|
7761
|
+
AnimatedSprite,
|
|
6831
7762
|
Animation,
|
|
7763
|
+
Animator,
|
|
6832
7764
|
AssetLoader,
|
|
6833
7765
|
BoxCollider,
|
|
6834
7766
|
Camera2D,
|
|
@@ -6858,30 +7790,42 @@ export {
|
|
|
6858
7790
|
VirtualJoystick,
|
|
6859
7791
|
World,
|
|
6860
7792
|
arrive,
|
|
7793
|
+
chromaticAberrationEffect,
|
|
6861
7794
|
createAtlas,
|
|
6862
7795
|
createCompoundCollider,
|
|
6863
7796
|
createInputMap,
|
|
6864
7797
|
createInputRecorder,
|
|
6865
7798
|
createNineSlice,
|
|
6866
7799
|
createPlayerInput,
|
|
7800
|
+
createPostProcessStack,
|
|
7801
|
+
createRenderLayerManager,
|
|
6867
7802
|
createSprite,
|
|
6868
7803
|
createTag,
|
|
7804
|
+
createTimeline,
|
|
6869
7805
|
createTimer,
|
|
6870
7806
|
createTransform,
|
|
7807
|
+
defaultLayers,
|
|
7808
|
+
defineAnimations,
|
|
6871
7809
|
definePlugin,
|
|
7810
|
+
definePrefab,
|
|
6872
7811
|
duck,
|
|
6873
7812
|
findByTag,
|
|
6874
7813
|
flee,
|
|
6875
7814
|
getGroupVolume,
|
|
6876
7815
|
globalInputContext,
|
|
6877
7816
|
hotReloadPlugin,
|
|
7817
|
+
mergeTileColliders,
|
|
6878
7818
|
overlapBox,
|
|
6879
7819
|
overlapCircle,
|
|
6880
7820
|
patrol,
|
|
7821
|
+
playClip,
|
|
6881
7822
|
preloadManifest,
|
|
6882
7823
|
raycast,
|
|
6883
7824
|
raycastAll,
|
|
7825
|
+
scanlineEffect,
|
|
6884
7826
|
seek,
|
|
7827
|
+
setAnimationState,
|
|
7828
|
+
setAnimatorParam,
|
|
6885
7829
|
setGroupMute,
|
|
6886
7830
|
setGroupVolume,
|
|
6887
7831
|
setMasterVolume,
|
|
@@ -6894,6 +7838,7 @@ export {
|
|
|
6894
7838
|
useCircleEnter,
|
|
6895
7839
|
useCircleExit,
|
|
6896
7840
|
useCircleStay,
|
|
7841
|
+
useCollidingWith,
|
|
6897
7842
|
useCollisionEnter,
|
|
6898
7843
|
useCollisionExit,
|
|
6899
7844
|
useCollisionStay,
|
|
@@ -6918,12 +7863,15 @@ export {
|
|
|
6918
7863
|
useKinematicBody,
|
|
6919
7864
|
useLevelTransition,
|
|
6920
7865
|
useLocalMultiplayer,
|
|
7866
|
+
useObjectPool,
|
|
6921
7867
|
usePathfinding,
|
|
6922
7868
|
usePause,
|
|
6923
7869
|
usePersistedBindings,
|
|
6924
7870
|
usePlatformerController,
|
|
6925
7871
|
usePlayerInput,
|
|
7872
|
+
usePostProcess,
|
|
6926
7873
|
usePreload,
|
|
7874
|
+
useProfiler,
|
|
6927
7875
|
useRestart,
|
|
6928
7876
|
useSave,
|
|
6929
7877
|
useSnapshot,
|
|
@@ -6932,6 +7880,8 @@ export {
|
|
|
6932
7880
|
useTriggerEnter,
|
|
6933
7881
|
useTriggerExit,
|
|
6934
7882
|
useTriggerStay,
|
|
7883
|
+
useTween,
|
|
6935
7884
|
useVirtualInput,
|
|
7885
|
+
vignetteEffect,
|
|
6936
7886
|
wander
|
|
6937
7887
|
};
|