@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/runtime/index.cjs
CHANGED
|
@@ -10984,16 +10984,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
10984
10984
|
});
|
|
10985
10985
|
|
|
10986
10986
|
// components/game/organisms/utils/isometric.ts
|
|
10987
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
10987
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
10988
10988
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
10989
10989
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
10990
|
+
if (layout === "hex") {
|
|
10991
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
10992
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
10993
|
+
return { x: screenX2, y: screenY2 };
|
|
10994
|
+
}
|
|
10990
10995
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
10991
10996
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
10992
10997
|
return { x: screenX, y: screenY };
|
|
10993
10998
|
}
|
|
10994
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
10999
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
10995
11000
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
10996
11001
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11002
|
+
if (layout === "hex") {
|
|
11003
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
11004
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
11005
|
+
return { x: col, y: row };
|
|
11006
|
+
}
|
|
10997
11007
|
const adjustedX = screenX - baseOffsetX;
|
|
10998
11008
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
10999
11009
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -11043,6 +11053,7 @@ function IsometricCanvas({
|
|
|
11043
11053
|
tileHoverEvent,
|
|
11044
11054
|
tileLeaveEvent,
|
|
11045
11055
|
// Rendering options
|
|
11056
|
+
tileLayout = "isometric",
|
|
11046
11057
|
scale = 0.4,
|
|
11047
11058
|
debug: debug2 = false,
|
|
11048
11059
|
backgroundImage = "",
|
|
@@ -11112,13 +11123,17 @@ function IsometricCanvas({
|
|
|
11112
11123
|
);
|
|
11113
11124
|
const sortedTiles = React84.useMemo(() => {
|
|
11114
11125
|
const tiles = [...tilesProp];
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11126
|
+
if (tileLayout === "hex") {
|
|
11127
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11128
|
+
} else {
|
|
11129
|
+
tiles.sort((a, b) => {
|
|
11130
|
+
const depthA = a.x + a.y;
|
|
11131
|
+
const depthB = b.x + b.y;
|
|
11132
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11133
|
+
});
|
|
11134
|
+
}
|
|
11120
11135
|
return tiles;
|
|
11121
|
-
}, [tilesProp]);
|
|
11136
|
+
}, [tilesProp, tileLayout]);
|
|
11122
11137
|
const gridWidth = React84.useMemo(() => {
|
|
11123
11138
|
if (sortedTiles.length === 0) return 0;
|
|
11124
11139
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11232,7 +11247,7 @@ function IsometricCanvas({
|
|
|
11232
11247
|
miniCanvas.width = mW;
|
|
11233
11248
|
miniCanvas.height = mH;
|
|
11234
11249
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11235
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11250
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11236
11251
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11237
11252
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11238
11253
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11243,7 +11258,7 @@ function IsometricCanvas({
|
|
|
11243
11258
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11244
11259
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11245
11260
|
for (const tile of sortedTiles) {
|
|
11246
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11261
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11247
11262
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11248
11263
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11249
11264
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11259,7 +11274,7 @@ function IsometricCanvas({
|
|
|
11259
11274
|
}
|
|
11260
11275
|
for (const unit of units) {
|
|
11261
11276
|
if (!unit.position) continue;
|
|
11262
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11277
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11263
11278
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11264
11279
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11265
11280
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11275,7 +11290,7 @@ function IsometricCanvas({
|
|
|
11275
11290
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11276
11291
|
mCtx.lineWidth = 1;
|
|
11277
11292
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11278
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11293
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11279
11294
|
const draw = React84.useCallback((animTime) => {
|
|
11280
11295
|
const canvas = canvasRef.current;
|
|
11281
11296
|
if (!canvas) return;
|
|
@@ -11315,7 +11330,7 @@ function IsometricCanvas({
|
|
|
11315
11330
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11316
11331
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11317
11332
|
for (const tile of sortedTiles) {
|
|
11318
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11333
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11319
11334
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11320
11335
|
continue;
|
|
11321
11336
|
}
|
|
@@ -11395,12 +11410,13 @@ function IsometricCanvas({
|
|
|
11395
11410
|
}
|
|
11396
11411
|
}
|
|
11397
11412
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11413
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11398
11414
|
const depthA = a.x + a.y;
|
|
11399
11415
|
const depthB = b.x + b.y;
|
|
11400
11416
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11401
11417
|
});
|
|
11402
11418
|
for (const feature of sortedFeatures) {
|
|
11403
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11419
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11404
11420
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11405
11421
|
continue;
|
|
11406
11422
|
}
|
|
@@ -11435,12 +11451,13 @@ function IsometricCanvas({
|
|
|
11435
11451
|
}
|
|
11436
11452
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11437
11453
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11454
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11438
11455
|
const depthA = a.position.x + a.position.y;
|
|
11439
11456
|
const depthB = b.position.x + b.position.y;
|
|
11440
11457
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11441
11458
|
});
|
|
11442
11459
|
for (const unit of sortedUnits) {
|
|
11443
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11460
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11444
11461
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11445
11462
|
continue;
|
|
11446
11463
|
}
|
|
@@ -11460,7 +11477,7 @@ function IsometricCanvas({
|
|
|
11460
11477
|
drawH = maxUnitW / ar;
|
|
11461
11478
|
}
|
|
11462
11479
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11463
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11480
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11464
11481
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11465
11482
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11466
11483
|
ctx.save();
|
|
@@ -11589,6 +11606,7 @@ function IsometricCanvas({
|
|
|
11589
11606
|
units,
|
|
11590
11607
|
features,
|
|
11591
11608
|
selectedUnitId,
|
|
11609
|
+
tileLayout,
|
|
11592
11610
|
scale,
|
|
11593
11611
|
debug2,
|
|
11594
11612
|
resolveTerrainSpriteUrl,
|
|
@@ -11617,14 +11635,14 @@ function IsometricCanvas({
|
|
|
11617
11635
|
if (!selectedUnitId) return;
|
|
11618
11636
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11619
11637
|
if (!unit?.position) return;
|
|
11620
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11638
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11621
11639
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11622
11640
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11623
11641
|
targetCameraRef.current = {
|
|
11624
11642
|
x: centerX - viewportSize.width / 2,
|
|
11625
11643
|
y: centerY - viewportSize.height / 2
|
|
11626
11644
|
};
|
|
11627
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11645
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11628
11646
|
React84.useEffect(() => {
|
|
11629
11647
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11630
11648
|
draw(animTimeRef.current);
|
|
@@ -11657,13 +11675,13 @@ function IsometricCanvas({
|
|
|
11657
11675
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11658
11676
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11659
11677
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11660
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11678
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11661
11679
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11662
11680
|
if (tileExists) {
|
|
11663
11681
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11664
11682
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11665
11683
|
}
|
|
11666
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11684
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11667
11685
|
const handleCanvasPointerUp = React84.useCallback((e) => {
|
|
11668
11686
|
singlePointerActiveRef.current = false;
|
|
11669
11687
|
if (enableCamera) handlePointerUp();
|
|
@@ -11672,7 +11690,7 @@ function IsometricCanvas({
|
|
|
11672
11690
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11673
11691
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11674
11692
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11675
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11693
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11676
11694
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11677
11695
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11678
11696
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11684,7 +11702,7 @@ function IsometricCanvas({
|
|
|
11684
11702
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11685
11703
|
}
|
|
11686
11704
|
}
|
|
11687
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11705
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11688
11706
|
const handleCanvasPointerLeave = React84.useCallback(() => {
|
|
11689
11707
|
handleMouseLeave();
|
|
11690
11708
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -44259,6 +44277,48 @@ var init_HeroOrganism = __esm({
|
|
|
44259
44277
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44260
44278
|
}
|
|
44261
44279
|
});
|
|
44280
|
+
function HexStrategyBoard({
|
|
44281
|
+
tiles,
|
|
44282
|
+
units,
|
|
44283
|
+
features,
|
|
44284
|
+
assetManifest,
|
|
44285
|
+
assetBaseUrl,
|
|
44286
|
+
scale = 0.45,
|
|
44287
|
+
showMinimap = true,
|
|
44288
|
+
enableCamera = true,
|
|
44289
|
+
tileClickEvent,
|
|
44290
|
+
unitClickEvent,
|
|
44291
|
+
isLoading,
|
|
44292
|
+
error,
|
|
44293
|
+
className
|
|
44294
|
+
}) {
|
|
44295
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
44296
|
+
IsometricCanvas_default,
|
|
44297
|
+
{
|
|
44298
|
+
tileLayout: "hex",
|
|
44299
|
+
tiles,
|
|
44300
|
+
units,
|
|
44301
|
+
features,
|
|
44302
|
+
assetManifest,
|
|
44303
|
+
assetBaseUrl,
|
|
44304
|
+
scale,
|
|
44305
|
+
showMinimap,
|
|
44306
|
+
enableCamera,
|
|
44307
|
+
tileClickEvent,
|
|
44308
|
+
unitClickEvent,
|
|
44309
|
+
isLoading,
|
|
44310
|
+
error
|
|
44311
|
+
}
|
|
44312
|
+
) });
|
|
44313
|
+
}
|
|
44314
|
+
var init_HexStrategyBoard = __esm({
|
|
44315
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44316
|
+
"use client";
|
|
44317
|
+
init_cn();
|
|
44318
|
+
init_IsometricCanvas();
|
|
44319
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44320
|
+
}
|
|
44321
|
+
});
|
|
44262
44322
|
var LandingPageTemplate;
|
|
44263
44323
|
var init_LandingPageTemplate = __esm({
|
|
44264
44324
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52087,6 +52147,7 @@ var init_component_registry_generated = __esm({
|
|
|
52087
52147
|
init_HealthPanel();
|
|
52088
52148
|
init_HeroOrganism();
|
|
52089
52149
|
init_HeroSection();
|
|
52150
|
+
init_HexStrategyBoard();
|
|
52090
52151
|
init_Icon();
|
|
52091
52152
|
init_InfiniteScrollSentinel();
|
|
52092
52153
|
init_Input();
|
|
@@ -52423,6 +52484,7 @@ var init_component_registry_generated = __esm({
|
|
|
52423
52484
|
"HealthPanel": HealthPanel,
|
|
52424
52485
|
"HeroOrganism": HeroOrganism,
|
|
52425
52486
|
"HeroSection": HeroSection,
|
|
52487
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52426
52488
|
"Icon": Icon,
|
|
52427
52489
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52428
52490
|
"Input": Input,
|
package/dist/runtime/index.js
CHANGED
|
@@ -10937,16 +10937,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
10937
10937
|
});
|
|
10938
10938
|
|
|
10939
10939
|
// components/game/organisms/utils/isometric.ts
|
|
10940
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
10940
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
10941
10941
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
10942
10942
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
10943
|
+
if (layout === "hex") {
|
|
10944
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
10945
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
10946
|
+
return { x: screenX2, y: screenY2 };
|
|
10947
|
+
}
|
|
10943
10948
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
10944
10949
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
10945
10950
|
return { x: screenX, y: screenY };
|
|
10946
10951
|
}
|
|
10947
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
10952
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
10948
10953
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
10949
10954
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
10955
|
+
if (layout === "hex") {
|
|
10956
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
10957
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
10958
|
+
return { x: col, y: row };
|
|
10959
|
+
}
|
|
10950
10960
|
const adjustedX = screenX - baseOffsetX;
|
|
10951
10961
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
10952
10962
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -10996,6 +11006,7 @@ function IsometricCanvas({
|
|
|
10996
11006
|
tileHoverEvent,
|
|
10997
11007
|
tileLeaveEvent,
|
|
10998
11008
|
// Rendering options
|
|
11009
|
+
tileLayout = "isometric",
|
|
10999
11010
|
scale = 0.4,
|
|
11000
11011
|
debug: debug2 = false,
|
|
11001
11012
|
backgroundImage = "",
|
|
@@ -11065,13 +11076,17 @@ function IsometricCanvas({
|
|
|
11065
11076
|
);
|
|
11066
11077
|
const sortedTiles = useMemo(() => {
|
|
11067
11078
|
const tiles = [...tilesProp];
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11079
|
+
if (tileLayout === "hex") {
|
|
11080
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11081
|
+
} else {
|
|
11082
|
+
tiles.sort((a, b) => {
|
|
11083
|
+
const depthA = a.x + a.y;
|
|
11084
|
+
const depthB = b.x + b.y;
|
|
11085
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11086
|
+
});
|
|
11087
|
+
}
|
|
11073
11088
|
return tiles;
|
|
11074
|
-
}, [tilesProp]);
|
|
11089
|
+
}, [tilesProp, tileLayout]);
|
|
11075
11090
|
const gridWidth = useMemo(() => {
|
|
11076
11091
|
if (sortedTiles.length === 0) return 0;
|
|
11077
11092
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11185,7 +11200,7 @@ function IsometricCanvas({
|
|
|
11185
11200
|
miniCanvas.width = mW;
|
|
11186
11201
|
miniCanvas.height = mH;
|
|
11187
11202
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11188
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11203
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11189
11204
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11190
11205
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11191
11206
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11196,7 +11211,7 @@ function IsometricCanvas({
|
|
|
11196
11211
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11197
11212
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11198
11213
|
for (const tile of sortedTiles) {
|
|
11199
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11214
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11200
11215
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11201
11216
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11202
11217
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11212,7 +11227,7 @@ function IsometricCanvas({
|
|
|
11212
11227
|
}
|
|
11213
11228
|
for (const unit of units) {
|
|
11214
11229
|
if (!unit.position) continue;
|
|
11215
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11230
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11216
11231
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11217
11232
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11218
11233
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11228,7 +11243,7 @@ function IsometricCanvas({
|
|
|
11228
11243
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11229
11244
|
mCtx.lineWidth = 1;
|
|
11230
11245
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11231
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11246
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11232
11247
|
const draw = useCallback((animTime) => {
|
|
11233
11248
|
const canvas = canvasRef.current;
|
|
11234
11249
|
if (!canvas) return;
|
|
@@ -11268,7 +11283,7 @@ function IsometricCanvas({
|
|
|
11268
11283
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11269
11284
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11270
11285
|
for (const tile of sortedTiles) {
|
|
11271
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11286
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11272
11287
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11273
11288
|
continue;
|
|
11274
11289
|
}
|
|
@@ -11348,12 +11363,13 @@ function IsometricCanvas({
|
|
|
11348
11363
|
}
|
|
11349
11364
|
}
|
|
11350
11365
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11366
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11351
11367
|
const depthA = a.x + a.y;
|
|
11352
11368
|
const depthB = b.x + b.y;
|
|
11353
11369
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11354
11370
|
});
|
|
11355
11371
|
for (const feature of sortedFeatures) {
|
|
11356
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11372
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11357
11373
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11358
11374
|
continue;
|
|
11359
11375
|
}
|
|
@@ -11388,12 +11404,13 @@ function IsometricCanvas({
|
|
|
11388
11404
|
}
|
|
11389
11405
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11390
11406
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11407
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11391
11408
|
const depthA = a.position.x + a.position.y;
|
|
11392
11409
|
const depthB = b.position.x + b.position.y;
|
|
11393
11410
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11394
11411
|
});
|
|
11395
11412
|
for (const unit of sortedUnits) {
|
|
11396
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11413
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11397
11414
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11398
11415
|
continue;
|
|
11399
11416
|
}
|
|
@@ -11413,7 +11430,7 @@ function IsometricCanvas({
|
|
|
11413
11430
|
drawH = maxUnitW / ar;
|
|
11414
11431
|
}
|
|
11415
11432
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11416
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11433
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11417
11434
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11418
11435
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11419
11436
|
ctx.save();
|
|
@@ -11542,6 +11559,7 @@ function IsometricCanvas({
|
|
|
11542
11559
|
units,
|
|
11543
11560
|
features,
|
|
11544
11561
|
selectedUnitId,
|
|
11562
|
+
tileLayout,
|
|
11545
11563
|
scale,
|
|
11546
11564
|
debug2,
|
|
11547
11565
|
resolveTerrainSpriteUrl,
|
|
@@ -11570,14 +11588,14 @@ function IsometricCanvas({
|
|
|
11570
11588
|
if (!selectedUnitId) return;
|
|
11571
11589
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11572
11590
|
if (!unit?.position) return;
|
|
11573
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11591
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11574
11592
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11575
11593
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11576
11594
|
targetCameraRef.current = {
|
|
11577
11595
|
x: centerX - viewportSize.width / 2,
|
|
11578
11596
|
y: centerY - viewportSize.height / 2
|
|
11579
11597
|
};
|
|
11580
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11598
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11581
11599
|
useEffect(() => {
|
|
11582
11600
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11583
11601
|
draw(animTimeRef.current);
|
|
@@ -11610,13 +11628,13 @@ function IsometricCanvas({
|
|
|
11610
11628
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11611
11629
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11612
11630
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11613
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11631
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11614
11632
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11615
11633
|
if (tileExists) {
|
|
11616
11634
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11617
11635
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11618
11636
|
}
|
|
11619
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11637
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11620
11638
|
const handleCanvasPointerUp = useCallback((e) => {
|
|
11621
11639
|
singlePointerActiveRef.current = false;
|
|
11622
11640
|
if (enableCamera) handlePointerUp();
|
|
@@ -11625,7 +11643,7 @@ function IsometricCanvas({
|
|
|
11625
11643
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11626
11644
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11627
11645
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11628
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11646
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11629
11647
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11630
11648
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11631
11649
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11637,7 +11655,7 @@ function IsometricCanvas({
|
|
|
11637
11655
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11638
11656
|
}
|
|
11639
11657
|
}
|
|
11640
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11658
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11641
11659
|
const handleCanvasPointerLeave = useCallback(() => {
|
|
11642
11660
|
handleMouseLeave();
|
|
11643
11661
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -44212,6 +44230,48 @@ var init_HeroOrganism = __esm({
|
|
|
44212
44230
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44213
44231
|
}
|
|
44214
44232
|
});
|
|
44233
|
+
function HexStrategyBoard({
|
|
44234
|
+
tiles,
|
|
44235
|
+
units,
|
|
44236
|
+
features,
|
|
44237
|
+
assetManifest,
|
|
44238
|
+
assetBaseUrl,
|
|
44239
|
+
scale = 0.45,
|
|
44240
|
+
showMinimap = true,
|
|
44241
|
+
enableCamera = true,
|
|
44242
|
+
tileClickEvent,
|
|
44243
|
+
unitClickEvent,
|
|
44244
|
+
isLoading,
|
|
44245
|
+
error,
|
|
44246
|
+
className
|
|
44247
|
+
}) {
|
|
44248
|
+
return /* @__PURE__ */ jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsx(
|
|
44249
|
+
IsometricCanvas_default,
|
|
44250
|
+
{
|
|
44251
|
+
tileLayout: "hex",
|
|
44252
|
+
tiles,
|
|
44253
|
+
units,
|
|
44254
|
+
features,
|
|
44255
|
+
assetManifest,
|
|
44256
|
+
assetBaseUrl,
|
|
44257
|
+
scale,
|
|
44258
|
+
showMinimap,
|
|
44259
|
+
enableCamera,
|
|
44260
|
+
tileClickEvent,
|
|
44261
|
+
unitClickEvent,
|
|
44262
|
+
isLoading,
|
|
44263
|
+
error
|
|
44264
|
+
}
|
|
44265
|
+
) });
|
|
44266
|
+
}
|
|
44267
|
+
var init_HexStrategyBoard = __esm({
|
|
44268
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44269
|
+
"use client";
|
|
44270
|
+
init_cn();
|
|
44271
|
+
init_IsometricCanvas();
|
|
44272
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44273
|
+
}
|
|
44274
|
+
});
|
|
44215
44275
|
var LandingPageTemplate;
|
|
44216
44276
|
var init_LandingPageTemplate = __esm({
|
|
44217
44277
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52040,6 +52100,7 @@ var init_component_registry_generated = __esm({
|
|
|
52040
52100
|
init_HealthPanel();
|
|
52041
52101
|
init_HeroOrganism();
|
|
52042
52102
|
init_HeroSection();
|
|
52103
|
+
init_HexStrategyBoard();
|
|
52043
52104
|
init_Icon();
|
|
52044
52105
|
init_InfiniteScrollSentinel();
|
|
52045
52106
|
init_Input();
|
|
@@ -52376,6 +52437,7 @@ var init_component_registry_generated = __esm({
|
|
|
52376
52437
|
"HealthPanel": HealthPanel,
|
|
52377
52438
|
"HeroOrganism": HeroOrganism,
|
|
52378
52439
|
"HeroSection": HeroSection,
|
|
52440
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52379
52441
|
"Icon": Icon,
|
|
52380
52442
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52381
52443
|
"Input": Input,
|