@almadar/ui 5.64.0 → 5.65.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 +84 -22
- package/dist/avl/index.js +84 -22
- package/dist/components/game/molecules/IsometricCanvas.d.ts +4 -1
- package/dist/components/game/molecules/index.d.ts +1 -0
- package/dist/components/game/organisms/HexStrategyBoard.d.ts +37 -0
- package/dist/components/game/organisms/index.d.ts +2 -0
- package/dist/components/game/organisms/utils/isometric.d.ts +20 -7
- package/dist/components/index.cjs +86 -22
- package/dist/components/index.js +86 -23
- package/dist/providers/index.cjs +84 -22
- package/dist/providers/index.js +84 -22
- package/dist/runtime/index.cjs +84 -22
- package/dist/runtime/index.js +84 -22
- package/package.json +1 -1
package/dist/providers/index.cjs
CHANGED
|
@@ -11286,16 +11286,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
11286
11286
|
});
|
|
11287
11287
|
|
|
11288
11288
|
// components/game/organisms/utils/isometric.ts
|
|
11289
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
11289
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
11290
11290
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11291
11291
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11292
|
+
if (layout === "hex") {
|
|
11293
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11294
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
11295
|
+
return { x: screenX2, y: screenY2 };
|
|
11296
|
+
}
|
|
11292
11297
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11293
11298
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
11294
11299
|
return { x: screenX, y: screenY };
|
|
11295
11300
|
}
|
|
11296
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
11301
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
11297
11302
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11298
11303
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11304
|
+
if (layout === "hex") {
|
|
11305
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
11306
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
11307
|
+
return { x: col, y: row };
|
|
11308
|
+
}
|
|
11299
11309
|
const adjustedX = screenX - baseOffsetX;
|
|
11300
11310
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
11301
11311
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -11345,6 +11355,7 @@ function IsometricCanvas({
|
|
|
11345
11355
|
tileHoverEvent,
|
|
11346
11356
|
tileLeaveEvent,
|
|
11347
11357
|
// Rendering options
|
|
11358
|
+
tileLayout = "isometric",
|
|
11348
11359
|
scale = 0.4,
|
|
11349
11360
|
debug: debug2 = false,
|
|
11350
11361
|
backgroundImage = "",
|
|
@@ -11414,13 +11425,17 @@ function IsometricCanvas({
|
|
|
11414
11425
|
);
|
|
11415
11426
|
const sortedTiles = React85.useMemo(() => {
|
|
11416
11427
|
const tiles = [...tilesProp];
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11420
|
-
|
|
11421
|
-
|
|
11428
|
+
if (tileLayout === "hex") {
|
|
11429
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11430
|
+
} else {
|
|
11431
|
+
tiles.sort((a, b) => {
|
|
11432
|
+
const depthA = a.x + a.y;
|
|
11433
|
+
const depthB = b.x + b.y;
|
|
11434
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11435
|
+
});
|
|
11436
|
+
}
|
|
11422
11437
|
return tiles;
|
|
11423
|
-
}, [tilesProp]);
|
|
11438
|
+
}, [tilesProp, tileLayout]);
|
|
11424
11439
|
const gridWidth = React85.useMemo(() => {
|
|
11425
11440
|
if (sortedTiles.length === 0) return 0;
|
|
11426
11441
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11534,7 +11549,7 @@ function IsometricCanvas({
|
|
|
11534
11549
|
miniCanvas.width = mW;
|
|
11535
11550
|
miniCanvas.height = mH;
|
|
11536
11551
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11537
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11552
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11538
11553
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11539
11554
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11540
11555
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11545,7 +11560,7 @@ function IsometricCanvas({
|
|
|
11545
11560
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11546
11561
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11547
11562
|
for (const tile of sortedTiles) {
|
|
11548
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11563
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11549
11564
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11550
11565
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11551
11566
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11561,7 +11576,7 @@ function IsometricCanvas({
|
|
|
11561
11576
|
}
|
|
11562
11577
|
for (const unit of units) {
|
|
11563
11578
|
if (!unit.position) continue;
|
|
11564
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11579
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11565
11580
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11566
11581
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11567
11582
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11577,7 +11592,7 @@ function IsometricCanvas({
|
|
|
11577
11592
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11578
11593
|
mCtx.lineWidth = 1;
|
|
11579
11594
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11580
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11595
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11581
11596
|
const draw = React85.useCallback((animTime) => {
|
|
11582
11597
|
const canvas = canvasRef.current;
|
|
11583
11598
|
if (!canvas) return;
|
|
@@ -11617,7 +11632,7 @@ function IsometricCanvas({
|
|
|
11617
11632
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11618
11633
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11619
11634
|
for (const tile of sortedTiles) {
|
|
11620
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11635
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11621
11636
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11622
11637
|
continue;
|
|
11623
11638
|
}
|
|
@@ -11697,12 +11712,13 @@ function IsometricCanvas({
|
|
|
11697
11712
|
}
|
|
11698
11713
|
}
|
|
11699
11714
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11715
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11700
11716
|
const depthA = a.x + a.y;
|
|
11701
11717
|
const depthB = b.x + b.y;
|
|
11702
11718
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11703
11719
|
});
|
|
11704
11720
|
for (const feature of sortedFeatures) {
|
|
11705
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11721
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11706
11722
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11707
11723
|
continue;
|
|
11708
11724
|
}
|
|
@@ -11737,12 +11753,13 @@ function IsometricCanvas({
|
|
|
11737
11753
|
}
|
|
11738
11754
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11739
11755
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11756
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11740
11757
|
const depthA = a.position.x + a.position.y;
|
|
11741
11758
|
const depthB = b.position.x + b.position.y;
|
|
11742
11759
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11743
11760
|
});
|
|
11744
11761
|
for (const unit of sortedUnits) {
|
|
11745
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11762
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11746
11763
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11747
11764
|
continue;
|
|
11748
11765
|
}
|
|
@@ -11762,7 +11779,7 @@ function IsometricCanvas({
|
|
|
11762
11779
|
drawH = maxUnitW / ar;
|
|
11763
11780
|
}
|
|
11764
11781
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11765
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11782
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11766
11783
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11767
11784
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11768
11785
|
ctx.save();
|
|
@@ -11891,6 +11908,7 @@ function IsometricCanvas({
|
|
|
11891
11908
|
units,
|
|
11892
11909
|
features,
|
|
11893
11910
|
selectedUnitId,
|
|
11911
|
+
tileLayout,
|
|
11894
11912
|
scale,
|
|
11895
11913
|
debug2,
|
|
11896
11914
|
resolveTerrainSpriteUrl,
|
|
@@ -11919,14 +11937,14 @@ function IsometricCanvas({
|
|
|
11919
11937
|
if (!selectedUnitId) return;
|
|
11920
11938
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11921
11939
|
if (!unit?.position) return;
|
|
11922
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11940
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11923
11941
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11924
11942
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11925
11943
|
targetCameraRef.current = {
|
|
11926
11944
|
x: centerX - viewportSize.width / 2,
|
|
11927
11945
|
y: centerY - viewportSize.height / 2
|
|
11928
11946
|
};
|
|
11929
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11947
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11930
11948
|
React85.useEffect(() => {
|
|
11931
11949
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11932
11950
|
draw(animTimeRef.current);
|
|
@@ -11959,13 +11977,13 @@ function IsometricCanvas({
|
|
|
11959
11977
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11960
11978
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11961
11979
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11962
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11980
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11963
11981
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11964
11982
|
if (tileExists) {
|
|
11965
11983
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11966
11984
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11967
11985
|
}
|
|
11968
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11986
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11969
11987
|
const handleCanvasPointerUp = React85.useCallback((e) => {
|
|
11970
11988
|
singlePointerActiveRef.current = false;
|
|
11971
11989
|
if (enableCamera) handlePointerUp();
|
|
@@ -11974,7 +11992,7 @@ function IsometricCanvas({
|
|
|
11974
11992
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11975
11993
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11976
11994
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11977
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11995
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11978
11996
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11979
11997
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11980
11998
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11986,7 +12004,7 @@ function IsometricCanvas({
|
|
|
11986
12004
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11987
12005
|
}
|
|
11988
12006
|
}
|
|
11989
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
12007
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11990
12008
|
const handleCanvasPointerLeave = React85.useCallback(() => {
|
|
11991
12009
|
handleMouseLeave();
|
|
11992
12010
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -44561,6 +44579,48 @@ var init_HeroOrganism = __esm({
|
|
|
44561
44579
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44562
44580
|
}
|
|
44563
44581
|
});
|
|
44582
|
+
function HexStrategyBoard({
|
|
44583
|
+
tiles,
|
|
44584
|
+
units,
|
|
44585
|
+
features,
|
|
44586
|
+
assetManifest,
|
|
44587
|
+
assetBaseUrl,
|
|
44588
|
+
scale = 0.45,
|
|
44589
|
+
showMinimap = true,
|
|
44590
|
+
enableCamera = true,
|
|
44591
|
+
tileClickEvent,
|
|
44592
|
+
unitClickEvent,
|
|
44593
|
+
isLoading,
|
|
44594
|
+
error,
|
|
44595
|
+
className
|
|
44596
|
+
}) {
|
|
44597
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
44598
|
+
IsometricCanvas_default,
|
|
44599
|
+
{
|
|
44600
|
+
tileLayout: "hex",
|
|
44601
|
+
tiles,
|
|
44602
|
+
units,
|
|
44603
|
+
features,
|
|
44604
|
+
assetManifest,
|
|
44605
|
+
assetBaseUrl,
|
|
44606
|
+
scale,
|
|
44607
|
+
showMinimap,
|
|
44608
|
+
enableCamera,
|
|
44609
|
+
tileClickEvent,
|
|
44610
|
+
unitClickEvent,
|
|
44611
|
+
isLoading,
|
|
44612
|
+
error
|
|
44613
|
+
}
|
|
44614
|
+
) });
|
|
44615
|
+
}
|
|
44616
|
+
var init_HexStrategyBoard = __esm({
|
|
44617
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44618
|
+
"use client";
|
|
44619
|
+
init_cn();
|
|
44620
|
+
init_IsometricCanvas();
|
|
44621
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44622
|
+
}
|
|
44623
|
+
});
|
|
44564
44624
|
var LandingPageTemplate;
|
|
44565
44625
|
var init_LandingPageTemplate = __esm({
|
|
44566
44626
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52370,6 +52430,7 @@ var init_component_registry_generated = __esm({
|
|
|
52370
52430
|
init_HealthPanel();
|
|
52371
52431
|
init_HeroOrganism();
|
|
52372
52432
|
init_HeroSection();
|
|
52433
|
+
init_HexStrategyBoard();
|
|
52373
52434
|
init_Icon();
|
|
52374
52435
|
init_InfiniteScrollSentinel();
|
|
52375
52436
|
init_Input();
|
|
@@ -52706,6 +52767,7 @@ var init_component_registry_generated = __esm({
|
|
|
52706
52767
|
"HealthPanel": HealthPanel,
|
|
52707
52768
|
"HeroOrganism": HeroOrganism,
|
|
52708
52769
|
"HeroSection": HeroSection,
|
|
52770
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52709
52771
|
"Icon": Icon,
|
|
52710
52772
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52711
52773
|
"Input": Input,
|
package/dist/providers/index.js
CHANGED
|
@@ -11239,16 +11239,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
11239
11239
|
});
|
|
11240
11240
|
|
|
11241
11241
|
// components/game/organisms/utils/isometric.ts
|
|
11242
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
11242
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
11243
11243
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11244
11244
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11245
|
+
if (layout === "hex") {
|
|
11246
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11247
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
11248
|
+
return { x: screenX2, y: screenY2 };
|
|
11249
|
+
}
|
|
11245
11250
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11246
11251
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
11247
11252
|
return { x: screenX, y: screenY };
|
|
11248
11253
|
}
|
|
11249
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
11254
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
11250
11255
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11251
11256
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11257
|
+
if (layout === "hex") {
|
|
11258
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
11259
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
11260
|
+
return { x: col, y: row };
|
|
11261
|
+
}
|
|
11252
11262
|
const adjustedX = screenX - baseOffsetX;
|
|
11253
11263
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
11254
11264
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -11298,6 +11308,7 @@ function IsometricCanvas({
|
|
|
11298
11308
|
tileHoverEvent,
|
|
11299
11309
|
tileLeaveEvent,
|
|
11300
11310
|
// Rendering options
|
|
11311
|
+
tileLayout = "isometric",
|
|
11301
11312
|
scale = 0.4,
|
|
11302
11313
|
debug: debug2 = false,
|
|
11303
11314
|
backgroundImage = "",
|
|
@@ -11367,13 +11378,17 @@ function IsometricCanvas({
|
|
|
11367
11378
|
);
|
|
11368
11379
|
const sortedTiles = useMemo(() => {
|
|
11369
11380
|
const tiles = [...tilesProp];
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11381
|
+
if (tileLayout === "hex") {
|
|
11382
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11383
|
+
} else {
|
|
11384
|
+
tiles.sort((a, b) => {
|
|
11385
|
+
const depthA = a.x + a.y;
|
|
11386
|
+
const depthB = b.x + b.y;
|
|
11387
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11388
|
+
});
|
|
11389
|
+
}
|
|
11375
11390
|
return tiles;
|
|
11376
|
-
}, [tilesProp]);
|
|
11391
|
+
}, [tilesProp, tileLayout]);
|
|
11377
11392
|
const gridWidth = useMemo(() => {
|
|
11378
11393
|
if (sortedTiles.length === 0) return 0;
|
|
11379
11394
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11487,7 +11502,7 @@ function IsometricCanvas({
|
|
|
11487
11502
|
miniCanvas.width = mW;
|
|
11488
11503
|
miniCanvas.height = mH;
|
|
11489
11504
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11490
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11505
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11491
11506
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11492
11507
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11493
11508
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11498,7 +11513,7 @@ function IsometricCanvas({
|
|
|
11498
11513
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11499
11514
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11500
11515
|
for (const tile of sortedTiles) {
|
|
11501
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11516
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11502
11517
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11503
11518
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11504
11519
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11514,7 +11529,7 @@ function IsometricCanvas({
|
|
|
11514
11529
|
}
|
|
11515
11530
|
for (const unit of units) {
|
|
11516
11531
|
if (!unit.position) continue;
|
|
11517
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11532
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11518
11533
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11519
11534
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11520
11535
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11530,7 +11545,7 @@ function IsometricCanvas({
|
|
|
11530
11545
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11531
11546
|
mCtx.lineWidth = 1;
|
|
11532
11547
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11533
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11548
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11534
11549
|
const draw = useCallback((animTime) => {
|
|
11535
11550
|
const canvas = canvasRef.current;
|
|
11536
11551
|
if (!canvas) return;
|
|
@@ -11570,7 +11585,7 @@ function IsometricCanvas({
|
|
|
11570
11585
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11571
11586
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11572
11587
|
for (const tile of sortedTiles) {
|
|
11573
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11588
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11574
11589
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11575
11590
|
continue;
|
|
11576
11591
|
}
|
|
@@ -11650,12 +11665,13 @@ function IsometricCanvas({
|
|
|
11650
11665
|
}
|
|
11651
11666
|
}
|
|
11652
11667
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11668
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11653
11669
|
const depthA = a.x + a.y;
|
|
11654
11670
|
const depthB = b.x + b.y;
|
|
11655
11671
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11656
11672
|
});
|
|
11657
11673
|
for (const feature of sortedFeatures) {
|
|
11658
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11674
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11659
11675
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11660
11676
|
continue;
|
|
11661
11677
|
}
|
|
@@ -11690,12 +11706,13 @@ function IsometricCanvas({
|
|
|
11690
11706
|
}
|
|
11691
11707
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11692
11708
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11709
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11693
11710
|
const depthA = a.position.x + a.position.y;
|
|
11694
11711
|
const depthB = b.position.x + b.position.y;
|
|
11695
11712
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11696
11713
|
});
|
|
11697
11714
|
for (const unit of sortedUnits) {
|
|
11698
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11715
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11699
11716
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11700
11717
|
continue;
|
|
11701
11718
|
}
|
|
@@ -11715,7 +11732,7 @@ function IsometricCanvas({
|
|
|
11715
11732
|
drawH = maxUnitW / ar;
|
|
11716
11733
|
}
|
|
11717
11734
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11718
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11735
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11719
11736
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11720
11737
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11721
11738
|
ctx.save();
|
|
@@ -11844,6 +11861,7 @@ function IsometricCanvas({
|
|
|
11844
11861
|
units,
|
|
11845
11862
|
features,
|
|
11846
11863
|
selectedUnitId,
|
|
11864
|
+
tileLayout,
|
|
11847
11865
|
scale,
|
|
11848
11866
|
debug2,
|
|
11849
11867
|
resolveTerrainSpriteUrl,
|
|
@@ -11872,14 +11890,14 @@ function IsometricCanvas({
|
|
|
11872
11890
|
if (!selectedUnitId) return;
|
|
11873
11891
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11874
11892
|
if (!unit?.position) return;
|
|
11875
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11893
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11876
11894
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11877
11895
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11878
11896
|
targetCameraRef.current = {
|
|
11879
11897
|
x: centerX - viewportSize.width / 2,
|
|
11880
11898
|
y: centerY - viewportSize.height / 2
|
|
11881
11899
|
};
|
|
11882
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11900
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11883
11901
|
useEffect(() => {
|
|
11884
11902
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11885
11903
|
draw(animTimeRef.current);
|
|
@@ -11912,13 +11930,13 @@ function IsometricCanvas({
|
|
|
11912
11930
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11913
11931
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11914
11932
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11915
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11933
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11916
11934
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11917
11935
|
if (tileExists) {
|
|
11918
11936
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11919
11937
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11920
11938
|
}
|
|
11921
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11939
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11922
11940
|
const handleCanvasPointerUp = useCallback((e) => {
|
|
11923
11941
|
singlePointerActiveRef.current = false;
|
|
11924
11942
|
if (enableCamera) handlePointerUp();
|
|
@@ -11927,7 +11945,7 @@ function IsometricCanvas({
|
|
|
11927
11945
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11928
11946
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11929
11947
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11930
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11948
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11931
11949
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11932
11950
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11933
11951
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11939,7 +11957,7 @@ function IsometricCanvas({
|
|
|
11939
11957
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11940
11958
|
}
|
|
11941
11959
|
}
|
|
11942
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11960
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11943
11961
|
const handleCanvasPointerLeave = useCallback(() => {
|
|
11944
11962
|
handleMouseLeave();
|
|
11945
11963
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -44514,6 +44532,48 @@ var init_HeroOrganism = __esm({
|
|
|
44514
44532
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44515
44533
|
}
|
|
44516
44534
|
});
|
|
44535
|
+
function HexStrategyBoard({
|
|
44536
|
+
tiles,
|
|
44537
|
+
units,
|
|
44538
|
+
features,
|
|
44539
|
+
assetManifest,
|
|
44540
|
+
assetBaseUrl,
|
|
44541
|
+
scale = 0.45,
|
|
44542
|
+
showMinimap = true,
|
|
44543
|
+
enableCamera = true,
|
|
44544
|
+
tileClickEvent,
|
|
44545
|
+
unitClickEvent,
|
|
44546
|
+
isLoading,
|
|
44547
|
+
error,
|
|
44548
|
+
className
|
|
44549
|
+
}) {
|
|
44550
|
+
return /* @__PURE__ */ jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsx(
|
|
44551
|
+
IsometricCanvas_default,
|
|
44552
|
+
{
|
|
44553
|
+
tileLayout: "hex",
|
|
44554
|
+
tiles,
|
|
44555
|
+
units,
|
|
44556
|
+
features,
|
|
44557
|
+
assetManifest,
|
|
44558
|
+
assetBaseUrl,
|
|
44559
|
+
scale,
|
|
44560
|
+
showMinimap,
|
|
44561
|
+
enableCamera,
|
|
44562
|
+
tileClickEvent,
|
|
44563
|
+
unitClickEvent,
|
|
44564
|
+
isLoading,
|
|
44565
|
+
error
|
|
44566
|
+
}
|
|
44567
|
+
) });
|
|
44568
|
+
}
|
|
44569
|
+
var init_HexStrategyBoard = __esm({
|
|
44570
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44571
|
+
"use client";
|
|
44572
|
+
init_cn();
|
|
44573
|
+
init_IsometricCanvas();
|
|
44574
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44575
|
+
}
|
|
44576
|
+
});
|
|
44517
44577
|
var LandingPageTemplate;
|
|
44518
44578
|
var init_LandingPageTemplate = __esm({
|
|
44519
44579
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52323,6 +52383,7 @@ var init_component_registry_generated = __esm({
|
|
|
52323
52383
|
init_HealthPanel();
|
|
52324
52384
|
init_HeroOrganism();
|
|
52325
52385
|
init_HeroSection();
|
|
52386
|
+
init_HexStrategyBoard();
|
|
52326
52387
|
init_Icon();
|
|
52327
52388
|
init_InfiniteScrollSentinel();
|
|
52328
52389
|
init_Input();
|
|
@@ -52659,6 +52720,7 @@ var init_component_registry_generated = __esm({
|
|
|
52659
52720
|
"HealthPanel": HealthPanel,
|
|
52660
52721
|
"HeroOrganism": HeroOrganism,
|
|
52661
52722
|
"HeroSection": HeroSection,
|
|
52723
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52662
52724
|
"Icon": Icon,
|
|
52663
52725
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52664
52726
|
"Input": Input,
|