@almadar/ui 5.41.0 → 5.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +329 -123
- package/dist/avl/index.js +329 -123
- package/dist/components/game/organisms/UncontrolledBattleBoard.d.ts +9 -1
- package/dist/components/game/organisms/physics-sim/SimulationCanvas.d.ts +8 -2
- package/dist/components/game/organisms/puzzles/sequencer/SequencerBoard.d.ts +16 -1
- package/dist/components/index.cjs +329 -123
- package/dist/components/index.js +329 -123
- package/dist/hooks/index.cjs +68 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +68 -1
- package/dist/hooks/useRenderInterpolation.d.ts +33 -0
- package/dist/providers/index.cjs +329 -123
- package/dist/providers/index.js +329 -123
- package/dist/runtime/index.cjs +329 -123
- package/dist/runtime/index.js +329 -123
- package/package.json +1 -1
package/dist/providers/index.js
CHANGED
|
@@ -28563,6 +28563,78 @@ var init_GameOverScreen = __esm({
|
|
|
28563
28563
|
GameOverScreen.displayName = "GameOverScreen";
|
|
28564
28564
|
}
|
|
28565
28565
|
});
|
|
28566
|
+
function useRenderInterpolation(options = {}) {
|
|
28567
|
+
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
28568
|
+
const prevRef = useRef(null);
|
|
28569
|
+
const currRef = useRef(null);
|
|
28570
|
+
const rafRef = useRef(null);
|
|
28571
|
+
const onSnapshot = useCallback((entities) => {
|
|
28572
|
+
prevRef.current = currRef.current;
|
|
28573
|
+
currRef.current = { entities, arrivedAt: performance.now() };
|
|
28574
|
+
}, []);
|
|
28575
|
+
const getInterpolated = useCallback((now) => {
|
|
28576
|
+
const out = /* @__PURE__ */ new Map();
|
|
28577
|
+
const curr = currRef.current;
|
|
28578
|
+
if (!curr) return out;
|
|
28579
|
+
const prev = prevRef.current;
|
|
28580
|
+
if (!prev) {
|
|
28581
|
+
for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
|
|
28582
|
+
return out;
|
|
28583
|
+
}
|
|
28584
|
+
const rawAlpha = (now - curr.arrivedAt) / tickIntervalMs;
|
|
28585
|
+
const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
|
|
28586
|
+
const prevMap = /* @__PURE__ */ new Map();
|
|
28587
|
+
for (const e of prev.entities) prevMap.set(e.id, e);
|
|
28588
|
+
for (const c of curr.entities) {
|
|
28589
|
+
const p2 = prevMap.get(c.id);
|
|
28590
|
+
if (!p2) {
|
|
28591
|
+
out.set(c.id, { x: c.x, y: c.y });
|
|
28592
|
+
} else {
|
|
28593
|
+
out.set(c.id, {
|
|
28594
|
+
x: p2.x + (c.x - p2.x) * alpha,
|
|
28595
|
+
y: p2.y + (c.y - p2.y) * alpha
|
|
28596
|
+
});
|
|
28597
|
+
}
|
|
28598
|
+
}
|
|
28599
|
+
return out;
|
|
28600
|
+
}, [tickIntervalMs]);
|
|
28601
|
+
const startLoop = useCallback(
|
|
28602
|
+
(draw) => {
|
|
28603
|
+
let active = true;
|
|
28604
|
+
const loop = () => {
|
|
28605
|
+
if (!active) return;
|
|
28606
|
+
try {
|
|
28607
|
+
draw(getInterpolated(performance.now()));
|
|
28608
|
+
} catch {
|
|
28609
|
+
}
|
|
28610
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28611
|
+
};
|
|
28612
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28613
|
+
return () => {
|
|
28614
|
+
active = false;
|
|
28615
|
+
if (rafRef.current !== null) {
|
|
28616
|
+
cancelAnimationFrame(rafRef.current);
|
|
28617
|
+
rafRef.current = null;
|
|
28618
|
+
}
|
|
28619
|
+
};
|
|
28620
|
+
},
|
|
28621
|
+
[getInterpolated]
|
|
28622
|
+
);
|
|
28623
|
+
useEffect(() => {
|
|
28624
|
+
return () => {
|
|
28625
|
+
if (rafRef.current !== null) {
|
|
28626
|
+
cancelAnimationFrame(rafRef.current);
|
|
28627
|
+
rafRef.current = null;
|
|
28628
|
+
}
|
|
28629
|
+
};
|
|
28630
|
+
}, []);
|
|
28631
|
+
return { onSnapshot, getInterpolated, startLoop };
|
|
28632
|
+
}
|
|
28633
|
+
var init_useRenderInterpolation = __esm({
|
|
28634
|
+
"hooks/useRenderInterpolation.ts"() {
|
|
28635
|
+
"use client";
|
|
28636
|
+
}
|
|
28637
|
+
});
|
|
28566
28638
|
function PlatformerCanvas({
|
|
28567
28639
|
player,
|
|
28568
28640
|
platforms = [
|
|
@@ -28631,8 +28703,43 @@ function PlatformerCanvas({
|
|
|
28631
28703
|
y: 336,
|
|
28632
28704
|
width: 32,
|
|
28633
28705
|
height: 48,
|
|
28706
|
+
vx: 0,
|
|
28707
|
+
vy: 0,
|
|
28708
|
+
grounded: true,
|
|
28634
28709
|
facingRight: true
|
|
28635
28710
|
};
|
|
28711
|
+
const playerRef = useRef(resolvedPlayer);
|
|
28712
|
+
playerRef.current = resolvedPlayer;
|
|
28713
|
+
const interp = useRenderInterpolation();
|
|
28714
|
+
useEffect(() => {
|
|
28715
|
+
interp.onSnapshot([{ id: "player", x: resolvedPlayer.x, y: resolvedPlayer.y }]);
|
|
28716
|
+
}, [resolvedPlayer.x, resolvedPlayer.y]);
|
|
28717
|
+
const propsRef = useRef({
|
|
28718
|
+
platforms,
|
|
28719
|
+
worldWidth,
|
|
28720
|
+
worldHeight,
|
|
28721
|
+
canvasWidth,
|
|
28722
|
+
canvasHeight,
|
|
28723
|
+
followCamera,
|
|
28724
|
+
bgColor,
|
|
28725
|
+
playerSprite,
|
|
28726
|
+
tileSprites,
|
|
28727
|
+
backgroundImage,
|
|
28728
|
+
assetBaseUrl
|
|
28729
|
+
});
|
|
28730
|
+
propsRef.current = {
|
|
28731
|
+
platforms,
|
|
28732
|
+
worldWidth,
|
|
28733
|
+
worldHeight,
|
|
28734
|
+
canvasWidth,
|
|
28735
|
+
canvasHeight,
|
|
28736
|
+
followCamera,
|
|
28737
|
+
bgColor,
|
|
28738
|
+
playerSprite,
|
|
28739
|
+
tileSprites,
|
|
28740
|
+
backgroundImage,
|
|
28741
|
+
assetBaseUrl
|
|
28742
|
+
};
|
|
28636
28743
|
const handleKeyDown = useCallback((e) => {
|
|
28637
28744
|
if (keysRef.current.has(e.code)) return;
|
|
28638
28745
|
keysRef.current.add(e.code);
|
|
@@ -28681,124 +28788,149 @@ function PlatformerCanvas({
|
|
|
28681
28788
|
canvas.width = canvasWidth * dpr;
|
|
28682
28789
|
canvas.height = canvasHeight * dpr;
|
|
28683
28790
|
ctx.scale(dpr, dpr);
|
|
28684
|
-
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
|
|
28688
|
-
|
|
28689
|
-
|
|
28690
|
-
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
const px = plat.x - camX;
|
|
28720
|
-
const py = plat.y - camY;
|
|
28721
|
-
const platType = plat.type ?? "ground";
|
|
28722
|
-
const spriteUrl = tileSprites?.[platType];
|
|
28723
|
-
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28724
|
-
if (tileImg) {
|
|
28725
|
-
const tileW = tileImg.naturalWidth;
|
|
28726
|
-
const tileH = tileImg.naturalHeight;
|
|
28727
|
-
const scaleH = plat.height / tileH;
|
|
28728
|
-
const scaledW = tileW * scaleH;
|
|
28729
|
-
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28730
|
-
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28731
|
-
const srcW = drawW / scaleH;
|
|
28732
|
-
ctx.drawImage(tileImg, 0, 0, srcW, tileH, px + tx, py, drawW, plat.height);
|
|
28733
|
-
}
|
|
28791
|
+
}, [canvasWidth, canvasHeight]);
|
|
28792
|
+
useEffect(() => {
|
|
28793
|
+
const drawFrame = (positions) => {
|
|
28794
|
+
const canvas = canvasRef.current;
|
|
28795
|
+
if (!canvas) return;
|
|
28796
|
+
const ctx = canvas.getContext("2d");
|
|
28797
|
+
if (!ctx) return;
|
|
28798
|
+
const {
|
|
28799
|
+
platforms: plats,
|
|
28800
|
+
worldWidth: ww,
|
|
28801
|
+
worldHeight: wh,
|
|
28802
|
+
canvasWidth: cw,
|
|
28803
|
+
canvasHeight: ch,
|
|
28804
|
+
followCamera: fc,
|
|
28805
|
+
bgColor: bg,
|
|
28806
|
+
playerSprite: pSprite,
|
|
28807
|
+
tileSprites: tSprites,
|
|
28808
|
+
backgroundImage: bgImg
|
|
28809
|
+
} = propsRef.current;
|
|
28810
|
+
const auth = playerRef.current;
|
|
28811
|
+
const interped = positions.get("player");
|
|
28812
|
+
const px = interped?.x ?? auth.x;
|
|
28813
|
+
const py = interped?.y ?? auth.y;
|
|
28814
|
+
let camX = 0;
|
|
28815
|
+
let camY = 0;
|
|
28816
|
+
if (fc) {
|
|
28817
|
+
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
28818
|
+
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
28819
|
+
}
|
|
28820
|
+
const bgImage = bgImg ? loadImage(bgImg) : null;
|
|
28821
|
+
if (bgImage) {
|
|
28822
|
+
ctx.drawImage(bgImage, 0, 0, cw, ch);
|
|
28823
|
+
} else if (bg) {
|
|
28824
|
+
ctx.fillStyle = bg;
|
|
28825
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28734
28826
|
} else {
|
|
28735
|
-
const
|
|
28736
|
-
|
|
28737
|
-
|
|
28738
|
-
ctx.fillStyle =
|
|
28739
|
-
ctx.fillRect(
|
|
28740
|
-
|
|
28741
|
-
|
|
28742
|
-
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28827
|
+
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
28828
|
+
grad.addColorStop(0, SKY_GRADIENT_TOP);
|
|
28829
|
+
grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
|
|
28830
|
+
ctx.fillStyle = grad;
|
|
28831
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28832
|
+
}
|
|
28833
|
+
ctx.strokeStyle = GRID_COLOR;
|
|
28834
|
+
ctx.lineWidth = 1;
|
|
28835
|
+
const gridSize = 32;
|
|
28836
|
+
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
28837
|
+
ctx.beginPath();
|
|
28838
|
+
ctx.moveTo(gx, 0);
|
|
28839
|
+
ctx.lineTo(gx, ch);
|
|
28840
|
+
ctx.stroke();
|
|
28841
|
+
}
|
|
28842
|
+
for (let gy = -camY % gridSize; gy < ch; gy += gridSize) {
|
|
28843
|
+
ctx.beginPath();
|
|
28844
|
+
ctx.moveTo(0, gy);
|
|
28845
|
+
ctx.lineTo(cw, gy);
|
|
28846
|
+
ctx.stroke();
|
|
28847
|
+
}
|
|
28848
|
+
for (const plat of plats) {
|
|
28849
|
+
const platX = plat.x - camX;
|
|
28850
|
+
const platY = plat.y - camY;
|
|
28851
|
+
const platType = plat.type ?? "ground";
|
|
28852
|
+
const spriteUrl = tSprites?.[platType];
|
|
28853
|
+
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28854
|
+
if (tileImg) {
|
|
28855
|
+
const tileW = tileImg.naturalWidth;
|
|
28856
|
+
const tileH = tileImg.naturalHeight;
|
|
28857
|
+
const scaleH = plat.height / tileH;
|
|
28858
|
+
const scaledW = tileW * scaleH;
|
|
28859
|
+
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28860
|
+
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28861
|
+
const srcW = drawW / scaleH;
|
|
28862
|
+
ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
28863
|
+
}
|
|
28864
|
+
} else {
|
|
28865
|
+
const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
|
|
28866
|
+
ctx.fillStyle = color;
|
|
28867
|
+
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
28868
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
|
|
28869
|
+
ctx.fillRect(platX, platY, plat.width, 3);
|
|
28870
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
|
28871
|
+
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
28872
|
+
if (platType === "hazard") {
|
|
28873
|
+
ctx.strokeStyle = "#e74c3c";
|
|
28874
|
+
ctx.lineWidth = 2;
|
|
28875
|
+
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
28876
|
+
ctx.beginPath();
|
|
28877
|
+
ctx.moveTo(sx, platY);
|
|
28878
|
+
ctx.lineTo(sx + 6, platY + plat.height);
|
|
28879
|
+
ctx.stroke();
|
|
28880
|
+
}
|
|
28881
|
+
}
|
|
28882
|
+
if (platType === "goal") {
|
|
28883
|
+
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28746
28884
|
ctx.beginPath();
|
|
28747
|
-
ctx.
|
|
28748
|
-
ctx.
|
|
28749
|
-
ctx.stroke();
|
|
28885
|
+
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
28886
|
+
ctx.fill();
|
|
28750
28887
|
}
|
|
28751
28888
|
}
|
|
28752
|
-
if (platType === "goal") {
|
|
28753
|
-
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28754
|
-
ctx.beginPath();
|
|
28755
|
-
ctx.arc(px + plat.width / 2, py - 10, 8, 0, Math.PI * 2);
|
|
28756
|
-
ctx.fill();
|
|
28757
|
-
}
|
|
28758
28889
|
}
|
|
28759
|
-
|
|
28760
|
-
|
|
28761
|
-
|
|
28762
|
-
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28768
|
-
|
|
28769
|
-
|
|
28770
|
-
|
|
28771
|
-
|
|
28890
|
+
const pw = auth.width ?? 24;
|
|
28891
|
+
const ph = auth.height ?? 32;
|
|
28892
|
+
const ppx = px - camX;
|
|
28893
|
+
const ppy = py - camY;
|
|
28894
|
+
const facingRight = auth.facingRight ?? true;
|
|
28895
|
+
const playerImg = pSprite ? loadImage(pSprite) : null;
|
|
28896
|
+
if (playerImg) {
|
|
28897
|
+
ctx.save();
|
|
28898
|
+
if (!facingRight) {
|
|
28899
|
+
ctx.translate(ppx + pw, ppy);
|
|
28900
|
+
ctx.scale(-1, 1);
|
|
28901
|
+
ctx.drawImage(playerImg, 0, 0, pw, ph);
|
|
28902
|
+
} else {
|
|
28903
|
+
ctx.drawImage(playerImg, ppx, ppy, pw, ph);
|
|
28904
|
+
}
|
|
28905
|
+
ctx.restore();
|
|
28772
28906
|
} else {
|
|
28773
|
-
ctx.
|
|
28907
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
28908
|
+
const radius = Math.min(pw, ph) * 0.25;
|
|
28909
|
+
ctx.beginPath();
|
|
28910
|
+
ctx.moveTo(ppx + radius, ppy);
|
|
28911
|
+
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28912
|
+
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28913
|
+
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28914
|
+
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28915
|
+
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28916
|
+
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28917
|
+
ctx.lineTo(ppx, ppy + radius);
|
|
28918
|
+
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28919
|
+
ctx.fill();
|
|
28920
|
+
const eyeY = ppy + ph * 0.3;
|
|
28921
|
+
const eyeSize = 3;
|
|
28922
|
+
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28923
|
+
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28924
|
+
ctx.beginPath();
|
|
28925
|
+
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28926
|
+
ctx.fill();
|
|
28927
|
+
ctx.beginPath();
|
|
28928
|
+
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28929
|
+
ctx.fill();
|
|
28774
28930
|
}
|
|
28775
|
-
|
|
28776
|
-
|
|
28777
|
-
|
|
28778
|
-
const radius = Math.min(pw, ph) * 0.25;
|
|
28779
|
-
ctx.beginPath();
|
|
28780
|
-
ctx.moveTo(ppx + radius, ppy);
|
|
28781
|
-
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28782
|
-
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28783
|
-
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28784
|
-
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28785
|
-
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28786
|
-
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28787
|
-
ctx.lineTo(ppx, ppy + radius);
|
|
28788
|
-
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28789
|
-
ctx.fill();
|
|
28790
|
-
const eyeY = ppy + ph * 0.3;
|
|
28791
|
-
const eyeSize = 3;
|
|
28792
|
-
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28793
|
-
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28794
|
-
ctx.beginPath();
|
|
28795
|
-
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28796
|
-
ctx.fill();
|
|
28797
|
-
ctx.beginPath();
|
|
28798
|
-
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28799
|
-
ctx.fill();
|
|
28800
|
-
}
|
|
28801
|
-
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
28931
|
+
};
|
|
28932
|
+
return interp.startLoop(drawFrame);
|
|
28933
|
+
}, [interp.startLoop, loadImage]);
|
|
28802
28934
|
return /* @__PURE__ */ jsx(
|
|
28803
28935
|
"canvas",
|
|
28804
28936
|
{
|
|
@@ -28816,6 +28948,7 @@ var init_PlatformerCanvas = __esm({
|
|
|
28816
28948
|
init_cn();
|
|
28817
28949
|
init_useEventBus();
|
|
28818
28950
|
init_verificationRegistry();
|
|
28951
|
+
init_useRenderInterpolation();
|
|
28819
28952
|
PLATFORM_COLORS = {
|
|
28820
28953
|
ground: "#4a7c59",
|
|
28821
28954
|
platform: "#7c6b4a",
|
|
@@ -29198,13 +29331,13 @@ var init_MapView = __esm({
|
|
|
29198
29331
|
shadowSize: [41, 41]
|
|
29199
29332
|
});
|
|
29200
29333
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29201
|
-
const { useEffect:
|
|
29334
|
+
const { useEffect: useEffect74, useRef: useRef69, useCallback: useCallback112, useState: useState104 } = React83__default;
|
|
29202
29335
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
29203
29336
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
29204
29337
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
29205
29338
|
const map = useMap();
|
|
29206
|
-
const prevRef =
|
|
29207
|
-
|
|
29339
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
29340
|
+
useEffect74(() => {
|
|
29208
29341
|
const prev = prevRef.current;
|
|
29209
29342
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
29210
29343
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -29215,7 +29348,7 @@ var init_MapView = __esm({
|
|
|
29215
29348
|
}
|
|
29216
29349
|
function MapClickHandler({ onMapClick }) {
|
|
29217
29350
|
const map = useMap();
|
|
29218
|
-
|
|
29351
|
+
useEffect74(() => {
|
|
29219
29352
|
if (!onMapClick) return;
|
|
29220
29353
|
const handler = (e) => {
|
|
29221
29354
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -29244,7 +29377,7 @@ var init_MapView = __esm({
|
|
|
29244
29377
|
}) {
|
|
29245
29378
|
const eventBus = useEventBus2();
|
|
29246
29379
|
const [clickedPosition, setClickedPosition] = useState104(null);
|
|
29247
|
-
const handleMapClick =
|
|
29380
|
+
const handleMapClick = useCallback112((lat, lng) => {
|
|
29248
29381
|
if (showClickedPin) {
|
|
29249
29382
|
setClickedPosition({ lat, lng });
|
|
29250
29383
|
}
|
|
@@ -29253,7 +29386,7 @@ var init_MapView = __esm({
|
|
|
29253
29386
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
29254
29387
|
}
|
|
29255
29388
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
29256
|
-
const handleMarkerClick =
|
|
29389
|
+
const handleMarkerClick = useCallback112((marker) => {
|
|
29257
29390
|
onMarkerClick?.(marker);
|
|
29258
29391
|
if (markerClickEvent) {
|
|
29259
29392
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -44738,6 +44871,10 @@ function SequencerBoard({
|
|
|
44738
44871
|
stepDurationMs = 1e3,
|
|
44739
44872
|
playEvent,
|
|
44740
44873
|
completeEvent,
|
|
44874
|
+
placeEvent,
|
|
44875
|
+
removeEvent,
|
|
44876
|
+
checkEvent,
|
|
44877
|
+
playAgainEvent,
|
|
44741
44878
|
className
|
|
44742
44879
|
}) {
|
|
44743
44880
|
const { emit } = useEventBus();
|
|
@@ -44773,7 +44910,8 @@ function SequencerBoard({
|
|
|
44773
44910
|
return next;
|
|
44774
44911
|
});
|
|
44775
44912
|
emit("UI:PLAY_SOUND", { key: "drop_slot" });
|
|
44776
|
-
|
|
44913
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotIndex: index, actionId: item.id });
|
|
44914
|
+
}, [emit, placeEvent]);
|
|
44777
44915
|
const handleSlotRemove = useCallback((index) => {
|
|
44778
44916
|
setSlots((prev) => {
|
|
44779
44917
|
const next = [...prev];
|
|
@@ -44786,7 +44924,8 @@ function SequencerBoard({
|
|
|
44786
44924
|
return next;
|
|
44787
44925
|
});
|
|
44788
44926
|
emit("UI:PLAY_SOUND", { key: "back" });
|
|
44789
|
-
|
|
44927
|
+
if (removeEvent) emit(`UI:${removeEvent}`, { slotIndex: index });
|
|
44928
|
+
}, [emit, removeEvent]);
|
|
44790
44929
|
const handleReset = useCallback(() => {
|
|
44791
44930
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44792
44931
|
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
@@ -44794,7 +44933,8 @@ function SequencerBoard({
|
|
|
44794
44933
|
setCurrentStep(-1);
|
|
44795
44934
|
setAttempts(0);
|
|
44796
44935
|
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
44797
|
-
|
|
44936
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
44937
|
+
}, [maxSlots, playAgainEvent, emit]);
|
|
44798
44938
|
const filledSlots = slots.filter((s) => !!s);
|
|
44799
44939
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
44800
44940
|
const handlePlay = useCallback(() => {
|
|
@@ -44816,6 +44956,7 @@ function SequencerBoard({
|
|
|
44816
44956
|
const success = solutions.some(
|
|
44817
44957
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
44818
44958
|
);
|
|
44959
|
+
if (checkEvent) emit(`UI:${checkEvent}`, { sequence: playerIds });
|
|
44819
44960
|
if (success) {
|
|
44820
44961
|
setPlayState("success");
|
|
44821
44962
|
setCurrentStep(-1);
|
|
@@ -44843,7 +44984,7 @@ function SequencerBoard({
|
|
|
44843
44984
|
}
|
|
44844
44985
|
};
|
|
44845
44986
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
44846
|
-
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
44987
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, checkEvent, emit]);
|
|
44847
44988
|
const machine = {
|
|
44848
44989
|
name: str(resolved?.title),
|
|
44849
44990
|
description: str(resolved?.description),
|
|
@@ -45098,11 +45239,13 @@ function SimulationCanvas({
|
|
|
45098
45239
|
height = 400,
|
|
45099
45240
|
running,
|
|
45100
45241
|
speed = 1,
|
|
45242
|
+
bodies: externalBodies,
|
|
45101
45243
|
className
|
|
45102
45244
|
}) {
|
|
45103
45245
|
const preset = useMemo(() => resolvePreset(presetProp), [presetProp]);
|
|
45104
45246
|
const canvasRef = useRef(null);
|
|
45105
45247
|
const bodiesRef = useRef(structuredClone(preset.bodies));
|
|
45248
|
+
const interp = useRenderInterpolation();
|
|
45106
45249
|
useEffect(() => {
|
|
45107
45250
|
bodiesRef.current = structuredClone(preset.bodies);
|
|
45108
45251
|
}, [preset]);
|
|
@@ -45200,6 +45343,67 @@ function SimulationCanvas({
|
|
|
45200
45343
|
}
|
|
45201
45344
|
}, [width, height, preset]);
|
|
45202
45345
|
useEffect(() => {
|
|
45346
|
+
if (!externalBodies) return;
|
|
45347
|
+
interp.onSnapshot(externalBodies.map((b) => ({ id: b.id, x: b.x, y: b.y })));
|
|
45348
|
+
}, [externalBodies]);
|
|
45349
|
+
const presetRef = useRef(preset);
|
|
45350
|
+
presetRef.current = preset;
|
|
45351
|
+
const widthRef = useRef(width);
|
|
45352
|
+
widthRef.current = width;
|
|
45353
|
+
const heightRef = useRef(height);
|
|
45354
|
+
heightRef.current = height;
|
|
45355
|
+
useEffect(() => {
|
|
45356
|
+
if (!externalBodies) return;
|
|
45357
|
+
const drawInterpolated = (positions) => {
|
|
45358
|
+
const canvas = canvasRef.current;
|
|
45359
|
+
if (!canvas) return;
|
|
45360
|
+
const ctx = canvas.getContext("2d");
|
|
45361
|
+
if (!ctx) return;
|
|
45362
|
+
const bodies = bodiesRef.current;
|
|
45363
|
+
const p2 = presetRef.current;
|
|
45364
|
+
const w = widthRef.current;
|
|
45365
|
+
const h = heightRef.current;
|
|
45366
|
+
ctx.clearRect(0, 0, w, h);
|
|
45367
|
+
ctx.fillStyle = p2.backgroundColor ?? "#1a1a2e";
|
|
45368
|
+
ctx.fillRect(0, 0, w, h);
|
|
45369
|
+
if (p2.constraints) {
|
|
45370
|
+
for (const c of p2.constraints) {
|
|
45371
|
+
const a = bodies[c.bodyA];
|
|
45372
|
+
const b = bodies[c.bodyB];
|
|
45373
|
+
if (a && b) {
|
|
45374
|
+
const aPos = positions.get(a.id) ?? a;
|
|
45375
|
+
const bPos = positions.get(b.id) ?? b;
|
|
45376
|
+
ctx.beginPath();
|
|
45377
|
+
ctx.moveTo(aPos.x, aPos.y);
|
|
45378
|
+
ctx.lineTo(bPos.x, bPos.y);
|
|
45379
|
+
ctx.strokeStyle = "#533483";
|
|
45380
|
+
ctx.lineWidth = 1;
|
|
45381
|
+
ctx.setLineDash([4, 4]);
|
|
45382
|
+
ctx.stroke();
|
|
45383
|
+
ctx.setLineDash([]);
|
|
45384
|
+
}
|
|
45385
|
+
}
|
|
45386
|
+
}
|
|
45387
|
+
for (const body of bodies) {
|
|
45388
|
+
const pos = positions.get(body.id) ?? body;
|
|
45389
|
+
ctx.beginPath();
|
|
45390
|
+
ctx.arc(pos.x, pos.y, body.radius, 0, Math.PI * 2);
|
|
45391
|
+
ctx.fillStyle = body.color ?? "#e94560";
|
|
45392
|
+
ctx.fill();
|
|
45393
|
+
if (p2.showVelocity) {
|
|
45394
|
+
ctx.beginPath();
|
|
45395
|
+
ctx.moveTo(pos.x, pos.y);
|
|
45396
|
+
ctx.lineTo(pos.x + body.vx * 0.1, pos.y + body.vy * 0.1);
|
|
45397
|
+
ctx.strokeStyle = "#16213e";
|
|
45398
|
+
ctx.lineWidth = 2;
|
|
45399
|
+
ctx.stroke();
|
|
45400
|
+
}
|
|
45401
|
+
}
|
|
45402
|
+
};
|
|
45403
|
+
return interp.startLoop(drawInterpolated);
|
|
45404
|
+
}, [externalBodies !== void 0, interp.startLoop]);
|
|
45405
|
+
useEffect(() => {
|
|
45406
|
+
if (externalBodies !== void 0) return;
|
|
45203
45407
|
if (!running) return;
|
|
45204
45408
|
let raf;
|
|
45205
45409
|
const loop = () => {
|
|
@@ -45209,10 +45413,11 @@ function SimulationCanvas({
|
|
|
45209
45413
|
};
|
|
45210
45414
|
raf = requestAnimationFrame(loop);
|
|
45211
45415
|
return () => cancelAnimationFrame(raf);
|
|
45212
|
-
}, [running, step, draw]);
|
|
45416
|
+
}, [running, step, draw, externalBodies]);
|
|
45213
45417
|
useEffect(() => {
|
|
45418
|
+
if (externalBodies !== void 0) return;
|
|
45214
45419
|
draw();
|
|
45215
|
-
}, [draw]);
|
|
45420
|
+
}, [draw, externalBodies]);
|
|
45216
45421
|
useEffect(() => {
|
|
45217
45422
|
if (typeof window === "undefined") return;
|
|
45218
45423
|
const canvas = canvasRef.current;
|
|
@@ -45238,6 +45443,7 @@ var init_SimulationCanvas = __esm({
|
|
|
45238
45443
|
init_atoms2();
|
|
45239
45444
|
init_verificationRegistry();
|
|
45240
45445
|
init_presets();
|
|
45446
|
+
init_useRenderInterpolation();
|
|
45241
45447
|
SimulationCanvas.displayName = "SimulationCanvas";
|
|
45242
45448
|
}
|
|
45243
45449
|
});
|