@almadar/ui 5.49.1 → 5.51.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 +519 -215
- package/dist/avl/index.js +521 -217
- package/dist/components/game/molecules/three/index.cjs +251 -3
- package/dist/components/game/molecules/three/index.js +253 -5
- package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +30 -0
- package/dist/components/game/organisms/types/isometric.d.ts +4 -0
- package/dist/components/game/organisms/types/spriteAnimation.d.ts +24 -0
- package/dist/components/game/organisms/utils/spriteAnimation.d.ts +29 -1
- package/dist/components/index.cjs +377 -141
- package/dist/components/index.js +378 -140
- package/dist/providers/index.cjs +289 -28
- package/dist/providers/index.js +290 -29
- package/dist/runtime/index.cjs +519 -215
- package/dist/runtime/index.js +521 -217
- package/package.json +1 -1
|
@@ -41,7 +41,7 @@ var core = require('@dnd-kit/core');
|
|
|
41
41
|
var sortable = require('@dnd-kit/sortable');
|
|
42
42
|
var utilities = require('@dnd-kit/utilities');
|
|
43
43
|
var react = require('@xyflow/react');
|
|
44
|
-
var
|
|
44
|
+
var THREE3 = require('three');
|
|
45
45
|
var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
|
|
46
46
|
var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
47
47
|
var GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader');
|
|
@@ -94,7 +94,7 @@ var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
|
94
94
|
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
95
95
|
var remarkMath__default = /*#__PURE__*/_interopDefault(remarkMath);
|
|
96
96
|
var rehypeKatex__default = /*#__PURE__*/_interopDefault(rehypeKatex);
|
|
97
|
-
var
|
|
97
|
+
var THREE3__namespace = /*#__PURE__*/_interopNamespace(THREE3);
|
|
98
98
|
|
|
99
99
|
var __defProp = Object.defineProperty;
|
|
100
100
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -9419,6 +9419,291 @@ var init_useCamera = __esm({
|
|
|
9419
9419
|
}
|
|
9420
9420
|
});
|
|
9421
9421
|
|
|
9422
|
+
// components/game/organisms/utils/spriteSheetConstants.ts
|
|
9423
|
+
exports.SHEET_COLUMNS = void 0; exports.SPRITE_SHEET_LAYOUT = void 0;
|
|
9424
|
+
var init_spriteSheetConstants = __esm({
|
|
9425
|
+
"components/game/organisms/utils/spriteSheetConstants.ts"() {
|
|
9426
|
+
exports.SHEET_COLUMNS = 8;
|
|
9427
|
+
exports.SPRITE_SHEET_LAYOUT = {
|
|
9428
|
+
idle: { row: 0, frames: 4, frameRate: 6, loop: true },
|
|
9429
|
+
walk: { row: 1, frames: 8, frameRate: 10, loop: true },
|
|
9430
|
+
attack: { row: 2, frames: 6, frameRate: 12, loop: false },
|
|
9431
|
+
hit: { row: 3, frames: 3, frameRate: 8, loop: false },
|
|
9432
|
+
death: { row: 4, frames: 6, frameRate: 8, loop: false }
|
|
9433
|
+
};
|
|
9434
|
+
}
|
|
9435
|
+
});
|
|
9436
|
+
|
|
9437
|
+
// components/game/organisms/utils/spriteAnimation.ts
|
|
9438
|
+
function inferDirection(dx, dy) {
|
|
9439
|
+
if (dx === 0 && dy === 0) return "se";
|
|
9440
|
+
if (dx >= 0 && dy >= 0) return "se";
|
|
9441
|
+
if (dx <= 0 && dy >= 0) return "sw";
|
|
9442
|
+
if (dx >= 0 && dy <= 0) return "ne";
|
|
9443
|
+
return "nw";
|
|
9444
|
+
}
|
|
9445
|
+
function resolveSheetDirection(facing) {
|
|
9446
|
+
switch (facing) {
|
|
9447
|
+
case "se":
|
|
9448
|
+
return { sheetDir: "se", flipX: false };
|
|
9449
|
+
case "sw":
|
|
9450
|
+
return { sheetDir: "sw", flipX: false };
|
|
9451
|
+
case "ne":
|
|
9452
|
+
return { sheetDir: "sw", flipX: true };
|
|
9453
|
+
case "nw":
|
|
9454
|
+
return { sheetDir: "se", flipX: true };
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
function frameRect(frame, row, columns, frameWidth, frameHeight) {
|
|
9458
|
+
return {
|
|
9459
|
+
sx: frame % columns * frameWidth,
|
|
9460
|
+
sy: row * frameHeight,
|
|
9461
|
+
sw: frameWidth,
|
|
9462
|
+
sh: frameHeight
|
|
9463
|
+
};
|
|
9464
|
+
}
|
|
9465
|
+
function getCurrentFrameFromDef(def, elapsed) {
|
|
9466
|
+
const frameDuration = 1e3 / def.frameRate;
|
|
9467
|
+
const totalDuration = def.frames * frameDuration;
|
|
9468
|
+
if (def.loop) {
|
|
9469
|
+
const frame2 = Math.floor(elapsed % totalDuration / frameDuration);
|
|
9470
|
+
return { frame: frame2, finished: false };
|
|
9471
|
+
}
|
|
9472
|
+
if (elapsed >= totalDuration) {
|
|
9473
|
+
return { frame: def.frames - 1, finished: true };
|
|
9474
|
+
}
|
|
9475
|
+
const frame = Math.floor(elapsed / frameDuration);
|
|
9476
|
+
return { frame, finished: false };
|
|
9477
|
+
}
|
|
9478
|
+
function getCurrentFrame(animName, elapsed) {
|
|
9479
|
+
return getCurrentFrameFromDef(exports.SPRITE_SHEET_LAYOUT[animName], elapsed);
|
|
9480
|
+
}
|
|
9481
|
+
function resolveFrame(sheetUrls, frameDims, animState) {
|
|
9482
|
+
if (!sheetUrls) return null;
|
|
9483
|
+
const { sheetDir, flipX } = resolveSheetDirection(animState.direction);
|
|
9484
|
+
const sheetUrl = sheetUrls[sheetDir];
|
|
9485
|
+
if (!sheetUrl) return null;
|
|
9486
|
+
const def = exports.SPRITE_SHEET_LAYOUT[animState.animation];
|
|
9487
|
+
const { frame } = getCurrentFrame(animState.animation, animState.elapsed);
|
|
9488
|
+
const rect = frameRect(frame, def.row, def.frames, frameDims.width, frameDims.height);
|
|
9489
|
+
return {
|
|
9490
|
+
sheetUrl,
|
|
9491
|
+
sx: rect.sx,
|
|
9492
|
+
sy: rect.sy,
|
|
9493
|
+
sw: rect.sw,
|
|
9494
|
+
sh: rect.sh,
|
|
9495
|
+
flipX
|
|
9496
|
+
};
|
|
9497
|
+
}
|
|
9498
|
+
function createUnitAnimationState(unitId) {
|
|
9499
|
+
return {
|
|
9500
|
+
unitId,
|
|
9501
|
+
animation: "idle",
|
|
9502
|
+
direction: "se",
|
|
9503
|
+
frame: 0,
|
|
9504
|
+
elapsed: 0,
|
|
9505
|
+
queuedAnimation: null,
|
|
9506
|
+
finished: false
|
|
9507
|
+
};
|
|
9508
|
+
}
|
|
9509
|
+
function transitionAnimation(state, newAnim, direction) {
|
|
9510
|
+
if (state.animation === "death" && state.finished) return state;
|
|
9511
|
+
if (state.animation === newAnim && exports.SPRITE_SHEET_LAYOUT[newAnim].loop) {
|
|
9512
|
+
return direction ? { ...state, direction } : state;
|
|
9513
|
+
}
|
|
9514
|
+
return {
|
|
9515
|
+
...state,
|
|
9516
|
+
animation: newAnim,
|
|
9517
|
+
direction: direction ?? state.direction,
|
|
9518
|
+
frame: 0,
|
|
9519
|
+
elapsed: 0,
|
|
9520
|
+
queuedAnimation: null,
|
|
9521
|
+
finished: false
|
|
9522
|
+
};
|
|
9523
|
+
}
|
|
9524
|
+
function tickAnimationState(state, deltaMs) {
|
|
9525
|
+
const newElapsed = state.elapsed + deltaMs;
|
|
9526
|
+
const { frame, finished } = getCurrentFrame(state.animation, newElapsed);
|
|
9527
|
+
const def = exports.SPRITE_SHEET_LAYOUT[state.animation];
|
|
9528
|
+
if (finished && !def.loop && !state.finished) {
|
|
9529
|
+
if (state.animation === "death") {
|
|
9530
|
+
return { ...state, elapsed: newElapsed, frame, finished: true };
|
|
9531
|
+
}
|
|
9532
|
+
const nextAnim = state.queuedAnimation ?? "idle";
|
|
9533
|
+
return {
|
|
9534
|
+
...state,
|
|
9535
|
+
animation: nextAnim,
|
|
9536
|
+
elapsed: 0,
|
|
9537
|
+
frame: 0,
|
|
9538
|
+
queuedAnimation: null,
|
|
9539
|
+
finished: false
|
|
9540
|
+
};
|
|
9541
|
+
}
|
|
9542
|
+
return { ...state, elapsed: newElapsed, frame, finished };
|
|
9543
|
+
}
|
|
9544
|
+
var init_spriteAnimation = __esm({
|
|
9545
|
+
"components/game/organisms/utils/spriteAnimation.ts"() {
|
|
9546
|
+
init_spriteSheetConstants();
|
|
9547
|
+
}
|
|
9548
|
+
});
|
|
9549
|
+
function unitAtlasUrl(unit) {
|
|
9550
|
+
if (unit.spriteSheet) return unit.spriteSheet;
|
|
9551
|
+
const sprite = unit.sprite;
|
|
9552
|
+
if (!sprite) return null;
|
|
9553
|
+
const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
|
|
9554
|
+
if (!match) return null;
|
|
9555
|
+
return `${match[1]}.json`;
|
|
9556
|
+
}
|
|
9557
|
+
function resolveSheetUrl(atlasUrl, relativeSheetPath) {
|
|
9558
|
+
try {
|
|
9559
|
+
return new URL(relativeSheetPath, atlasUrl).toString();
|
|
9560
|
+
} catch {
|
|
9561
|
+
const base = atlasUrl.slice(0, atlasUrl.lastIndexOf("/") + 1);
|
|
9562
|
+
return `${base}${relativeSheetPath.replace(/^\.\//, "")}`;
|
|
9563
|
+
}
|
|
9564
|
+
}
|
|
9565
|
+
function useUnitSpriteAtlas(units) {
|
|
9566
|
+
const atlasCacheRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
9567
|
+
const loadingRef = React76.useRef(/* @__PURE__ */ new Set());
|
|
9568
|
+
const [pendingCount, setPendingCount] = React76.useState(0);
|
|
9569
|
+
const [, forceTick] = React76.useState(0);
|
|
9570
|
+
const animStatesRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
9571
|
+
const lastTickRef = React76.useRef(0);
|
|
9572
|
+
const rafRef = React76.useRef(0);
|
|
9573
|
+
const atlasUrls = React76.useMemo(() => {
|
|
9574
|
+
const set = /* @__PURE__ */ new Set();
|
|
9575
|
+
for (const unit of units) {
|
|
9576
|
+
const url = unitAtlasUrl(unit);
|
|
9577
|
+
if (url) set.add(url);
|
|
9578
|
+
}
|
|
9579
|
+
return [...set];
|
|
9580
|
+
}, [units]);
|
|
9581
|
+
React76.useEffect(() => {
|
|
9582
|
+
const cache = atlasCacheRef.current;
|
|
9583
|
+
const loading = loadingRef.current;
|
|
9584
|
+
const toLoad = atlasUrls.filter((url) => !cache.has(url) && !loading.has(url));
|
|
9585
|
+
if (toLoad.length === 0) return;
|
|
9586
|
+
let cancelled = false;
|
|
9587
|
+
setPendingCount((prev) => prev + toLoad.length);
|
|
9588
|
+
for (const url of toLoad) {
|
|
9589
|
+
loading.add(url);
|
|
9590
|
+
fetch(url).then((res) => res.ok ? res.json() : Promise.reject(new Error(String(res.status)))).then((atlas) => {
|
|
9591
|
+
if (cancelled) return;
|
|
9592
|
+
cache.set(url, atlas);
|
|
9593
|
+
}).catch(() => {
|
|
9594
|
+
}).finally(() => {
|
|
9595
|
+
if (cancelled) return;
|
|
9596
|
+
loading.delete(url);
|
|
9597
|
+
setPendingCount((prev) => Math.max(0, prev - 1));
|
|
9598
|
+
forceTick((n) => n + 1);
|
|
9599
|
+
});
|
|
9600
|
+
}
|
|
9601
|
+
return () => {
|
|
9602
|
+
cancelled = true;
|
|
9603
|
+
};
|
|
9604
|
+
}, [atlasUrls]);
|
|
9605
|
+
const sheetUrls = React76.useMemo(() => {
|
|
9606
|
+
const urls = /* @__PURE__ */ new Set();
|
|
9607
|
+
for (const unit of units) {
|
|
9608
|
+
const atlasUrl = unitAtlasUrl(unit);
|
|
9609
|
+
if (!atlasUrl) continue;
|
|
9610
|
+
const atlas = atlasCacheRef.current.get(atlasUrl);
|
|
9611
|
+
if (!atlas) continue;
|
|
9612
|
+
for (const rel of Object.values(atlas.sheets)) {
|
|
9613
|
+
if (rel) urls.add(resolveSheetUrl(atlasUrl, rel));
|
|
9614
|
+
}
|
|
9615
|
+
}
|
|
9616
|
+
return [...urls];
|
|
9617
|
+
}, [units, pendingCount]);
|
|
9618
|
+
React76.useEffect(() => {
|
|
9619
|
+
const hasAtlasUnits = units.some((u) => unitAtlasUrl(u) !== null);
|
|
9620
|
+
if (!hasAtlasUnits) return;
|
|
9621
|
+
let running = true;
|
|
9622
|
+
const tick = (ts) => {
|
|
9623
|
+
if (!running) return;
|
|
9624
|
+
const last = lastTickRef.current || ts;
|
|
9625
|
+
const delta = ts - last;
|
|
9626
|
+
lastTickRef.current = ts;
|
|
9627
|
+
const states = animStatesRef.current;
|
|
9628
|
+
const currentIds = /* @__PURE__ */ new Set();
|
|
9629
|
+
for (const unit of units) {
|
|
9630
|
+
if (unitAtlasUrl(unit) === null) continue;
|
|
9631
|
+
currentIds.add(unit.id);
|
|
9632
|
+
let state = states.get(unit.id);
|
|
9633
|
+
if (!state) {
|
|
9634
|
+
state = { animation: "idle", direction: "se", elapsed: 0, walkHold: 0, prev: null };
|
|
9635
|
+
states.set(unit.id, state);
|
|
9636
|
+
}
|
|
9637
|
+
const posX = unit.position?.x ?? unit.x ?? 0;
|
|
9638
|
+
const posY = unit.position?.y ?? unit.y ?? 0;
|
|
9639
|
+
if (state.prev) {
|
|
9640
|
+
const dx = posX - state.prev.x;
|
|
9641
|
+
const dy = posY - state.prev.y;
|
|
9642
|
+
if (dx !== 0 || dy !== 0) {
|
|
9643
|
+
state.animation = "walk";
|
|
9644
|
+
state.direction = inferDirection(dx, dy);
|
|
9645
|
+
state.walkHold = WALK_HOLD_MS;
|
|
9646
|
+
} else if (state.animation === "walk") {
|
|
9647
|
+
state.walkHold -= delta;
|
|
9648
|
+
if (state.walkHold <= 0) state.animation = "idle";
|
|
9649
|
+
}
|
|
9650
|
+
}
|
|
9651
|
+
state.prev = { x: posX, y: posY };
|
|
9652
|
+
state.elapsed += delta;
|
|
9653
|
+
}
|
|
9654
|
+
for (const id of states.keys()) {
|
|
9655
|
+
if (!currentIds.has(id)) states.delete(id);
|
|
9656
|
+
}
|
|
9657
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
9658
|
+
};
|
|
9659
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
9660
|
+
return () => {
|
|
9661
|
+
running = false;
|
|
9662
|
+
cancelAnimationFrame(rafRef.current);
|
|
9663
|
+
lastTickRef.current = 0;
|
|
9664
|
+
};
|
|
9665
|
+
}, [units]);
|
|
9666
|
+
const resolveUnitFrame = React76.useCallback((unitId) => {
|
|
9667
|
+
const unit = units.find((u) => u.id === unitId);
|
|
9668
|
+
if (!unit) return null;
|
|
9669
|
+
const atlasUrl = unitAtlasUrl(unit);
|
|
9670
|
+
if (!atlasUrl) return null;
|
|
9671
|
+
const atlas = atlasCacheRef.current.get(atlasUrl);
|
|
9672
|
+
if (!atlas) return null;
|
|
9673
|
+
const state = animStatesRef.current.get(unitId);
|
|
9674
|
+
const animation = state?.animation ?? "idle";
|
|
9675
|
+
const direction = state?.direction ?? "se";
|
|
9676
|
+
const elapsed = state?.elapsed ?? 0;
|
|
9677
|
+
const def = atlas.animations[animation] ?? atlas.animations.idle;
|
|
9678
|
+
if (!def) return null;
|
|
9679
|
+
const { sheetDir, flipX } = resolveSheetDirection(direction);
|
|
9680
|
+
const rel = atlas.sheets[sheetDir] ?? atlas.sheets.se ?? atlas.sheets.sw;
|
|
9681
|
+
if (!rel) return null;
|
|
9682
|
+
const sheetUrl = resolveSheetUrl(atlasUrl, rel);
|
|
9683
|
+
const isIdle = animation === "idle";
|
|
9684
|
+
const frame = isIdle ? 0 : getCurrentFrameFromDef(def, elapsed).frame;
|
|
9685
|
+
const rect = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
|
|
9686
|
+
return {
|
|
9687
|
+
sheetUrl,
|
|
9688
|
+
sx: rect.sx,
|
|
9689
|
+
sy: rect.sy,
|
|
9690
|
+
sw: rect.sw,
|
|
9691
|
+
sh: rect.sh,
|
|
9692
|
+
flipX,
|
|
9693
|
+
applyBreathing: isIdle
|
|
9694
|
+
};
|
|
9695
|
+
}, [units]);
|
|
9696
|
+
return { sheetUrls, resolveUnitFrame, pendingCount };
|
|
9697
|
+
}
|
|
9698
|
+
var WALK_HOLD_MS;
|
|
9699
|
+
var init_useUnitSpriteAtlas = __esm({
|
|
9700
|
+
"components/game/molecules/useUnitSpriteAtlas.ts"() {
|
|
9701
|
+
"use client";
|
|
9702
|
+
init_spriteAnimation();
|
|
9703
|
+
WALK_HOLD_MS = 600;
|
|
9704
|
+
}
|
|
9705
|
+
});
|
|
9706
|
+
|
|
9422
9707
|
// components/game/organisms/utils/isometric.ts
|
|
9423
9708
|
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
9424
9709
|
const scaledTileWidth = exports.TILE_WIDTH * scale;
|
|
@@ -9532,6 +9817,10 @@ function IsometricCanvas({
|
|
|
9532
9817
|
() => unitsProp.map((u) => u.position ? u : { ...u, position: { x: u.x ?? 0, y: u.y ?? 0 } }),
|
|
9533
9818
|
[unitsProp]
|
|
9534
9819
|
);
|
|
9820
|
+
const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal, pendingCount: atlasPending } = useUnitSpriteAtlas(units);
|
|
9821
|
+
const resolveFrameForUnit = React76.useCallback((unitId) => {
|
|
9822
|
+
return resolveUnitFrame?.(unitId) ?? resolveUnitFrameInternal(unitId);
|
|
9823
|
+
}, [resolveUnitFrame, resolveUnitFrameInternal]);
|
|
9535
9824
|
const features = React76.useMemo(
|
|
9536
9825
|
() => featuresProp.map((f3) => {
|
|
9537
9826
|
if (f3.type) return f3;
|
|
@@ -9615,9 +9904,10 @@ function IsometricCanvas({
|
|
|
9615
9904
|
}
|
|
9616
9905
|
}
|
|
9617
9906
|
if (effectSpriteUrls) urls.push(...effectSpriteUrls);
|
|
9907
|
+
if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
|
|
9618
9908
|
if (backgroundImage) urls.push(backgroundImage);
|
|
9619
9909
|
return [...new Set(urls.filter(Boolean))];
|
|
9620
|
-
}, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, backgroundImage, assetManifest, resolveManifestUrl]);
|
|
9910
|
+
}, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl]);
|
|
9621
9911
|
const { getImage, pendingCount } = useImageCache(spriteUrls);
|
|
9622
9912
|
React76.useEffect(() => {
|
|
9623
9913
|
if (typeof window === "undefined") return;
|
|
@@ -9905,7 +10195,7 @@ function IsometricCanvas({
|
|
|
9905
10195
|
ctx.lineWidth = 3;
|
|
9906
10196
|
ctx.stroke();
|
|
9907
10197
|
}
|
|
9908
|
-
const frame =
|
|
10198
|
+
const frame = resolveFrameForUnit(unit.id);
|
|
9909
10199
|
const frameImg = frame ? getImage(frame.sheetUrl) : null;
|
|
9910
10200
|
if (frame && frameImg) {
|
|
9911
10201
|
const frameAr = frame.sw / frame.sh;
|
|
@@ -10015,7 +10305,7 @@ function IsometricCanvas({
|
|
|
10015
10305
|
resolveTerrainSpriteUrl,
|
|
10016
10306
|
resolveFeatureSpriteUrl,
|
|
10017
10307
|
resolveUnitSpriteUrl,
|
|
10018
|
-
|
|
10308
|
+
resolveFrameForUnit,
|
|
10019
10309
|
getImage,
|
|
10020
10310
|
gridWidth,
|
|
10021
10311
|
gridHeight,
|
|
@@ -10047,7 +10337,7 @@ function IsometricCanvas({
|
|
|
10047
10337
|
};
|
|
10048
10338
|
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
10049
10339
|
React76.useEffect(() => {
|
|
10050
|
-
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0;
|
|
10340
|
+
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
10051
10341
|
draw(animTimeRef.current);
|
|
10052
10342
|
if (!hasAnimations) return;
|
|
10053
10343
|
let running = true;
|
|
@@ -10063,7 +10353,7 @@ function IsometricCanvas({
|
|
|
10063
10353
|
running = false;
|
|
10064
10354
|
cancelAnimationFrame(rafIdRef.current);
|
|
10065
10355
|
};
|
|
10066
|
-
}, [draw, units.length, validMoves.length, attackTargets.length, selectedUnitId, hasActiveEffects2, pendingCount, lerpToTarget, targetCameraRef]);
|
|
10356
|
+
}, [draw, units.length, validMoves.length, attackTargets.length, selectedUnitId, hasActiveEffects2, pendingCount, atlasPending, lerpToTarget, targetCameraRef]);
|
|
10067
10357
|
const handleMouseMoveWithCamera = React76.useCallback((e) => {
|
|
10068
10358
|
if (enableCamera) {
|
|
10069
10359
|
const wasPanning = handleMouseMove(e, () => draw(animTimeRef.current));
|
|
@@ -10208,6 +10498,7 @@ var init_IsometricCanvas = __esm({
|
|
|
10208
10498
|
init_ErrorState();
|
|
10209
10499
|
init_useImageCache();
|
|
10210
10500
|
init_useCamera();
|
|
10501
|
+
init_useUnitSpriteAtlas();
|
|
10211
10502
|
init_verificationRegistry();
|
|
10212
10503
|
init_isometric();
|
|
10213
10504
|
IsometricCanvas.displayName = "IsometricCanvas";
|
|
@@ -29578,13 +29869,13 @@ var init_MapView = __esm({
|
|
|
29578
29869
|
shadowSize: [41, 41]
|
|
29579
29870
|
});
|
|
29580
29871
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29581
|
-
const { useEffect:
|
|
29872
|
+
const { useEffect: useEffect80, useRef: useRef78, useCallback: useCallback120, useState: useState110 } = React76__namespace.default;
|
|
29582
29873
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
29583
29874
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
29584
29875
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
29585
29876
|
const map = useMap();
|
|
29586
|
-
const prevRef =
|
|
29587
|
-
|
|
29877
|
+
const prevRef = useRef78({ centerLat, centerLng, zoom });
|
|
29878
|
+
useEffect80(() => {
|
|
29588
29879
|
const prev = prevRef.current;
|
|
29589
29880
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
29590
29881
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -29595,7 +29886,7 @@ var init_MapView = __esm({
|
|
|
29595
29886
|
}
|
|
29596
29887
|
function MapClickHandler({ onMapClick }) {
|
|
29597
29888
|
const map = useMap();
|
|
29598
|
-
|
|
29889
|
+
useEffect80(() => {
|
|
29599
29890
|
if (!onMapClick) return;
|
|
29600
29891
|
const handler = (e) => {
|
|
29601
29892
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -29623,8 +29914,8 @@ var init_MapView = __esm({
|
|
|
29623
29914
|
showAttribution = true
|
|
29624
29915
|
}) {
|
|
29625
29916
|
const eventBus = useEventBus3();
|
|
29626
|
-
const [clickedPosition, setClickedPosition] =
|
|
29627
|
-
const handleMapClick =
|
|
29917
|
+
const [clickedPosition, setClickedPosition] = useState110(null);
|
|
29918
|
+
const handleMapClick = useCallback120((lat, lng) => {
|
|
29628
29919
|
if (showClickedPin) {
|
|
29629
29920
|
setClickedPosition({ lat, lng });
|
|
29630
29921
|
}
|
|
@@ -29633,7 +29924,7 @@ var init_MapView = __esm({
|
|
|
29633
29924
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
29634
29925
|
}
|
|
29635
29926
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
29636
|
-
const handleMarkerClick =
|
|
29927
|
+
const handleMarkerClick = useCallback120((marker) => {
|
|
29637
29928
|
onMarkerClick?.(marker);
|
|
29638
29929
|
if (markerClickEvent) {
|
|
29639
29930
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -41678,7 +41969,7 @@ var init_AssetLoader = __esm({
|
|
|
41678
41969
|
__publicField(this, "textureCache");
|
|
41679
41970
|
__publicField(this, "loadingPromises");
|
|
41680
41971
|
this.objLoader = new OBJLoader_js.OBJLoader();
|
|
41681
|
-
this.textureLoader = new
|
|
41972
|
+
this.textureLoader = new THREE3__namespace.TextureLoader();
|
|
41682
41973
|
this.modelCache = /* @__PURE__ */ new Map();
|
|
41683
41974
|
this.textureCache = /* @__PURE__ */ new Map();
|
|
41684
41975
|
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
@@ -41752,7 +42043,7 @@ var init_AssetLoader = __esm({
|
|
|
41752
42043
|
return this.loadingPromises.get(`texture:${url}`);
|
|
41753
42044
|
}
|
|
41754
42045
|
const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
|
|
41755
|
-
texture.colorSpace =
|
|
42046
|
+
texture.colorSpace = THREE3__namespace.SRGBColorSpace;
|
|
41756
42047
|
this.textureCache.set(url, texture);
|
|
41757
42048
|
this.loadingPromises.delete(`texture:${url}`);
|
|
41758
42049
|
return texture;
|
|
@@ -41826,7 +42117,7 @@ var init_AssetLoader = __esm({
|
|
|
41826
42117
|
});
|
|
41827
42118
|
this.modelCache.forEach((model) => {
|
|
41828
42119
|
model.scene.traverse((child) => {
|
|
41829
|
-
if (child instanceof
|
|
42120
|
+
if (child instanceof THREE3__namespace.Mesh) {
|
|
41830
42121
|
child.geometry.dispose();
|
|
41831
42122
|
if (Array.isArray(child.material)) {
|
|
41832
42123
|
child.material.forEach((m) => m.dispose());
|
|
@@ -42382,7 +42673,7 @@ function ModelLoader({
|
|
|
42382
42673
|
if (!loadedModel) return null;
|
|
42383
42674
|
const cloned = loadedModel.clone();
|
|
42384
42675
|
cloned.traverse((child) => {
|
|
42385
|
-
if (child instanceof
|
|
42676
|
+
if (child instanceof THREE3__namespace.Mesh) {
|
|
42386
42677
|
child.castShadow = castShadow;
|
|
42387
42678
|
child.receiveShadow = receiveShadow;
|
|
42388
42679
|
}
|
|
@@ -42496,6 +42787,47 @@ function CameraController({
|
|
|
42496
42787
|
}, [camera.position, onCameraChange]);
|
|
42497
42788
|
return null;
|
|
42498
42789
|
}
|
|
42790
|
+
function UnitSpriteBillboard({
|
|
42791
|
+
sheetUrl,
|
|
42792
|
+
resolveFrame: resolveFrame2,
|
|
42793
|
+
height = 1.2
|
|
42794
|
+
}) {
|
|
42795
|
+
const texture = fiber.useLoader(THREE3__namespace.TextureLoader, sheetUrl);
|
|
42796
|
+
const meshRef = React76.useRef(null);
|
|
42797
|
+
const matRef = React76.useRef(null);
|
|
42798
|
+
const [aspect, setAspect] = React76.useState(1);
|
|
42799
|
+
fiber.useFrame(() => {
|
|
42800
|
+
const frame = resolveFrame2();
|
|
42801
|
+
if (!frame || !texture.image) return;
|
|
42802
|
+
const imgW = texture.image.width;
|
|
42803
|
+
const imgH = texture.image.height;
|
|
42804
|
+
if (!imgW || !imgH) return;
|
|
42805
|
+
texture.repeat.set((frame.flipX ? -1 : 1) * (frame.sw / imgW), frame.sh / imgH);
|
|
42806
|
+
texture.offset.set(
|
|
42807
|
+
frame.flipX ? (frame.sx + frame.sw) / imgW : frame.sx / imgW,
|
|
42808
|
+
1 - (frame.sy + frame.sh) / imgH
|
|
42809
|
+
);
|
|
42810
|
+
texture.magFilter = THREE3__namespace.NearestFilter;
|
|
42811
|
+
texture.minFilter = THREE3__namespace.NearestFilter;
|
|
42812
|
+
texture.needsUpdate = true;
|
|
42813
|
+
const nextAspect = frame.sw / frame.sh;
|
|
42814
|
+
if (Math.abs(nextAspect - aspect) > 1e-3) setAspect(nextAspect);
|
|
42815
|
+
if (matRef.current) matRef.current.needsUpdate = true;
|
|
42816
|
+
});
|
|
42817
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("mesh", { ref: meshRef, position: [0, height / 2, 0], children: [
|
|
42818
|
+
/* @__PURE__ */ jsxRuntime.jsx("planeGeometry", { args: [height * aspect, height] }),
|
|
42819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
42820
|
+
"meshBasicMaterial",
|
|
42821
|
+
{
|
|
42822
|
+
ref: matRef,
|
|
42823
|
+
map: texture,
|
|
42824
|
+
transparent: true,
|
|
42825
|
+
alphaTest: 0.1,
|
|
42826
|
+
side: THREE3__namespace.DoubleSide
|
|
42827
|
+
}
|
|
42828
|
+
)
|
|
42829
|
+
] });
|
|
42830
|
+
}
|
|
42499
42831
|
var DEFAULT_GRID_CONFIG, GameCanvas3D;
|
|
42500
42832
|
var init_GameCanvas3D2 = __esm({
|
|
42501
42833
|
"components/game/molecules/GameCanvas3D.tsx"() {
|
|
@@ -42506,6 +42838,7 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42506
42838
|
init_Canvas3DLoadingState2();
|
|
42507
42839
|
init_Canvas3DErrorBoundary2();
|
|
42508
42840
|
init_ModelLoader();
|
|
42841
|
+
init_useUnitSpriteAtlas();
|
|
42509
42842
|
init_cn();
|
|
42510
42843
|
init_GameCanvas3D();
|
|
42511
42844
|
DEFAULT_GRID_CONFIG = {
|
|
@@ -42562,8 +42895,10 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42562
42895
|
const controlsRef = React76.useRef(null);
|
|
42563
42896
|
const [hoveredTile, setHoveredTile] = React76.useState(null);
|
|
42564
42897
|
const [internalError, setInternalError] = React76.useState(null);
|
|
42898
|
+
const { sheetUrls: atlasSheetUrls, resolveUnitFrame } = useUnitSpriteAtlas(units);
|
|
42899
|
+
const preloadUrls = React76.useMemo(() => [...preloadAssets, ...atlasSheetUrls], [preloadAssets, atlasSheetUrls]);
|
|
42565
42900
|
const { isLoading: assetsLoading, progress, loaded, total } = useAssetLoader({
|
|
42566
|
-
preloadUrls
|
|
42901
|
+
preloadUrls,
|
|
42567
42902
|
loader: customAssetLoader
|
|
42568
42903
|
});
|
|
42569
42904
|
const eventHandlers = useGameCanvas3DEvents({
|
|
@@ -42622,7 +42957,7 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42622
42957
|
getCameraPosition: () => {
|
|
42623
42958
|
if (controlsRef.current) {
|
|
42624
42959
|
const pos = controlsRef.current.object.position;
|
|
42625
|
-
return new
|
|
42960
|
+
return new THREE3__namespace.Vector3(pos.x, pos.y, pos.z);
|
|
42626
42961
|
}
|
|
42627
42962
|
return null;
|
|
42628
42963
|
},
|
|
@@ -42774,6 +43109,8 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42774
43109
|
({ unit, position }) => {
|
|
42775
43110
|
const isSelected = selectedUnitId === unit.id;
|
|
42776
43111
|
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
43112
|
+
const hasAtlas = unitAtlasUrl(unit) !== null;
|
|
43113
|
+
const initialFrame = hasAtlas ? resolveUnitFrame(unit.id) : null;
|
|
42777
43114
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
42778
43115
|
"group",
|
|
42779
43116
|
{
|
|
@@ -42785,7 +43122,16 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42785
43122
|
/* @__PURE__ */ jsxRuntime.jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
|
|
42786
43123
|
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
|
|
42787
43124
|
] }),
|
|
42788
|
-
|
|
43125
|
+
hasAtlas && initialFrame ? (
|
|
43126
|
+
/* Animated sprite-sheet billboard — single cropped frame, by state */
|
|
43127
|
+
/* @__PURE__ */ jsxRuntime.jsx(drei.Billboard, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
43128
|
+
UnitSpriteBillboard,
|
|
43129
|
+
{
|
|
43130
|
+
sheetUrl: initialFrame.sheetUrl,
|
|
43131
|
+
resolveFrame: () => resolveUnitFrame(unit.id)
|
|
43132
|
+
}
|
|
43133
|
+
) })
|
|
43134
|
+
) : unit.modelUrl ? (
|
|
42789
43135
|
/* GLB unit model (box fallback while loading / on error) */
|
|
42790
43136
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
42791
43137
|
ModelLoader,
|
|
@@ -42839,7 +43185,7 @@ var init_GameCanvas3D2 = __esm({
|
|
|
42839
43185
|
}
|
|
42840
43186
|
);
|
|
42841
43187
|
},
|
|
42842
|
-
[selectedUnitId, handleUnitClick]
|
|
43188
|
+
[selectedUnitId, handleUnitClick, resolveUnitFrame]
|
|
42843
43189
|
);
|
|
42844
43190
|
const DefaultFeatureRenderer = React76.useCallback(
|
|
42845
43191
|
({
|
|
@@ -48543,12 +48889,8 @@ function Sprite({
|
|
|
48543
48889
|
}) {
|
|
48544
48890
|
const eventBus = useEventBus();
|
|
48545
48891
|
const sourcePosition = React76.useMemo(() => {
|
|
48546
|
-
const
|
|
48547
|
-
|
|
48548
|
-
return {
|
|
48549
|
-
x: frameX * frameWidth,
|
|
48550
|
-
y: frameY * frameHeight
|
|
48551
|
-
};
|
|
48892
|
+
const { sx, sy } = frameRect(frame, Math.floor(frame / columns), columns, frameWidth, frameHeight);
|
|
48893
|
+
return { x: sx, y: sy };
|
|
48552
48894
|
}, [frame, columns, frameWidth, frameHeight]);
|
|
48553
48895
|
const transform = React76.useMemo(() => {
|
|
48554
48896
|
const transforms = [
|
|
@@ -48606,8 +48948,7 @@ function drawSprite(ctx, image, props) {
|
|
|
48606
48948
|
opacity = 1,
|
|
48607
48949
|
columns = 16
|
|
48608
48950
|
} = props;
|
|
48609
|
-
const sourceX = frame
|
|
48610
|
-
const sourceY = Math.floor(frame / columns) * frameHeight;
|
|
48951
|
+
const { sx: sourceX, sy: sourceY } = frameRect(frame, Math.floor(frame / columns), columns, frameWidth, frameHeight);
|
|
48611
48952
|
ctx.save();
|
|
48612
48953
|
ctx.globalAlpha = opacity;
|
|
48613
48954
|
ctx.translate(x + frameWidth / 2, y + frameHeight / 2);
|
|
@@ -48632,6 +48973,7 @@ var init_Sprite = __esm({
|
|
|
48632
48973
|
"components/game/atoms/Sprite.tsx"() {
|
|
48633
48974
|
"use client";
|
|
48634
48975
|
init_useEventBus();
|
|
48976
|
+
init_spriteAnimation();
|
|
48635
48977
|
}
|
|
48636
48978
|
});
|
|
48637
48979
|
exports.StatCard = void 0;
|
|
@@ -52639,121 +52981,15 @@ init_useGameAudio();
|
|
|
52639
52981
|
init_useImageCache();
|
|
52640
52982
|
init_useCamera();
|
|
52641
52983
|
|
|
52642
|
-
// components/game/organisms/utils/spriteSheetConstants.ts
|
|
52643
|
-
var SHEET_COLUMNS = 8;
|
|
52644
|
-
var SPRITE_SHEET_LAYOUT = {
|
|
52645
|
-
idle: { row: 0, frames: 4, frameRate: 6, loop: true },
|
|
52646
|
-
walk: { row: 1, frames: 8, frameRate: 10, loop: true },
|
|
52647
|
-
attack: { row: 2, frames: 6, frameRate: 12, loop: false },
|
|
52648
|
-
hit: { row: 3, frames: 3, frameRate: 8, loop: false },
|
|
52649
|
-
death: { row: 4, frames: 6, frameRate: 8, loop: false }
|
|
52650
|
-
};
|
|
52651
|
-
|
|
52652
|
-
// components/game/organisms/utils/spriteAnimation.ts
|
|
52653
|
-
function inferDirection(dx, dy) {
|
|
52654
|
-
if (dx === 0 && dy === 0) return "se";
|
|
52655
|
-
if (dx >= 0 && dy >= 0) return "se";
|
|
52656
|
-
if (dx <= 0 && dy >= 0) return "sw";
|
|
52657
|
-
if (dx >= 0 && dy <= 0) return "ne";
|
|
52658
|
-
return "nw";
|
|
52659
|
-
}
|
|
52660
|
-
function resolveSheetDirection(facing) {
|
|
52661
|
-
switch (facing) {
|
|
52662
|
-
case "se":
|
|
52663
|
-
return { sheetDir: "se", flipX: false };
|
|
52664
|
-
case "sw":
|
|
52665
|
-
return { sheetDir: "sw", flipX: false };
|
|
52666
|
-
case "ne":
|
|
52667
|
-
return { sheetDir: "sw", flipX: true };
|
|
52668
|
-
case "nw":
|
|
52669
|
-
return { sheetDir: "se", flipX: true };
|
|
52670
|
-
}
|
|
52671
|
-
}
|
|
52672
|
-
function getCurrentFrame(animName, elapsed) {
|
|
52673
|
-
const def = SPRITE_SHEET_LAYOUT[animName];
|
|
52674
|
-
const frameDuration = 1e3 / def.frameRate;
|
|
52675
|
-
const totalDuration = def.frames * frameDuration;
|
|
52676
|
-
if (def.loop) {
|
|
52677
|
-
const frame2 = Math.floor(elapsed % totalDuration / frameDuration);
|
|
52678
|
-
return { frame: frame2, finished: false };
|
|
52679
|
-
}
|
|
52680
|
-
if (elapsed >= totalDuration) {
|
|
52681
|
-
return { frame: def.frames - 1, finished: true };
|
|
52682
|
-
}
|
|
52683
|
-
const frame = Math.floor(elapsed / frameDuration);
|
|
52684
|
-
return { frame, finished: false };
|
|
52685
|
-
}
|
|
52686
|
-
function resolveFrame(sheetUrls, frameDims, animState) {
|
|
52687
|
-
if (!sheetUrls) return null;
|
|
52688
|
-
const { sheetDir, flipX } = resolveSheetDirection(animState.direction);
|
|
52689
|
-
const sheetUrl = sheetUrls[sheetDir];
|
|
52690
|
-
if (!sheetUrl) return null;
|
|
52691
|
-
const def = SPRITE_SHEET_LAYOUT[animState.animation];
|
|
52692
|
-
const { frame } = getCurrentFrame(animState.animation, animState.elapsed);
|
|
52693
|
-
return {
|
|
52694
|
-
sheetUrl,
|
|
52695
|
-
sx: frame * frameDims.width,
|
|
52696
|
-
sy: def.row * frameDims.height,
|
|
52697
|
-
sw: frameDims.width,
|
|
52698
|
-
sh: frameDims.height,
|
|
52699
|
-
flipX
|
|
52700
|
-
};
|
|
52701
|
-
}
|
|
52702
|
-
function createUnitAnimationState(unitId) {
|
|
52703
|
-
return {
|
|
52704
|
-
unitId,
|
|
52705
|
-
animation: "idle",
|
|
52706
|
-
direction: "se",
|
|
52707
|
-
frame: 0,
|
|
52708
|
-
elapsed: 0,
|
|
52709
|
-
queuedAnimation: null,
|
|
52710
|
-
finished: false
|
|
52711
|
-
};
|
|
52712
|
-
}
|
|
52713
|
-
function transitionAnimation(state, newAnim, direction) {
|
|
52714
|
-
if (state.animation === "death" && state.finished) return state;
|
|
52715
|
-
if (state.animation === newAnim && SPRITE_SHEET_LAYOUT[newAnim].loop) {
|
|
52716
|
-
return direction ? { ...state, direction } : state;
|
|
52717
|
-
}
|
|
52718
|
-
return {
|
|
52719
|
-
...state,
|
|
52720
|
-
animation: newAnim,
|
|
52721
|
-
direction: direction ?? state.direction,
|
|
52722
|
-
frame: 0,
|
|
52723
|
-
elapsed: 0,
|
|
52724
|
-
queuedAnimation: null,
|
|
52725
|
-
finished: false
|
|
52726
|
-
};
|
|
52727
|
-
}
|
|
52728
|
-
function tickAnimationState(state, deltaMs) {
|
|
52729
|
-
const newElapsed = state.elapsed + deltaMs;
|
|
52730
|
-
const { frame, finished } = getCurrentFrame(state.animation, newElapsed);
|
|
52731
|
-
const def = SPRITE_SHEET_LAYOUT[state.animation];
|
|
52732
|
-
if (finished && !def.loop && !state.finished) {
|
|
52733
|
-
if (state.animation === "death") {
|
|
52734
|
-
return { ...state, elapsed: newElapsed, frame, finished: true };
|
|
52735
|
-
}
|
|
52736
|
-
const nextAnim = state.queuedAnimation ?? "idle";
|
|
52737
|
-
return {
|
|
52738
|
-
...state,
|
|
52739
|
-
animation: nextAnim,
|
|
52740
|
-
elapsed: 0,
|
|
52741
|
-
frame: 0,
|
|
52742
|
-
queuedAnimation: null,
|
|
52743
|
-
finished: false
|
|
52744
|
-
};
|
|
52745
|
-
}
|
|
52746
|
-
return { ...state, elapsed: newElapsed, frame, finished };
|
|
52747
|
-
}
|
|
52748
|
-
|
|
52749
52984
|
// components/game/organisms/hooks/useSpriteAnimations.ts
|
|
52985
|
+
init_spriteAnimation();
|
|
52750
52986
|
function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
|
|
52751
52987
|
const speed = options.speed ?? 1;
|
|
52752
52988
|
const animStatesRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
52753
52989
|
const prevPositionsRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
52754
52990
|
const unitDataRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
52755
52991
|
const walkHoldRef = React76.useRef(/* @__PURE__ */ new Map());
|
|
52756
|
-
const
|
|
52992
|
+
const WALK_HOLD_MS2 = 600;
|
|
52757
52993
|
const syncUnits = React76.useCallback((units, deltaMs) => {
|
|
52758
52994
|
const scaledDelta = deltaMs * speed;
|
|
52759
52995
|
const states = animStatesRef.current;
|
|
@@ -52779,7 +53015,7 @@ function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
|
|
|
52779
53015
|
const dir = inferDirection(dx, dy);
|
|
52780
53016
|
if (state.animation !== "attack" && state.animation !== "hit" && state.animation !== "death") {
|
|
52781
53017
|
state = transitionAnimation(state, "walk", dir);
|
|
52782
|
-
walkHold.set(unit.id,
|
|
53018
|
+
walkHold.set(unit.id, WALK_HOLD_MS2);
|
|
52783
53019
|
}
|
|
52784
53020
|
} else if (state.animation === "walk") {
|
|
52785
53021
|
const remaining = (walkHold.get(unit.id) ?? 0) - scaledDelta;
|
|
@@ -53112,6 +53348,8 @@ function usePhysics2D(options = {}) {
|
|
|
53112
53348
|
|
|
53113
53349
|
// components/game/organisms/index.ts
|
|
53114
53350
|
init_isometric();
|
|
53351
|
+
init_spriteAnimation();
|
|
53352
|
+
init_spriteSheetConstants();
|
|
53115
53353
|
init_BattleBoard();
|
|
53116
53354
|
init_UncontrolledBattleBoard();
|
|
53117
53355
|
init_useBattleState();
|
|
@@ -53776,8 +54014,6 @@ exports.RoguelikeBoard = RoguelikeBoard;
|
|
|
53776
54014
|
exports.RoguelikeTemplate = RoguelikeTemplate;
|
|
53777
54015
|
exports.RuleEditor = RuleEditor;
|
|
53778
54016
|
exports.RuntimeDebugger = RuntimeDebugger;
|
|
53779
|
-
exports.SHEET_COLUMNS = SHEET_COLUMNS;
|
|
53780
|
-
exports.SPRITE_SHEET_LAYOUT = SPRITE_SHEET_LAYOUT;
|
|
53781
54017
|
exports.ScoreBoard = ScoreBoard;
|
|
53782
54018
|
exports.ScoreDisplay = ScoreDisplay;
|
|
53783
54019
|
exports.SequenceBar = SequenceBar;
|