@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/runtime/index.js
CHANGED
|
@@ -28130,6 +28130,78 @@ var init_GameOverScreen = __esm({
|
|
|
28130
28130
|
GameOverScreen.displayName = "GameOverScreen";
|
|
28131
28131
|
}
|
|
28132
28132
|
});
|
|
28133
|
+
function useRenderInterpolation(options = {}) {
|
|
28134
|
+
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
28135
|
+
const prevRef = useRef(null);
|
|
28136
|
+
const currRef = useRef(null);
|
|
28137
|
+
const rafRef = useRef(null);
|
|
28138
|
+
const onSnapshot = useCallback((entities) => {
|
|
28139
|
+
prevRef.current = currRef.current;
|
|
28140
|
+
currRef.current = { entities, arrivedAt: performance.now() };
|
|
28141
|
+
}, []);
|
|
28142
|
+
const getInterpolated = useCallback((now2) => {
|
|
28143
|
+
const out = /* @__PURE__ */ new Map();
|
|
28144
|
+
const curr = currRef.current;
|
|
28145
|
+
if (!curr) return out;
|
|
28146
|
+
const prev = prevRef.current;
|
|
28147
|
+
if (!prev) {
|
|
28148
|
+
for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
|
|
28149
|
+
return out;
|
|
28150
|
+
}
|
|
28151
|
+
const rawAlpha = (now2 - curr.arrivedAt) / tickIntervalMs;
|
|
28152
|
+
const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
|
|
28153
|
+
const prevMap = /* @__PURE__ */ new Map();
|
|
28154
|
+
for (const e of prev.entities) prevMap.set(e.id, e);
|
|
28155
|
+
for (const c of curr.entities) {
|
|
28156
|
+
const p2 = prevMap.get(c.id);
|
|
28157
|
+
if (!p2) {
|
|
28158
|
+
out.set(c.id, { x: c.x, y: c.y });
|
|
28159
|
+
} else {
|
|
28160
|
+
out.set(c.id, {
|
|
28161
|
+
x: p2.x + (c.x - p2.x) * alpha,
|
|
28162
|
+
y: p2.y + (c.y - p2.y) * alpha
|
|
28163
|
+
});
|
|
28164
|
+
}
|
|
28165
|
+
}
|
|
28166
|
+
return out;
|
|
28167
|
+
}, [tickIntervalMs]);
|
|
28168
|
+
const startLoop = useCallback(
|
|
28169
|
+
(draw) => {
|
|
28170
|
+
let active = true;
|
|
28171
|
+
const loop = () => {
|
|
28172
|
+
if (!active) return;
|
|
28173
|
+
try {
|
|
28174
|
+
draw(getInterpolated(performance.now()));
|
|
28175
|
+
} catch {
|
|
28176
|
+
}
|
|
28177
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28178
|
+
};
|
|
28179
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28180
|
+
return () => {
|
|
28181
|
+
active = false;
|
|
28182
|
+
if (rafRef.current !== null) {
|
|
28183
|
+
cancelAnimationFrame(rafRef.current);
|
|
28184
|
+
rafRef.current = null;
|
|
28185
|
+
}
|
|
28186
|
+
};
|
|
28187
|
+
},
|
|
28188
|
+
[getInterpolated]
|
|
28189
|
+
);
|
|
28190
|
+
useEffect(() => {
|
|
28191
|
+
return () => {
|
|
28192
|
+
if (rafRef.current !== null) {
|
|
28193
|
+
cancelAnimationFrame(rafRef.current);
|
|
28194
|
+
rafRef.current = null;
|
|
28195
|
+
}
|
|
28196
|
+
};
|
|
28197
|
+
}, []);
|
|
28198
|
+
return { onSnapshot, getInterpolated, startLoop };
|
|
28199
|
+
}
|
|
28200
|
+
var init_useRenderInterpolation = __esm({
|
|
28201
|
+
"hooks/useRenderInterpolation.ts"() {
|
|
28202
|
+
"use client";
|
|
28203
|
+
}
|
|
28204
|
+
});
|
|
28133
28205
|
function PlatformerCanvas({
|
|
28134
28206
|
player,
|
|
28135
28207
|
platforms = [
|
|
@@ -28198,8 +28270,43 @@ function PlatformerCanvas({
|
|
|
28198
28270
|
y: 336,
|
|
28199
28271
|
width: 32,
|
|
28200
28272
|
height: 48,
|
|
28273
|
+
vx: 0,
|
|
28274
|
+
vy: 0,
|
|
28275
|
+
grounded: true,
|
|
28201
28276
|
facingRight: true
|
|
28202
28277
|
};
|
|
28278
|
+
const playerRef = useRef(resolvedPlayer);
|
|
28279
|
+
playerRef.current = resolvedPlayer;
|
|
28280
|
+
const interp = useRenderInterpolation();
|
|
28281
|
+
useEffect(() => {
|
|
28282
|
+
interp.onSnapshot([{ id: "player", x: resolvedPlayer.x, y: resolvedPlayer.y }]);
|
|
28283
|
+
}, [resolvedPlayer.x, resolvedPlayer.y]);
|
|
28284
|
+
const propsRef = useRef({
|
|
28285
|
+
platforms,
|
|
28286
|
+
worldWidth,
|
|
28287
|
+
worldHeight,
|
|
28288
|
+
canvasWidth,
|
|
28289
|
+
canvasHeight,
|
|
28290
|
+
followCamera,
|
|
28291
|
+
bgColor,
|
|
28292
|
+
playerSprite,
|
|
28293
|
+
tileSprites,
|
|
28294
|
+
backgroundImage,
|
|
28295
|
+
assetBaseUrl
|
|
28296
|
+
});
|
|
28297
|
+
propsRef.current = {
|
|
28298
|
+
platforms,
|
|
28299
|
+
worldWidth,
|
|
28300
|
+
worldHeight,
|
|
28301
|
+
canvasWidth,
|
|
28302
|
+
canvasHeight,
|
|
28303
|
+
followCamera,
|
|
28304
|
+
bgColor,
|
|
28305
|
+
playerSprite,
|
|
28306
|
+
tileSprites,
|
|
28307
|
+
backgroundImage,
|
|
28308
|
+
assetBaseUrl
|
|
28309
|
+
};
|
|
28203
28310
|
const handleKeyDown = useCallback((e) => {
|
|
28204
28311
|
if (keysRef.current.has(e.code)) return;
|
|
28205
28312
|
keysRef.current.add(e.code);
|
|
@@ -28248,124 +28355,149 @@ function PlatformerCanvas({
|
|
|
28248
28355
|
canvas.width = canvasWidth * dpr;
|
|
28249
28356
|
canvas.height = canvasHeight * dpr;
|
|
28250
28357
|
ctx.scale(dpr, dpr);
|
|
28251
|
-
|
|
28252
|
-
|
|
28253
|
-
|
|
28254
|
-
|
|
28255
|
-
|
|
28256
|
-
|
|
28257
|
-
|
|
28258
|
-
|
|
28259
|
-
|
|
28260
|
-
|
|
28261
|
-
|
|
28262
|
-
|
|
28263
|
-
|
|
28264
|
-
|
|
28265
|
-
|
|
28266
|
-
|
|
28267
|
-
|
|
28268
|
-
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
|
|
28273
|
-
|
|
28274
|
-
|
|
28275
|
-
|
|
28276
|
-
|
|
28277
|
-
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
|
|
28282
|
-
|
|
28283
|
-
|
|
28284
|
-
|
|
28285
|
-
|
|
28286
|
-
const px = plat.x - camX;
|
|
28287
|
-
const py = plat.y - camY;
|
|
28288
|
-
const platType = plat.type ?? "ground";
|
|
28289
|
-
const spriteUrl = tileSprites?.[platType];
|
|
28290
|
-
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28291
|
-
if (tileImg) {
|
|
28292
|
-
const tileW = tileImg.naturalWidth;
|
|
28293
|
-
const tileH = tileImg.naturalHeight;
|
|
28294
|
-
const scaleH = plat.height / tileH;
|
|
28295
|
-
const scaledW = tileW * scaleH;
|
|
28296
|
-
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28297
|
-
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28298
|
-
const srcW = drawW / scaleH;
|
|
28299
|
-
ctx.drawImage(tileImg, 0, 0, srcW, tileH, px + tx, py, drawW, plat.height);
|
|
28300
|
-
}
|
|
28358
|
+
}, [canvasWidth, canvasHeight]);
|
|
28359
|
+
useEffect(() => {
|
|
28360
|
+
const drawFrame = (positions) => {
|
|
28361
|
+
const canvas = canvasRef.current;
|
|
28362
|
+
if (!canvas) return;
|
|
28363
|
+
const ctx = canvas.getContext("2d");
|
|
28364
|
+
if (!ctx) return;
|
|
28365
|
+
const {
|
|
28366
|
+
platforms: plats,
|
|
28367
|
+
worldWidth: ww,
|
|
28368
|
+
worldHeight: wh,
|
|
28369
|
+
canvasWidth: cw,
|
|
28370
|
+
canvasHeight: ch,
|
|
28371
|
+
followCamera: fc,
|
|
28372
|
+
bgColor: bg,
|
|
28373
|
+
playerSprite: pSprite,
|
|
28374
|
+
tileSprites: tSprites,
|
|
28375
|
+
backgroundImage: bgImg
|
|
28376
|
+
} = propsRef.current;
|
|
28377
|
+
const auth = playerRef.current;
|
|
28378
|
+
const interped = positions.get("player");
|
|
28379
|
+
const px = interped?.x ?? auth.x;
|
|
28380
|
+
const py = interped?.y ?? auth.y;
|
|
28381
|
+
let camX = 0;
|
|
28382
|
+
let camY = 0;
|
|
28383
|
+
if (fc) {
|
|
28384
|
+
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
28385
|
+
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
28386
|
+
}
|
|
28387
|
+
const bgImage = bgImg ? loadImage(bgImg) : null;
|
|
28388
|
+
if (bgImage) {
|
|
28389
|
+
ctx.drawImage(bgImage, 0, 0, cw, ch);
|
|
28390
|
+
} else if (bg) {
|
|
28391
|
+
ctx.fillStyle = bg;
|
|
28392
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28301
28393
|
} else {
|
|
28302
|
-
const
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
ctx.fillStyle =
|
|
28306
|
-
ctx.fillRect(
|
|
28307
|
-
|
|
28308
|
-
|
|
28309
|
-
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28394
|
+
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
28395
|
+
grad.addColorStop(0, SKY_GRADIENT_TOP);
|
|
28396
|
+
grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
|
|
28397
|
+
ctx.fillStyle = grad;
|
|
28398
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28399
|
+
}
|
|
28400
|
+
ctx.strokeStyle = GRID_COLOR;
|
|
28401
|
+
ctx.lineWidth = 1;
|
|
28402
|
+
const gridSize = 32;
|
|
28403
|
+
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
28404
|
+
ctx.beginPath();
|
|
28405
|
+
ctx.moveTo(gx, 0);
|
|
28406
|
+
ctx.lineTo(gx, ch);
|
|
28407
|
+
ctx.stroke();
|
|
28408
|
+
}
|
|
28409
|
+
for (let gy = -camY % gridSize; gy < ch; gy += gridSize) {
|
|
28410
|
+
ctx.beginPath();
|
|
28411
|
+
ctx.moveTo(0, gy);
|
|
28412
|
+
ctx.lineTo(cw, gy);
|
|
28413
|
+
ctx.stroke();
|
|
28414
|
+
}
|
|
28415
|
+
for (const plat of plats) {
|
|
28416
|
+
const platX = plat.x - camX;
|
|
28417
|
+
const platY = plat.y - camY;
|
|
28418
|
+
const platType = plat.type ?? "ground";
|
|
28419
|
+
const spriteUrl = tSprites?.[platType];
|
|
28420
|
+
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28421
|
+
if (tileImg) {
|
|
28422
|
+
const tileW = tileImg.naturalWidth;
|
|
28423
|
+
const tileH = tileImg.naturalHeight;
|
|
28424
|
+
const scaleH = plat.height / tileH;
|
|
28425
|
+
const scaledW = tileW * scaleH;
|
|
28426
|
+
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28427
|
+
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28428
|
+
const srcW = drawW / scaleH;
|
|
28429
|
+
ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
28430
|
+
}
|
|
28431
|
+
} else {
|
|
28432
|
+
const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
|
|
28433
|
+
ctx.fillStyle = color;
|
|
28434
|
+
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
28435
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
|
|
28436
|
+
ctx.fillRect(platX, platY, plat.width, 3);
|
|
28437
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
|
28438
|
+
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
28439
|
+
if (platType === "hazard") {
|
|
28440
|
+
ctx.strokeStyle = "#e74c3c";
|
|
28441
|
+
ctx.lineWidth = 2;
|
|
28442
|
+
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
28443
|
+
ctx.beginPath();
|
|
28444
|
+
ctx.moveTo(sx, platY);
|
|
28445
|
+
ctx.lineTo(sx + 6, platY + plat.height);
|
|
28446
|
+
ctx.stroke();
|
|
28447
|
+
}
|
|
28448
|
+
}
|
|
28449
|
+
if (platType === "goal") {
|
|
28450
|
+
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28313
28451
|
ctx.beginPath();
|
|
28314
|
-
ctx.
|
|
28315
|
-
ctx.
|
|
28316
|
-
ctx.stroke();
|
|
28452
|
+
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
28453
|
+
ctx.fill();
|
|
28317
28454
|
}
|
|
28318
28455
|
}
|
|
28319
|
-
if (platType === "goal") {
|
|
28320
|
-
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28321
|
-
ctx.beginPath();
|
|
28322
|
-
ctx.arc(px + plat.width / 2, py - 10, 8, 0, Math.PI * 2);
|
|
28323
|
-
ctx.fill();
|
|
28324
|
-
}
|
|
28325
28456
|
}
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28331
|
-
|
|
28332
|
-
|
|
28333
|
-
|
|
28334
|
-
|
|
28335
|
-
|
|
28336
|
-
|
|
28337
|
-
|
|
28338
|
-
|
|
28457
|
+
const pw = auth.width ?? 24;
|
|
28458
|
+
const ph = auth.height ?? 32;
|
|
28459
|
+
const ppx = px - camX;
|
|
28460
|
+
const ppy = py - camY;
|
|
28461
|
+
const facingRight = auth.facingRight ?? true;
|
|
28462
|
+
const playerImg = pSprite ? loadImage(pSprite) : null;
|
|
28463
|
+
if (playerImg) {
|
|
28464
|
+
ctx.save();
|
|
28465
|
+
if (!facingRight) {
|
|
28466
|
+
ctx.translate(ppx + pw, ppy);
|
|
28467
|
+
ctx.scale(-1, 1);
|
|
28468
|
+
ctx.drawImage(playerImg, 0, 0, pw, ph);
|
|
28469
|
+
} else {
|
|
28470
|
+
ctx.drawImage(playerImg, ppx, ppy, pw, ph);
|
|
28471
|
+
}
|
|
28472
|
+
ctx.restore();
|
|
28339
28473
|
} else {
|
|
28340
|
-
ctx.
|
|
28474
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
28475
|
+
const radius = Math.min(pw, ph) * 0.25;
|
|
28476
|
+
ctx.beginPath();
|
|
28477
|
+
ctx.moveTo(ppx + radius, ppy);
|
|
28478
|
+
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28479
|
+
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28480
|
+
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28481
|
+
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28482
|
+
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28483
|
+
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28484
|
+
ctx.lineTo(ppx, ppy + radius);
|
|
28485
|
+
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28486
|
+
ctx.fill();
|
|
28487
|
+
const eyeY = ppy + ph * 0.3;
|
|
28488
|
+
const eyeSize = 3;
|
|
28489
|
+
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28490
|
+
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28491
|
+
ctx.beginPath();
|
|
28492
|
+
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28493
|
+
ctx.fill();
|
|
28494
|
+
ctx.beginPath();
|
|
28495
|
+
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28496
|
+
ctx.fill();
|
|
28341
28497
|
}
|
|
28342
|
-
|
|
28343
|
-
|
|
28344
|
-
|
|
28345
|
-
const radius = Math.min(pw, ph) * 0.25;
|
|
28346
|
-
ctx.beginPath();
|
|
28347
|
-
ctx.moveTo(ppx + radius, ppy);
|
|
28348
|
-
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28349
|
-
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28350
|
-
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28351
|
-
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28352
|
-
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28353
|
-
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28354
|
-
ctx.lineTo(ppx, ppy + radius);
|
|
28355
|
-
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28356
|
-
ctx.fill();
|
|
28357
|
-
const eyeY = ppy + ph * 0.3;
|
|
28358
|
-
const eyeSize = 3;
|
|
28359
|
-
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28360
|
-
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28361
|
-
ctx.beginPath();
|
|
28362
|
-
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28363
|
-
ctx.fill();
|
|
28364
|
-
ctx.beginPath();
|
|
28365
|
-
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28366
|
-
ctx.fill();
|
|
28367
|
-
}
|
|
28368
|
-
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
28498
|
+
};
|
|
28499
|
+
return interp.startLoop(drawFrame);
|
|
28500
|
+
}, [interp.startLoop, loadImage]);
|
|
28369
28501
|
return /* @__PURE__ */ jsx(
|
|
28370
28502
|
"canvas",
|
|
28371
28503
|
{
|
|
@@ -28383,6 +28515,7 @@ var init_PlatformerCanvas = __esm({
|
|
|
28383
28515
|
init_cn();
|
|
28384
28516
|
init_useEventBus();
|
|
28385
28517
|
init_verificationRegistry();
|
|
28518
|
+
init_useRenderInterpolation();
|
|
28386
28519
|
PLATFORM_COLORS = {
|
|
28387
28520
|
ground: "#4a7c59",
|
|
28388
28521
|
platform: "#7c6b4a",
|
|
@@ -28765,13 +28898,13 @@ var init_MapView = __esm({
|
|
|
28765
28898
|
shadowSize: [41, 41]
|
|
28766
28899
|
});
|
|
28767
28900
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
28768
|
-
const { useEffect:
|
|
28901
|
+
const { useEffect: useEffect75, useRef: useRef69, useCallback: useCallback112, useState: useState107 } = React82__default;
|
|
28769
28902
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
28770
28903
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
28771
28904
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
28772
28905
|
const map = useMap();
|
|
28773
|
-
const prevRef =
|
|
28774
|
-
|
|
28906
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
28907
|
+
useEffect75(() => {
|
|
28775
28908
|
const prev = prevRef.current;
|
|
28776
28909
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
28777
28910
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -28782,7 +28915,7 @@ var init_MapView = __esm({
|
|
|
28782
28915
|
}
|
|
28783
28916
|
function MapClickHandler({ onMapClick }) {
|
|
28784
28917
|
const map = useMap();
|
|
28785
|
-
|
|
28918
|
+
useEffect75(() => {
|
|
28786
28919
|
if (!onMapClick) return;
|
|
28787
28920
|
const handler = (e) => {
|
|
28788
28921
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -28811,7 +28944,7 @@ var init_MapView = __esm({
|
|
|
28811
28944
|
}) {
|
|
28812
28945
|
const eventBus = useEventBus3();
|
|
28813
28946
|
const [clickedPosition, setClickedPosition] = useState107(null);
|
|
28814
|
-
const handleMapClick =
|
|
28947
|
+
const handleMapClick = useCallback112((lat, lng) => {
|
|
28815
28948
|
if (showClickedPin) {
|
|
28816
28949
|
setClickedPosition({ lat, lng });
|
|
28817
28950
|
}
|
|
@@ -28820,7 +28953,7 @@ var init_MapView = __esm({
|
|
|
28820
28953
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
28821
28954
|
}
|
|
28822
28955
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
28823
|
-
const handleMarkerClick =
|
|
28956
|
+
const handleMarkerClick = useCallback112((marker) => {
|
|
28824
28957
|
onMarkerClick?.(marker);
|
|
28825
28958
|
if (markerClickEvent) {
|
|
28826
28959
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -44324,6 +44457,10 @@ function SequencerBoard({
|
|
|
44324
44457
|
stepDurationMs = 1e3,
|
|
44325
44458
|
playEvent,
|
|
44326
44459
|
completeEvent,
|
|
44460
|
+
placeEvent,
|
|
44461
|
+
removeEvent,
|
|
44462
|
+
checkEvent,
|
|
44463
|
+
playAgainEvent,
|
|
44327
44464
|
className
|
|
44328
44465
|
}) {
|
|
44329
44466
|
const { emit } = useEventBus();
|
|
@@ -44359,7 +44496,8 @@ function SequencerBoard({
|
|
|
44359
44496
|
return next;
|
|
44360
44497
|
});
|
|
44361
44498
|
emit("UI:PLAY_SOUND", { key: "drop_slot" });
|
|
44362
|
-
|
|
44499
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotIndex: index, actionId: item.id });
|
|
44500
|
+
}, [emit, placeEvent]);
|
|
44363
44501
|
const handleSlotRemove = useCallback((index) => {
|
|
44364
44502
|
setSlots((prev) => {
|
|
44365
44503
|
const next = [...prev];
|
|
@@ -44372,7 +44510,8 @@ function SequencerBoard({
|
|
|
44372
44510
|
return next;
|
|
44373
44511
|
});
|
|
44374
44512
|
emit("UI:PLAY_SOUND", { key: "back" });
|
|
44375
|
-
|
|
44513
|
+
if (removeEvent) emit(`UI:${removeEvent}`, { slotIndex: index });
|
|
44514
|
+
}, [emit, removeEvent]);
|
|
44376
44515
|
const handleReset = useCallback(() => {
|
|
44377
44516
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44378
44517
|
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
@@ -44380,7 +44519,8 @@ function SequencerBoard({
|
|
|
44380
44519
|
setCurrentStep(-1);
|
|
44381
44520
|
setAttempts(0);
|
|
44382
44521
|
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
44383
|
-
|
|
44522
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
44523
|
+
}, [maxSlots, playAgainEvent, emit]);
|
|
44384
44524
|
const filledSlots = slots.filter((s) => !!s);
|
|
44385
44525
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
44386
44526
|
const handlePlay = useCallback(() => {
|
|
@@ -44402,6 +44542,7 @@ function SequencerBoard({
|
|
|
44402
44542
|
const success = solutions.some(
|
|
44403
44543
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
44404
44544
|
);
|
|
44545
|
+
if (checkEvent) emit(`UI:${checkEvent}`, { sequence: playerIds });
|
|
44405
44546
|
if (success) {
|
|
44406
44547
|
setPlayState("success");
|
|
44407
44548
|
setCurrentStep(-1);
|
|
@@ -44429,7 +44570,7 @@ function SequencerBoard({
|
|
|
44429
44570
|
}
|
|
44430
44571
|
};
|
|
44431
44572
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
44432
|
-
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
44573
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, checkEvent, emit]);
|
|
44433
44574
|
const machine = {
|
|
44434
44575
|
name: str(resolved?.title),
|
|
44435
44576
|
description: str(resolved?.description),
|
|
@@ -44684,11 +44825,13 @@ function SimulationCanvas({
|
|
|
44684
44825
|
height = 400,
|
|
44685
44826
|
running,
|
|
44686
44827
|
speed = 1,
|
|
44828
|
+
bodies: externalBodies,
|
|
44687
44829
|
className
|
|
44688
44830
|
}) {
|
|
44689
44831
|
const preset = useMemo(() => resolvePreset(presetProp), [presetProp]);
|
|
44690
44832
|
const canvasRef = useRef(null);
|
|
44691
44833
|
const bodiesRef = useRef(structuredClone(preset.bodies));
|
|
44834
|
+
const interp = useRenderInterpolation();
|
|
44692
44835
|
useEffect(() => {
|
|
44693
44836
|
bodiesRef.current = structuredClone(preset.bodies);
|
|
44694
44837
|
}, [preset]);
|
|
@@ -44786,6 +44929,67 @@ function SimulationCanvas({
|
|
|
44786
44929
|
}
|
|
44787
44930
|
}, [width, height, preset]);
|
|
44788
44931
|
useEffect(() => {
|
|
44932
|
+
if (!externalBodies) return;
|
|
44933
|
+
interp.onSnapshot(externalBodies.map((b) => ({ id: b.id, x: b.x, y: b.y })));
|
|
44934
|
+
}, [externalBodies]);
|
|
44935
|
+
const presetRef = useRef(preset);
|
|
44936
|
+
presetRef.current = preset;
|
|
44937
|
+
const widthRef = useRef(width);
|
|
44938
|
+
widthRef.current = width;
|
|
44939
|
+
const heightRef = useRef(height);
|
|
44940
|
+
heightRef.current = height;
|
|
44941
|
+
useEffect(() => {
|
|
44942
|
+
if (!externalBodies) return;
|
|
44943
|
+
const drawInterpolated = (positions) => {
|
|
44944
|
+
const canvas = canvasRef.current;
|
|
44945
|
+
if (!canvas) return;
|
|
44946
|
+
const ctx = canvas.getContext("2d");
|
|
44947
|
+
if (!ctx) return;
|
|
44948
|
+
const bodies = bodiesRef.current;
|
|
44949
|
+
const p2 = presetRef.current;
|
|
44950
|
+
const w = widthRef.current;
|
|
44951
|
+
const h = heightRef.current;
|
|
44952
|
+
ctx.clearRect(0, 0, w, h);
|
|
44953
|
+
ctx.fillStyle = p2.backgroundColor ?? "#1a1a2e";
|
|
44954
|
+
ctx.fillRect(0, 0, w, h);
|
|
44955
|
+
if (p2.constraints) {
|
|
44956
|
+
for (const c of p2.constraints) {
|
|
44957
|
+
const a = bodies[c.bodyA];
|
|
44958
|
+
const b = bodies[c.bodyB];
|
|
44959
|
+
if (a && b) {
|
|
44960
|
+
const aPos = positions.get(a.id) ?? a;
|
|
44961
|
+
const bPos = positions.get(b.id) ?? b;
|
|
44962
|
+
ctx.beginPath();
|
|
44963
|
+
ctx.moveTo(aPos.x, aPos.y);
|
|
44964
|
+
ctx.lineTo(bPos.x, bPos.y);
|
|
44965
|
+
ctx.strokeStyle = "#533483";
|
|
44966
|
+
ctx.lineWidth = 1;
|
|
44967
|
+
ctx.setLineDash([4, 4]);
|
|
44968
|
+
ctx.stroke();
|
|
44969
|
+
ctx.setLineDash([]);
|
|
44970
|
+
}
|
|
44971
|
+
}
|
|
44972
|
+
}
|
|
44973
|
+
for (const body of bodies) {
|
|
44974
|
+
const pos = positions.get(body.id) ?? body;
|
|
44975
|
+
ctx.beginPath();
|
|
44976
|
+
ctx.arc(pos.x, pos.y, body.radius, 0, Math.PI * 2);
|
|
44977
|
+
ctx.fillStyle = body.color ?? "#e94560";
|
|
44978
|
+
ctx.fill();
|
|
44979
|
+
if (p2.showVelocity) {
|
|
44980
|
+
ctx.beginPath();
|
|
44981
|
+
ctx.moveTo(pos.x, pos.y);
|
|
44982
|
+
ctx.lineTo(pos.x + body.vx * 0.1, pos.y + body.vy * 0.1);
|
|
44983
|
+
ctx.strokeStyle = "#16213e";
|
|
44984
|
+
ctx.lineWidth = 2;
|
|
44985
|
+
ctx.stroke();
|
|
44986
|
+
}
|
|
44987
|
+
}
|
|
44988
|
+
};
|
|
44989
|
+
return interp.startLoop(drawInterpolated);
|
|
44990
|
+
}, [externalBodies !== void 0, interp.startLoop]);
|
|
44991
|
+
useEffect(() => {
|
|
44992
|
+
if (externalBodies !== void 0) return;
|
|
44789
44993
|
if (!running) return;
|
|
44790
44994
|
let raf;
|
|
44791
44995
|
const loop = () => {
|
|
@@ -44795,10 +44999,11 @@ function SimulationCanvas({
|
|
|
44795
44999
|
};
|
|
44796
45000
|
raf = requestAnimationFrame(loop);
|
|
44797
45001
|
return () => cancelAnimationFrame(raf);
|
|
44798
|
-
}, [running, step, draw]);
|
|
45002
|
+
}, [running, step, draw, externalBodies]);
|
|
44799
45003
|
useEffect(() => {
|
|
45004
|
+
if (externalBodies !== void 0) return;
|
|
44800
45005
|
draw();
|
|
44801
|
-
}, [draw]);
|
|
45006
|
+
}, [draw, externalBodies]);
|
|
44802
45007
|
useEffect(() => {
|
|
44803
45008
|
if (typeof window === "undefined") return;
|
|
44804
45009
|
const canvas = canvasRef.current;
|
|
@@ -44824,6 +45029,7 @@ var init_SimulationCanvas = __esm({
|
|
|
44824
45029
|
init_atoms2();
|
|
44825
45030
|
init_verificationRegistry();
|
|
44826
45031
|
init_presets();
|
|
45032
|
+
init_useRenderInterpolation();
|
|
44827
45033
|
SimulationCanvas.displayName = "SimulationCanvas";
|
|
44828
45034
|
}
|
|
44829
45035
|
});
|