@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
|
@@ -28834,6 +28834,78 @@ var init_GameOverScreen = __esm({
|
|
|
28834
28834
|
GameOverScreen.displayName = "GameOverScreen";
|
|
28835
28835
|
}
|
|
28836
28836
|
});
|
|
28837
|
+
function useRenderInterpolation(options = {}) {
|
|
28838
|
+
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
28839
|
+
const prevRef = React77.useRef(null);
|
|
28840
|
+
const currRef = React77.useRef(null);
|
|
28841
|
+
const rafRef = React77.useRef(null);
|
|
28842
|
+
const onSnapshot = React77.useCallback((entities) => {
|
|
28843
|
+
prevRef.current = currRef.current;
|
|
28844
|
+
currRef.current = { entities, arrivedAt: performance.now() };
|
|
28845
|
+
}, []);
|
|
28846
|
+
const getInterpolated = React77.useCallback((now) => {
|
|
28847
|
+
const out = /* @__PURE__ */ new Map();
|
|
28848
|
+
const curr = currRef.current;
|
|
28849
|
+
if (!curr) return out;
|
|
28850
|
+
const prev = prevRef.current;
|
|
28851
|
+
if (!prev) {
|
|
28852
|
+
for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
|
|
28853
|
+
return out;
|
|
28854
|
+
}
|
|
28855
|
+
const rawAlpha = (now - curr.arrivedAt) / tickIntervalMs;
|
|
28856
|
+
const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
|
|
28857
|
+
const prevMap = /* @__PURE__ */ new Map();
|
|
28858
|
+
for (const e of prev.entities) prevMap.set(e.id, e);
|
|
28859
|
+
for (const c of curr.entities) {
|
|
28860
|
+
const p2 = prevMap.get(c.id);
|
|
28861
|
+
if (!p2) {
|
|
28862
|
+
out.set(c.id, { x: c.x, y: c.y });
|
|
28863
|
+
} else {
|
|
28864
|
+
out.set(c.id, {
|
|
28865
|
+
x: p2.x + (c.x - p2.x) * alpha,
|
|
28866
|
+
y: p2.y + (c.y - p2.y) * alpha
|
|
28867
|
+
});
|
|
28868
|
+
}
|
|
28869
|
+
}
|
|
28870
|
+
return out;
|
|
28871
|
+
}, [tickIntervalMs]);
|
|
28872
|
+
const startLoop = React77.useCallback(
|
|
28873
|
+
(draw) => {
|
|
28874
|
+
let active = true;
|
|
28875
|
+
const loop = () => {
|
|
28876
|
+
if (!active) return;
|
|
28877
|
+
try {
|
|
28878
|
+
draw(getInterpolated(performance.now()));
|
|
28879
|
+
} catch {
|
|
28880
|
+
}
|
|
28881
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28882
|
+
};
|
|
28883
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28884
|
+
return () => {
|
|
28885
|
+
active = false;
|
|
28886
|
+
if (rafRef.current !== null) {
|
|
28887
|
+
cancelAnimationFrame(rafRef.current);
|
|
28888
|
+
rafRef.current = null;
|
|
28889
|
+
}
|
|
28890
|
+
};
|
|
28891
|
+
},
|
|
28892
|
+
[getInterpolated]
|
|
28893
|
+
);
|
|
28894
|
+
React77.useEffect(() => {
|
|
28895
|
+
return () => {
|
|
28896
|
+
if (rafRef.current !== null) {
|
|
28897
|
+
cancelAnimationFrame(rafRef.current);
|
|
28898
|
+
rafRef.current = null;
|
|
28899
|
+
}
|
|
28900
|
+
};
|
|
28901
|
+
}, []);
|
|
28902
|
+
return { onSnapshot, getInterpolated, startLoop };
|
|
28903
|
+
}
|
|
28904
|
+
var init_useRenderInterpolation = __esm({
|
|
28905
|
+
"hooks/useRenderInterpolation.ts"() {
|
|
28906
|
+
"use client";
|
|
28907
|
+
}
|
|
28908
|
+
});
|
|
28837
28909
|
function PlatformerCanvas({
|
|
28838
28910
|
player,
|
|
28839
28911
|
platforms = [
|
|
@@ -28902,8 +28974,43 @@ function PlatformerCanvas({
|
|
|
28902
28974
|
y: 336,
|
|
28903
28975
|
width: 32,
|
|
28904
28976
|
height: 48,
|
|
28977
|
+
vx: 0,
|
|
28978
|
+
vy: 0,
|
|
28979
|
+
grounded: true,
|
|
28905
28980
|
facingRight: true
|
|
28906
28981
|
};
|
|
28982
|
+
const playerRef = React77.useRef(resolvedPlayer);
|
|
28983
|
+
playerRef.current = resolvedPlayer;
|
|
28984
|
+
const interp = useRenderInterpolation();
|
|
28985
|
+
React77.useEffect(() => {
|
|
28986
|
+
interp.onSnapshot([{ id: "player", x: resolvedPlayer.x, y: resolvedPlayer.y }]);
|
|
28987
|
+
}, [resolvedPlayer.x, resolvedPlayer.y]);
|
|
28988
|
+
const propsRef = React77.useRef({
|
|
28989
|
+
platforms,
|
|
28990
|
+
worldWidth,
|
|
28991
|
+
worldHeight,
|
|
28992
|
+
canvasWidth,
|
|
28993
|
+
canvasHeight,
|
|
28994
|
+
followCamera,
|
|
28995
|
+
bgColor,
|
|
28996
|
+
playerSprite,
|
|
28997
|
+
tileSprites,
|
|
28998
|
+
backgroundImage,
|
|
28999
|
+
assetBaseUrl
|
|
29000
|
+
});
|
|
29001
|
+
propsRef.current = {
|
|
29002
|
+
platforms,
|
|
29003
|
+
worldWidth,
|
|
29004
|
+
worldHeight,
|
|
29005
|
+
canvasWidth,
|
|
29006
|
+
canvasHeight,
|
|
29007
|
+
followCamera,
|
|
29008
|
+
bgColor,
|
|
29009
|
+
playerSprite,
|
|
29010
|
+
tileSprites,
|
|
29011
|
+
backgroundImage,
|
|
29012
|
+
assetBaseUrl
|
|
29013
|
+
};
|
|
28907
29014
|
const handleKeyDown = React77.useCallback((e) => {
|
|
28908
29015
|
if (keysRef.current.has(e.code)) return;
|
|
28909
29016
|
keysRef.current.add(e.code);
|
|
@@ -28952,124 +29059,149 @@ function PlatformerCanvas({
|
|
|
28952
29059
|
canvas.width = canvasWidth * dpr;
|
|
28953
29060
|
canvas.height = canvasHeight * dpr;
|
|
28954
29061
|
ctx.scale(dpr, dpr);
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
|
|
28961
|
-
|
|
28962
|
-
|
|
28963
|
-
|
|
28964
|
-
|
|
28965
|
-
|
|
28966
|
-
|
|
28967
|
-
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
|
|
28971
|
-
|
|
28972
|
-
|
|
28973
|
-
|
|
28974
|
-
|
|
28975
|
-
|
|
28976
|
-
|
|
28977
|
-
|
|
28978
|
-
|
|
28979
|
-
|
|
28980
|
-
|
|
28981
|
-
|
|
28982
|
-
|
|
28983
|
-
|
|
28984
|
-
|
|
28985
|
-
|
|
28986
|
-
|
|
28987
|
-
|
|
28988
|
-
|
|
28989
|
-
|
|
28990
|
-
const px = plat.x - camX;
|
|
28991
|
-
const py = plat.y - camY;
|
|
28992
|
-
const platType = plat.type ?? "ground";
|
|
28993
|
-
const spriteUrl = tileSprites?.[platType];
|
|
28994
|
-
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28995
|
-
if (tileImg) {
|
|
28996
|
-
const tileW = tileImg.naturalWidth;
|
|
28997
|
-
const tileH = tileImg.naturalHeight;
|
|
28998
|
-
const scaleH = plat.height / tileH;
|
|
28999
|
-
const scaledW = tileW * scaleH;
|
|
29000
|
-
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
29001
|
-
const drawW = Math.min(scaledW, plat.width - tx);
|
|
29002
|
-
const srcW = drawW / scaleH;
|
|
29003
|
-
ctx.drawImage(tileImg, 0, 0, srcW, tileH, px + tx, py, drawW, plat.height);
|
|
29004
|
-
}
|
|
29062
|
+
}, [canvasWidth, canvasHeight]);
|
|
29063
|
+
React77.useEffect(() => {
|
|
29064
|
+
const drawFrame = (positions) => {
|
|
29065
|
+
const canvas = canvasRef.current;
|
|
29066
|
+
if (!canvas) return;
|
|
29067
|
+
const ctx = canvas.getContext("2d");
|
|
29068
|
+
if (!ctx) return;
|
|
29069
|
+
const {
|
|
29070
|
+
platforms: plats,
|
|
29071
|
+
worldWidth: ww,
|
|
29072
|
+
worldHeight: wh,
|
|
29073
|
+
canvasWidth: cw,
|
|
29074
|
+
canvasHeight: ch,
|
|
29075
|
+
followCamera: fc,
|
|
29076
|
+
bgColor: bg,
|
|
29077
|
+
playerSprite: pSprite,
|
|
29078
|
+
tileSprites: tSprites,
|
|
29079
|
+
backgroundImage: bgImg
|
|
29080
|
+
} = propsRef.current;
|
|
29081
|
+
const auth = playerRef.current;
|
|
29082
|
+
const interped = positions.get("player");
|
|
29083
|
+
const px = interped?.x ?? auth.x;
|
|
29084
|
+
const py = interped?.y ?? auth.y;
|
|
29085
|
+
let camX = 0;
|
|
29086
|
+
let camY = 0;
|
|
29087
|
+
if (fc) {
|
|
29088
|
+
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
29089
|
+
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
29090
|
+
}
|
|
29091
|
+
const bgImage = bgImg ? loadImage(bgImg) : null;
|
|
29092
|
+
if (bgImage) {
|
|
29093
|
+
ctx.drawImage(bgImage, 0, 0, cw, ch);
|
|
29094
|
+
} else if (bg) {
|
|
29095
|
+
ctx.fillStyle = bg;
|
|
29096
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
29005
29097
|
} else {
|
|
29006
|
-
const
|
|
29007
|
-
|
|
29008
|
-
|
|
29009
|
-
ctx.fillStyle =
|
|
29010
|
-
ctx.fillRect(
|
|
29011
|
-
|
|
29012
|
-
|
|
29013
|
-
|
|
29014
|
-
|
|
29015
|
-
|
|
29016
|
-
|
|
29098
|
+
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
29099
|
+
grad.addColorStop(0, SKY_GRADIENT_TOP);
|
|
29100
|
+
grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
|
|
29101
|
+
ctx.fillStyle = grad;
|
|
29102
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
29103
|
+
}
|
|
29104
|
+
ctx.strokeStyle = GRID_COLOR;
|
|
29105
|
+
ctx.lineWidth = 1;
|
|
29106
|
+
const gridSize = 32;
|
|
29107
|
+
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
29108
|
+
ctx.beginPath();
|
|
29109
|
+
ctx.moveTo(gx, 0);
|
|
29110
|
+
ctx.lineTo(gx, ch);
|
|
29111
|
+
ctx.stroke();
|
|
29112
|
+
}
|
|
29113
|
+
for (let gy = -camY % gridSize; gy < ch; gy += gridSize) {
|
|
29114
|
+
ctx.beginPath();
|
|
29115
|
+
ctx.moveTo(0, gy);
|
|
29116
|
+
ctx.lineTo(cw, gy);
|
|
29117
|
+
ctx.stroke();
|
|
29118
|
+
}
|
|
29119
|
+
for (const plat of plats) {
|
|
29120
|
+
const platX = plat.x - camX;
|
|
29121
|
+
const platY = plat.y - camY;
|
|
29122
|
+
const platType = plat.type ?? "ground";
|
|
29123
|
+
const spriteUrl = tSprites?.[platType];
|
|
29124
|
+
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
29125
|
+
if (tileImg) {
|
|
29126
|
+
const tileW = tileImg.naturalWidth;
|
|
29127
|
+
const tileH = tileImg.naturalHeight;
|
|
29128
|
+
const scaleH = plat.height / tileH;
|
|
29129
|
+
const scaledW = tileW * scaleH;
|
|
29130
|
+
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
29131
|
+
const drawW = Math.min(scaledW, plat.width - tx);
|
|
29132
|
+
const srcW = drawW / scaleH;
|
|
29133
|
+
ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
29134
|
+
}
|
|
29135
|
+
} else {
|
|
29136
|
+
const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
|
|
29137
|
+
ctx.fillStyle = color;
|
|
29138
|
+
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
29139
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
|
|
29140
|
+
ctx.fillRect(platX, platY, plat.width, 3);
|
|
29141
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
|
29142
|
+
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
29143
|
+
if (platType === "hazard") {
|
|
29144
|
+
ctx.strokeStyle = "#e74c3c";
|
|
29145
|
+
ctx.lineWidth = 2;
|
|
29146
|
+
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
29147
|
+
ctx.beginPath();
|
|
29148
|
+
ctx.moveTo(sx, platY);
|
|
29149
|
+
ctx.lineTo(sx + 6, platY + plat.height);
|
|
29150
|
+
ctx.stroke();
|
|
29151
|
+
}
|
|
29152
|
+
}
|
|
29153
|
+
if (platType === "goal") {
|
|
29154
|
+
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
29017
29155
|
ctx.beginPath();
|
|
29018
|
-
ctx.
|
|
29019
|
-
ctx.
|
|
29020
|
-
ctx.stroke();
|
|
29156
|
+
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
29157
|
+
ctx.fill();
|
|
29021
29158
|
}
|
|
29022
29159
|
}
|
|
29023
|
-
if (platType === "goal") {
|
|
29024
|
-
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
29025
|
-
ctx.beginPath();
|
|
29026
|
-
ctx.arc(px + plat.width / 2, py - 10, 8, 0, Math.PI * 2);
|
|
29027
|
-
ctx.fill();
|
|
29028
|
-
}
|
|
29029
29160
|
}
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
|
|
29033
|
-
|
|
29034
|
-
|
|
29035
|
-
|
|
29036
|
-
|
|
29037
|
-
|
|
29038
|
-
|
|
29039
|
-
|
|
29040
|
-
|
|
29041
|
-
|
|
29042
|
-
|
|
29161
|
+
const pw = auth.width ?? 24;
|
|
29162
|
+
const ph = auth.height ?? 32;
|
|
29163
|
+
const ppx = px - camX;
|
|
29164
|
+
const ppy = py - camY;
|
|
29165
|
+
const facingRight = auth.facingRight ?? true;
|
|
29166
|
+
const playerImg = pSprite ? loadImage(pSprite) : null;
|
|
29167
|
+
if (playerImg) {
|
|
29168
|
+
ctx.save();
|
|
29169
|
+
if (!facingRight) {
|
|
29170
|
+
ctx.translate(ppx + pw, ppy);
|
|
29171
|
+
ctx.scale(-1, 1);
|
|
29172
|
+
ctx.drawImage(playerImg, 0, 0, pw, ph);
|
|
29173
|
+
} else {
|
|
29174
|
+
ctx.drawImage(playerImg, ppx, ppy, pw, ph);
|
|
29175
|
+
}
|
|
29176
|
+
ctx.restore();
|
|
29043
29177
|
} else {
|
|
29044
|
-
ctx.
|
|
29178
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
29179
|
+
const radius = Math.min(pw, ph) * 0.25;
|
|
29180
|
+
ctx.beginPath();
|
|
29181
|
+
ctx.moveTo(ppx + radius, ppy);
|
|
29182
|
+
ctx.lineTo(ppx + pw - radius, ppy);
|
|
29183
|
+
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
29184
|
+
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
29185
|
+
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
29186
|
+
ctx.lineTo(ppx + radius, ppy + ph);
|
|
29187
|
+
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
29188
|
+
ctx.lineTo(ppx, ppy + radius);
|
|
29189
|
+
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
29190
|
+
ctx.fill();
|
|
29191
|
+
const eyeY = ppy + ph * 0.3;
|
|
29192
|
+
const eyeSize = 3;
|
|
29193
|
+
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
29194
|
+
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
29195
|
+
ctx.beginPath();
|
|
29196
|
+
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
29197
|
+
ctx.fill();
|
|
29198
|
+
ctx.beginPath();
|
|
29199
|
+
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
29200
|
+
ctx.fill();
|
|
29045
29201
|
}
|
|
29046
|
-
|
|
29047
|
-
|
|
29048
|
-
|
|
29049
|
-
const radius = Math.min(pw, ph) * 0.25;
|
|
29050
|
-
ctx.beginPath();
|
|
29051
|
-
ctx.moveTo(ppx + radius, ppy);
|
|
29052
|
-
ctx.lineTo(ppx + pw - radius, ppy);
|
|
29053
|
-
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
29054
|
-
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
29055
|
-
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
29056
|
-
ctx.lineTo(ppx + radius, ppy + ph);
|
|
29057
|
-
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
29058
|
-
ctx.lineTo(ppx, ppy + radius);
|
|
29059
|
-
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
29060
|
-
ctx.fill();
|
|
29061
|
-
const eyeY = ppy + ph * 0.3;
|
|
29062
|
-
const eyeSize = 3;
|
|
29063
|
-
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
29064
|
-
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
29065
|
-
ctx.beginPath();
|
|
29066
|
-
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
29067
|
-
ctx.fill();
|
|
29068
|
-
ctx.beginPath();
|
|
29069
|
-
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
29070
|
-
ctx.fill();
|
|
29071
|
-
}
|
|
29072
|
-
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
29202
|
+
};
|
|
29203
|
+
return interp.startLoop(drawFrame);
|
|
29204
|
+
}, [interp.startLoop, loadImage]);
|
|
29073
29205
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
29074
29206
|
"canvas",
|
|
29075
29207
|
{
|
|
@@ -29087,6 +29219,7 @@ var init_PlatformerCanvas = __esm({
|
|
|
29087
29219
|
init_cn();
|
|
29088
29220
|
init_useEventBus();
|
|
29089
29221
|
init_verificationRegistry();
|
|
29222
|
+
init_useRenderInterpolation();
|
|
29090
29223
|
PLATFORM_COLORS = {
|
|
29091
29224
|
ground: "#4a7c59",
|
|
29092
29225
|
platform: "#7c6b4a",
|
|
@@ -29491,13 +29624,13 @@ var init_MapView = __esm({
|
|
|
29491
29624
|
shadowSize: [41, 41]
|
|
29492
29625
|
});
|
|
29493
29626
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29494
|
-
const { useEffect:
|
|
29627
|
+
const { useEffect: useEffect74, useRef: useRef71, useCallback: useCallback114, useState: useState105 } = React77__namespace.default;
|
|
29495
29628
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
29496
29629
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
29497
29630
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
29498
29631
|
const map = useMap();
|
|
29499
|
-
const prevRef =
|
|
29500
|
-
|
|
29632
|
+
const prevRef = useRef71({ centerLat, centerLng, zoom });
|
|
29633
|
+
useEffect74(() => {
|
|
29501
29634
|
const prev = prevRef.current;
|
|
29502
29635
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
29503
29636
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -29508,7 +29641,7 @@ var init_MapView = __esm({
|
|
|
29508
29641
|
}
|
|
29509
29642
|
function MapClickHandler({ onMapClick }) {
|
|
29510
29643
|
const map = useMap();
|
|
29511
|
-
|
|
29644
|
+
useEffect74(() => {
|
|
29512
29645
|
if (!onMapClick) return;
|
|
29513
29646
|
const handler = (e) => {
|
|
29514
29647
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -29537,7 +29670,7 @@ var init_MapView = __esm({
|
|
|
29537
29670
|
}) {
|
|
29538
29671
|
const eventBus = useEventBus2();
|
|
29539
29672
|
const [clickedPosition, setClickedPosition] = useState105(null);
|
|
29540
|
-
const handleMapClick =
|
|
29673
|
+
const handleMapClick = useCallback114((lat, lng) => {
|
|
29541
29674
|
if (showClickedPin) {
|
|
29542
29675
|
setClickedPosition({ lat, lng });
|
|
29543
29676
|
}
|
|
@@ -29546,7 +29679,7 @@ var init_MapView = __esm({
|
|
|
29546
29679
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
29547
29680
|
}
|
|
29548
29681
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
29549
|
-
const handleMarkerClick =
|
|
29682
|
+
const handleMarkerClick = useCallback114((marker) => {
|
|
29550
29683
|
onMarkerClick?.(marker);
|
|
29551
29684
|
if (markerClickEvent) {
|
|
29552
29685
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -45508,6 +45641,10 @@ function SequencerBoard({
|
|
|
45508
45641
|
stepDurationMs = 1e3,
|
|
45509
45642
|
playEvent,
|
|
45510
45643
|
completeEvent,
|
|
45644
|
+
placeEvent,
|
|
45645
|
+
removeEvent,
|
|
45646
|
+
checkEvent,
|
|
45647
|
+
playAgainEvent,
|
|
45511
45648
|
className
|
|
45512
45649
|
}) {
|
|
45513
45650
|
const { emit } = useEventBus();
|
|
@@ -45543,7 +45680,8 @@ function SequencerBoard({
|
|
|
45543
45680
|
return next;
|
|
45544
45681
|
});
|
|
45545
45682
|
emit("UI:PLAY_SOUND", { key: "drop_slot" });
|
|
45546
|
-
|
|
45683
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotIndex: index, actionId: item.id });
|
|
45684
|
+
}, [emit, placeEvent]);
|
|
45547
45685
|
const handleSlotRemove = React77.useCallback((index) => {
|
|
45548
45686
|
setSlots((prev) => {
|
|
45549
45687
|
const next = [...prev];
|
|
@@ -45556,7 +45694,8 @@ function SequencerBoard({
|
|
|
45556
45694
|
return next;
|
|
45557
45695
|
});
|
|
45558
45696
|
emit("UI:PLAY_SOUND", { key: "back" });
|
|
45559
|
-
|
|
45697
|
+
if (removeEvent) emit(`UI:${removeEvent}`, { slotIndex: index });
|
|
45698
|
+
}, [emit, removeEvent]);
|
|
45560
45699
|
const handleReset = React77.useCallback(() => {
|
|
45561
45700
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
45562
45701
|
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
@@ -45564,7 +45703,8 @@ function SequencerBoard({
|
|
|
45564
45703
|
setCurrentStep(-1);
|
|
45565
45704
|
setAttempts(0);
|
|
45566
45705
|
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
45567
|
-
|
|
45706
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
45707
|
+
}, [maxSlots, playAgainEvent, emit]);
|
|
45568
45708
|
const filledSlots = slots.filter((s) => !!s);
|
|
45569
45709
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
45570
45710
|
const handlePlay = React77.useCallback(() => {
|
|
@@ -45586,6 +45726,7 @@ function SequencerBoard({
|
|
|
45586
45726
|
const success = solutions.some(
|
|
45587
45727
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
45588
45728
|
);
|
|
45729
|
+
if (checkEvent) emit(`UI:${checkEvent}`, { sequence: playerIds });
|
|
45589
45730
|
if (success) {
|
|
45590
45731
|
setPlayState("success");
|
|
45591
45732
|
setCurrentStep(-1);
|
|
@@ -45613,7 +45754,7 @@ function SequencerBoard({
|
|
|
45613
45754
|
}
|
|
45614
45755
|
};
|
|
45615
45756
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
45616
|
-
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
45757
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, checkEvent, emit]);
|
|
45617
45758
|
const machine = {
|
|
45618
45759
|
name: str(resolved?.title),
|
|
45619
45760
|
description: str(resolved?.description),
|
|
@@ -45868,11 +46009,13 @@ function SimulationCanvas({
|
|
|
45868
46009
|
height = 400,
|
|
45869
46010
|
running,
|
|
45870
46011
|
speed = 1,
|
|
46012
|
+
bodies: externalBodies,
|
|
45871
46013
|
className
|
|
45872
46014
|
}) {
|
|
45873
46015
|
const preset = React77.useMemo(() => resolvePreset(presetProp), [presetProp]);
|
|
45874
46016
|
const canvasRef = React77.useRef(null);
|
|
45875
46017
|
const bodiesRef = React77.useRef(structuredClone(preset.bodies));
|
|
46018
|
+
const interp = useRenderInterpolation();
|
|
45876
46019
|
React77.useEffect(() => {
|
|
45877
46020
|
bodiesRef.current = structuredClone(preset.bodies);
|
|
45878
46021
|
}, [preset]);
|
|
@@ -45970,6 +46113,67 @@ function SimulationCanvas({
|
|
|
45970
46113
|
}
|
|
45971
46114
|
}, [width, height, preset]);
|
|
45972
46115
|
React77.useEffect(() => {
|
|
46116
|
+
if (!externalBodies) return;
|
|
46117
|
+
interp.onSnapshot(externalBodies.map((b) => ({ id: b.id, x: b.x, y: b.y })));
|
|
46118
|
+
}, [externalBodies]);
|
|
46119
|
+
const presetRef = React77.useRef(preset);
|
|
46120
|
+
presetRef.current = preset;
|
|
46121
|
+
const widthRef = React77.useRef(width);
|
|
46122
|
+
widthRef.current = width;
|
|
46123
|
+
const heightRef = React77.useRef(height);
|
|
46124
|
+
heightRef.current = height;
|
|
46125
|
+
React77.useEffect(() => {
|
|
46126
|
+
if (!externalBodies) return;
|
|
46127
|
+
const drawInterpolated = (positions) => {
|
|
46128
|
+
const canvas = canvasRef.current;
|
|
46129
|
+
if (!canvas) return;
|
|
46130
|
+
const ctx = canvas.getContext("2d");
|
|
46131
|
+
if (!ctx) return;
|
|
46132
|
+
const bodies = bodiesRef.current;
|
|
46133
|
+
const p2 = presetRef.current;
|
|
46134
|
+
const w = widthRef.current;
|
|
46135
|
+
const h = heightRef.current;
|
|
46136
|
+
ctx.clearRect(0, 0, w, h);
|
|
46137
|
+
ctx.fillStyle = p2.backgroundColor ?? "#1a1a2e";
|
|
46138
|
+
ctx.fillRect(0, 0, w, h);
|
|
46139
|
+
if (p2.constraints) {
|
|
46140
|
+
for (const c of p2.constraints) {
|
|
46141
|
+
const a = bodies[c.bodyA];
|
|
46142
|
+
const b = bodies[c.bodyB];
|
|
46143
|
+
if (a && b) {
|
|
46144
|
+
const aPos = positions.get(a.id) ?? a;
|
|
46145
|
+
const bPos = positions.get(b.id) ?? b;
|
|
46146
|
+
ctx.beginPath();
|
|
46147
|
+
ctx.moveTo(aPos.x, aPos.y);
|
|
46148
|
+
ctx.lineTo(bPos.x, bPos.y);
|
|
46149
|
+
ctx.strokeStyle = "#533483";
|
|
46150
|
+
ctx.lineWidth = 1;
|
|
46151
|
+
ctx.setLineDash([4, 4]);
|
|
46152
|
+
ctx.stroke();
|
|
46153
|
+
ctx.setLineDash([]);
|
|
46154
|
+
}
|
|
46155
|
+
}
|
|
46156
|
+
}
|
|
46157
|
+
for (const body of bodies) {
|
|
46158
|
+
const pos = positions.get(body.id) ?? body;
|
|
46159
|
+
ctx.beginPath();
|
|
46160
|
+
ctx.arc(pos.x, pos.y, body.radius, 0, Math.PI * 2);
|
|
46161
|
+
ctx.fillStyle = body.color ?? "#e94560";
|
|
46162
|
+
ctx.fill();
|
|
46163
|
+
if (p2.showVelocity) {
|
|
46164
|
+
ctx.beginPath();
|
|
46165
|
+
ctx.moveTo(pos.x, pos.y);
|
|
46166
|
+
ctx.lineTo(pos.x + body.vx * 0.1, pos.y + body.vy * 0.1);
|
|
46167
|
+
ctx.strokeStyle = "#16213e";
|
|
46168
|
+
ctx.lineWidth = 2;
|
|
46169
|
+
ctx.stroke();
|
|
46170
|
+
}
|
|
46171
|
+
}
|
|
46172
|
+
};
|
|
46173
|
+
return interp.startLoop(drawInterpolated);
|
|
46174
|
+
}, [externalBodies !== void 0, interp.startLoop]);
|
|
46175
|
+
React77.useEffect(() => {
|
|
46176
|
+
if (externalBodies !== void 0) return;
|
|
45973
46177
|
if (!running) return;
|
|
45974
46178
|
let raf;
|
|
45975
46179
|
const loop = () => {
|
|
@@ -45979,10 +46183,11 @@ function SimulationCanvas({
|
|
|
45979
46183
|
};
|
|
45980
46184
|
raf = requestAnimationFrame(loop);
|
|
45981
46185
|
return () => cancelAnimationFrame(raf);
|
|
45982
|
-
}, [running, step, draw]);
|
|
46186
|
+
}, [running, step, draw, externalBodies]);
|
|
45983
46187
|
React77.useEffect(() => {
|
|
46188
|
+
if (externalBodies !== void 0) return;
|
|
45984
46189
|
draw();
|
|
45985
|
-
}, [draw]);
|
|
46190
|
+
}, [draw, externalBodies]);
|
|
45986
46191
|
React77.useEffect(() => {
|
|
45987
46192
|
if (typeof window === "undefined") return;
|
|
45988
46193
|
const canvas = canvasRef.current;
|
|
@@ -46008,6 +46213,7 @@ var init_SimulationCanvas = __esm({
|
|
|
46008
46213
|
init_atoms2();
|
|
46009
46214
|
init_verificationRegistry();
|
|
46010
46215
|
init_presets();
|
|
46216
|
+
init_useRenderInterpolation();
|
|
46011
46217
|
SimulationCanvas.displayName = "SimulationCanvas";
|
|
46012
46218
|
}
|
|
46013
46219
|
});
|