@almadar/ui 5.104.0 → 5.105.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 +154 -80
- package/dist/avl/index.js +154 -80
- package/dist/components/game/2d/molecules/Canvas2D.d.ts +1 -1
- package/dist/components/game/2d/molecules/SideCanvas2D.d.ts +36 -0
- package/dist/components/game/3d/atoms/EventMarker3D.d.ts +17 -0
- package/dist/components/game/3d/atoms/SpriteBillboard3D.d.ts +18 -0
- package/dist/components/game/3d/index.cjs +539 -496
- package/dist/components/game/3d/index.js +367 -324
- package/dist/components/game/3d/molecules/FeatureMesh3D.d.ts +21 -0
- package/dist/components/game/3d/molecules/GameCamera3D.d.ts +35 -0
- package/dist/components/game/3d/molecules/Lighting3D.d.ts +10 -2
- package/dist/components/game/3d/molecules/SideScene3D.d.ts +31 -0
- package/dist/components/game/3d/molecules/TileMesh3D.d.ts +28 -0
- package/dist/components/game/3d/molecules/UnitMesh3D.d.ts +29 -0
- package/dist/components/game/shared/game3dTheme.d.ts +55 -0
- package/dist/components/game/shared/isometric.d.ts +38 -0
- package/dist/components/game/shared/isometricTypes.d.ts +4 -0
- package/dist/components/index.cjs +146 -79
- package/dist/components/index.js +150 -83
- package/dist/providers/index.cjs +154 -80
- package/dist/providers/index.js +154 -80
- package/dist/runtime/index.cjs +154 -80
- package/dist/runtime/index.js +154 -80
- package/package.json +1 -1
package/dist/avl/index.js
CHANGED
|
@@ -11203,7 +11203,7 @@ function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric")
|
|
|
11203
11203
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
11204
11204
|
return { x: Math.round(tileX), y: Math.round(tileY) };
|
|
11205
11205
|
}
|
|
11206
|
-
var TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS;
|
|
11206
|
+
var TILE_WIDTH, TILE_HEIGHT, FLOOR_HEIGHT, DIAMOND_TOP_Y, FEATURE_COLORS, TERRAIN_COLORS, TEAM_COLORS, TEAM_SHADOW_COLORS, HIGHLIGHT_COLORS, SELECTION_RING_COLOR, GRID_STROKE_COLOR, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS, MINIMAP_UNIT_COLORS, UNIT_LABEL_BG_COLORS, SIDE_PLATFORM_COLORS, SIDE_PLAYER_COLOR, SIDE_PLAYER_EYE_COLOR, SIDE_SKY_GRADIENT_TOP, SIDE_SKY_GRADIENT_BOTTOM, SIDE_GRID_COLOR, SIDE_FX_COLOR, SIDE_PLATFORM_BEVEL_COLOR, SIDE_PLATFORM_SHADOW_COLOR, SIDE_HAZARD_STRIPE_COLOR, SIDE_GOAL_GLOW_COLOR, DEFAULT_BG_COLOR;
|
|
11207
11207
|
var init_isometric = __esm({
|
|
11208
11208
|
"components/game/shared/isometric.ts"() {
|
|
11209
11209
|
TILE_WIDTH = 256;
|
|
@@ -11220,14 +11220,79 @@ var init_isometric = __esm({
|
|
|
11220
11220
|
mountain: "#78716c",
|
|
11221
11221
|
default: "#9ca3af"
|
|
11222
11222
|
};
|
|
11223
|
+
TERRAIN_COLORS = {
|
|
11224
|
+
water: "#3b82f6",
|
|
11225
|
+
mountain: "#78716c",
|
|
11226
|
+
stone: "#9ca3af",
|
|
11227
|
+
default: "#4ade80"
|
|
11228
|
+
};
|
|
11229
|
+
TEAM_COLORS = {
|
|
11230
|
+
player: "#3b82f6",
|
|
11231
|
+
enemy: "#ef4444",
|
|
11232
|
+
neutral: "#6b7280",
|
|
11233
|
+
default: "#6b7280"
|
|
11234
|
+
};
|
|
11235
|
+
TEAM_SHADOW_COLORS = {
|
|
11236
|
+
player: "rgba(0,150,255,0.6)",
|
|
11237
|
+
default: "rgba(255,50,50,0.6)"
|
|
11238
|
+
};
|
|
11239
|
+
HIGHLIGHT_COLORS = {
|
|
11240
|
+
hover: "rgba(255,255,255,0.15)",
|
|
11241
|
+
validMove: "rgba(74,222,128,0.25)",
|
|
11242
|
+
attack: "rgba(239,68,68,0.35)"
|
|
11243
|
+
};
|
|
11244
|
+
SELECTION_RING_COLOR = "rgba(0,200,255,0.8)";
|
|
11245
|
+
GRID_STROKE_COLOR = "rgba(0,0,0,0.2)";
|
|
11246
|
+
BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
|
|
11247
|
+
MINIMAP_TERRAIN_COLORS = {
|
|
11248
|
+
water: "#3b82f6",
|
|
11249
|
+
mountain: "#78716c",
|
|
11250
|
+
default: "#4ade80"
|
|
11251
|
+
};
|
|
11252
|
+
MINIMAP_UNIT_COLORS = {
|
|
11253
|
+
player: "#60a5fa",
|
|
11254
|
+
enemy: "#f87171",
|
|
11255
|
+
neutral: "#9ca3af",
|
|
11256
|
+
default: "#9ca3af"
|
|
11257
|
+
};
|
|
11258
|
+
UNIT_LABEL_BG_COLORS = {
|
|
11259
|
+
player: "rgba(59,130,246,0.9)",
|
|
11260
|
+
enemy: "rgba(239,68,68,0.9)",
|
|
11261
|
+
neutral: "rgba(107,114,128,0.9)",
|
|
11262
|
+
default: "rgba(107,114,128,0.9)"
|
|
11263
|
+
};
|
|
11264
|
+
SIDE_PLATFORM_COLORS = {
|
|
11265
|
+
ground: "#4a7c59",
|
|
11266
|
+
platform: "#7c6b4a",
|
|
11267
|
+
hazard: "#c0392b",
|
|
11268
|
+
goal: "#f1c40f"
|
|
11269
|
+
};
|
|
11270
|
+
SIDE_PLAYER_COLOR = "#3498db";
|
|
11271
|
+
SIDE_PLAYER_EYE_COLOR = "#ffffff";
|
|
11272
|
+
SIDE_SKY_GRADIENT_TOP = "#1a1a2e";
|
|
11273
|
+
SIDE_SKY_GRADIENT_BOTTOM = "#16213e";
|
|
11274
|
+
SIDE_GRID_COLOR = "rgba(255, 255, 255, 0.03)";
|
|
11275
|
+
SIDE_FX_COLOR = "#ffe066";
|
|
11276
|
+
SIDE_PLATFORM_BEVEL_COLOR = "rgba(255,255,255,0.15)";
|
|
11277
|
+
SIDE_PLATFORM_SHADOW_COLOR = "rgba(0,0,0,0.3)";
|
|
11278
|
+
SIDE_HAZARD_STRIPE_COLOR = "#e74c3c";
|
|
11279
|
+
SIDE_GOAL_GLOW_COLOR = "rgba(241, 196, 15, 0.5)";
|
|
11280
|
+
DEFAULT_BG_COLOR = "#5c94fc";
|
|
11223
11281
|
}
|
|
11224
11282
|
});
|
|
11225
11283
|
|
|
11226
11284
|
// components/game/shared/spriteSheetConstants.ts
|
|
11227
|
-
var SHEET_COLUMNS;
|
|
11285
|
+
var SHEET_COLUMNS, SPRITE_SHEET_LAYOUT;
|
|
11228
11286
|
var init_spriteSheetConstants = __esm({
|
|
11229
11287
|
"components/game/shared/spriteSheetConstants.ts"() {
|
|
11230
11288
|
SHEET_COLUMNS = 8;
|
|
11289
|
+
SPRITE_SHEET_LAYOUT = {
|
|
11290
|
+
idle: { row: 0, frames: 4, frameRate: 6, loop: true },
|
|
11291
|
+
walk: { row: 1, frames: 8, frameRate: 10, loop: true },
|
|
11292
|
+
attack: { row: 2, frames: 6, frameRate: 12, loop: false },
|
|
11293
|
+
hit: { row: 3, frames: 3, frameRate: 8, loop: false },
|
|
11294
|
+
death: { row: 4, frames: 6, frameRate: 8, loop: false }
|
|
11295
|
+
};
|
|
11231
11296
|
}
|
|
11232
11297
|
});
|
|
11233
11298
|
|
|
@@ -13960,7 +14025,7 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
13960
14025
|
function normalizeBackdrop(bg) {
|
|
13961
14026
|
return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
|
|
13962
14027
|
}
|
|
13963
|
-
function
|
|
14028
|
+
function SideCanvas2D({
|
|
13964
14029
|
player,
|
|
13965
14030
|
platforms,
|
|
13966
14031
|
worldWidth,
|
|
@@ -13981,24 +14046,18 @@ function SideView({
|
|
|
13981
14046
|
const canvasRef = useRef(null);
|
|
13982
14047
|
const eventBus = useEventBus();
|
|
13983
14048
|
const keysRef = useRef(/* @__PURE__ */ new Set());
|
|
13984
|
-
const
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
if (
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
}
|
|
13993
|
-
if (!cached) {
|
|
13994
|
-
const img = new Image();
|
|
13995
|
-
img.crossOrigin = "anonymous";
|
|
13996
|
-
img.src = url;
|
|
13997
|
-
img.onload = () => setLoadedImages((prev) => new Set(prev).add(url));
|
|
13998
|
-
imageCache2.current.set(url, img);
|
|
14049
|
+
const spriteUrls = useMemo(() => {
|
|
14050
|
+
const urls = [];
|
|
14051
|
+
if (backgroundImage?.url) urls.push(backgroundImage.url);
|
|
14052
|
+
if (playerSprite?.url) urls.push(playerSprite.url);
|
|
14053
|
+
if (tileSprites) {
|
|
14054
|
+
for (const asset of Object.values(tileSprites)) {
|
|
14055
|
+
if (asset?.url) urls.push(asset.url);
|
|
14056
|
+
}
|
|
13999
14057
|
}
|
|
14000
|
-
return
|
|
14001
|
-
}, [
|
|
14058
|
+
return urls;
|
|
14059
|
+
}, [backgroundImage, playerSprite, tileSprites]);
|
|
14060
|
+
const { getImage } = useImageCache(spriteUrls);
|
|
14002
14061
|
useEffect(() => {
|
|
14003
14062
|
if (typeof window === "undefined") return;
|
|
14004
14063
|
const canvas = canvasRef.current;
|
|
@@ -14111,7 +14170,7 @@ function SideView({
|
|
|
14111
14170
|
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
14112
14171
|
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
14113
14172
|
}
|
|
14114
|
-
const bgImage = bgImg ?
|
|
14173
|
+
const bgImage = bgImg ? getImage(bgImg.url) : void 0;
|
|
14115
14174
|
const bgSrc = bgImage ? resolveAssetSource(bgImage, bgImg, NOOP) : null;
|
|
14116
14175
|
if (bgSrc) {
|
|
14117
14176
|
blit(ctx, bgSrc, 0, 0, cw, ch);
|
|
@@ -14122,12 +14181,12 @@ function SideView({
|
|
|
14122
14181
|
ctx.fillRect(0, 0, cw, ch);
|
|
14123
14182
|
} else {
|
|
14124
14183
|
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
14125
|
-
grad.addColorStop(0,
|
|
14126
|
-
grad.addColorStop(1,
|
|
14184
|
+
grad.addColorStop(0, SIDE_SKY_GRADIENT_TOP);
|
|
14185
|
+
grad.addColorStop(1, SIDE_SKY_GRADIENT_BOTTOM);
|
|
14127
14186
|
ctx.fillStyle = grad;
|
|
14128
14187
|
ctx.fillRect(0, 0, cw, ch);
|
|
14129
14188
|
}
|
|
14130
|
-
ctx.strokeStyle =
|
|
14189
|
+
ctx.strokeStyle = SIDE_GRID_COLOR;
|
|
14131
14190
|
ctx.lineWidth = 1;
|
|
14132
14191
|
const gridSize = 32;
|
|
14133
14192
|
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
@@ -14147,7 +14206,7 @@ function SideView({
|
|
|
14147
14206
|
const platY = plat.y - camY;
|
|
14148
14207
|
const platType = plat.type ?? "ground";
|
|
14149
14208
|
const spriteAsset = tSprites?.[platType];
|
|
14150
|
-
const tileImg = spriteAsset ?
|
|
14209
|
+
const tileImg = spriteAsset ? getImage(spriteAsset.url) : void 0;
|
|
14151
14210
|
const tileSrc = tileImg ? resolveAssetSource(tileImg, spriteAsset, NOOP) : null;
|
|
14152
14211
|
if (tileSrc) {
|
|
14153
14212
|
const originX = tileSrc.rect ? tileSrc.rect.sx : 0;
|
|
@@ -14162,15 +14221,15 @@ function SideView({
|
|
|
14162
14221
|
ctx.drawImage(tileImg, originX, originY, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
14163
14222
|
}
|
|
14164
14223
|
} else {
|
|
14165
|
-
const color =
|
|
14224
|
+
const color = SIDE_PLATFORM_COLORS[platType] ?? SIDE_PLATFORM_COLORS.ground;
|
|
14166
14225
|
ctx.fillStyle = color;
|
|
14167
14226
|
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
14168
|
-
ctx.fillStyle =
|
|
14227
|
+
ctx.fillStyle = SIDE_PLATFORM_BEVEL_COLOR;
|
|
14169
14228
|
ctx.fillRect(platX, platY, plat.width, 3);
|
|
14170
|
-
ctx.fillStyle =
|
|
14229
|
+
ctx.fillStyle = SIDE_PLATFORM_SHADOW_COLOR;
|
|
14171
14230
|
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
14172
14231
|
if (platType === "hazard") {
|
|
14173
|
-
ctx.strokeStyle =
|
|
14232
|
+
ctx.strokeStyle = SIDE_HAZARD_STRIPE_COLOR;
|
|
14174
14233
|
ctx.lineWidth = 2;
|
|
14175
14234
|
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
14176
14235
|
ctx.beginPath();
|
|
@@ -14180,7 +14239,7 @@ function SideView({
|
|
|
14180
14239
|
}
|
|
14181
14240
|
}
|
|
14182
14241
|
if (platType === "goal") {
|
|
14183
|
-
ctx.fillStyle =
|
|
14242
|
+
ctx.fillStyle = SIDE_GOAL_GLOW_COLOR;
|
|
14184
14243
|
ctx.beginPath();
|
|
14185
14244
|
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
14186
14245
|
ctx.fill();
|
|
@@ -14192,7 +14251,7 @@ function SideView({
|
|
|
14192
14251
|
const ppx = px - camX;
|
|
14193
14252
|
const ppy = py - camY;
|
|
14194
14253
|
const facingRight = auth.facingRight ?? true;
|
|
14195
|
-
const playerImg = pSprite ?
|
|
14254
|
+
const playerImg = pSprite ? getImage(pSprite.url) : void 0;
|
|
14196
14255
|
const playerSrc = playerImg ? resolveAssetSource(playerImg, pSprite, NOOP) : null;
|
|
14197
14256
|
if (playerSrc) {
|
|
14198
14257
|
ctx.save();
|
|
@@ -14205,7 +14264,7 @@ function SideView({
|
|
|
14205
14264
|
}
|
|
14206
14265
|
ctx.restore();
|
|
14207
14266
|
} else {
|
|
14208
|
-
ctx.fillStyle =
|
|
14267
|
+
ctx.fillStyle = SIDE_PLAYER_COLOR;
|
|
14209
14268
|
const radius = Math.min(pw, ph) * 0.25;
|
|
14210
14269
|
ctx.beginPath();
|
|
14211
14270
|
ctx.moveTo(ppx + radius, ppy);
|
|
@@ -14221,7 +14280,7 @@ function SideView({
|
|
|
14221
14280
|
const eyeY = ppy + ph * 0.3;
|
|
14222
14281
|
const eyeSize = 3;
|
|
14223
14282
|
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
14224
|
-
ctx.fillStyle =
|
|
14283
|
+
ctx.fillStyle = SIDE_PLAYER_EYE_COLOR;
|
|
14225
14284
|
ctx.beginPath();
|
|
14226
14285
|
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
14227
14286
|
ctx.fill();
|
|
@@ -14235,7 +14294,7 @@ function SideView({
|
|
|
14235
14294
|
const alpha = Math.min(1, fx.ttl / 4);
|
|
14236
14295
|
const prev = ctx.globalAlpha;
|
|
14237
14296
|
ctx.globalAlpha = alpha;
|
|
14238
|
-
ctx.fillStyle =
|
|
14297
|
+
ctx.fillStyle = SIDE_FX_COLOR;
|
|
14239
14298
|
ctx.beginPath();
|
|
14240
14299
|
ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
|
|
14241
14300
|
ctx.fill();
|
|
@@ -14243,7 +14302,7 @@ function SideView({
|
|
|
14243
14302
|
}
|
|
14244
14303
|
};
|
|
14245
14304
|
return interp.startLoop(drawFrame);
|
|
14246
|
-
}, [interp.startLoop,
|
|
14305
|
+
}, [interp.startLoop, getImage]);
|
|
14247
14306
|
return /* @__PURE__ */ jsx(
|
|
14248
14307
|
"canvas",
|
|
14249
14308
|
{
|
|
@@ -14255,6 +14314,33 @@ function SideView({
|
|
|
14255
14314
|
}
|
|
14256
14315
|
);
|
|
14257
14316
|
}
|
|
14317
|
+
var NOOP;
|
|
14318
|
+
var init_SideCanvas2D = __esm({
|
|
14319
|
+
"components/game/2d/molecules/SideCanvas2D.tsx"() {
|
|
14320
|
+
"use client";
|
|
14321
|
+
init_cn();
|
|
14322
|
+
init_useEventBus();
|
|
14323
|
+
init_useImageCache();
|
|
14324
|
+
init_atlasSlice();
|
|
14325
|
+
init_useRenderInterpolation();
|
|
14326
|
+
init_verificationRegistry();
|
|
14327
|
+
init_isometric();
|
|
14328
|
+
NOOP = () => {
|
|
14329
|
+
};
|
|
14330
|
+
SideCanvas2D.displayName = "SideCanvas2D";
|
|
14331
|
+
}
|
|
14332
|
+
});
|
|
14333
|
+
function normalizeBackdrop2(bg) {
|
|
14334
|
+
return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
|
|
14335
|
+
}
|
|
14336
|
+
function resolveTileFallbackColor(tile) {
|
|
14337
|
+
const override = tile.color;
|
|
14338
|
+
return override ?? TERRAIN_COLORS[tile.terrain ?? ""] ?? TERRAIN_COLORS.default;
|
|
14339
|
+
}
|
|
14340
|
+
function resolveUnitTeamColor(unit) {
|
|
14341
|
+
const override = unit.tint;
|
|
14342
|
+
return override ?? TEAM_COLORS[unit.team ?? ""] ?? TEAM_COLORS.default;
|
|
14343
|
+
}
|
|
14258
14344
|
function Canvas2D({
|
|
14259
14345
|
// Closed-circuit
|
|
14260
14346
|
className,
|
|
@@ -14304,13 +14390,13 @@ function Canvas2D({
|
|
|
14304
14390
|
// Side-view asset resolution
|
|
14305
14391
|
playerSprite,
|
|
14306
14392
|
tileSprites,
|
|
14307
|
-
bgColor =
|
|
14393
|
+
bgColor = DEFAULT_BG_COLOR,
|
|
14308
14394
|
worldWidth = 800,
|
|
14309
14395
|
worldHeight = 400,
|
|
14310
14396
|
// Remote asset loading
|
|
14311
14397
|
assetManifest
|
|
14312
14398
|
}) {
|
|
14313
|
-
const backgroundImage =
|
|
14399
|
+
const backgroundImage = normalizeBackdrop2(backgroundImageRaw);
|
|
14314
14400
|
const isSide = projection === "side";
|
|
14315
14401
|
const isFree = projection === "free";
|
|
14316
14402
|
const flatLike = projection === "hex" || projection === "flat" || isFree;
|
|
@@ -14494,7 +14580,7 @@ function Canvas2D({
|
|
|
14494
14580
|
return sortedTiles.map((t2) => ({
|
|
14495
14581
|
x: t2.x,
|
|
14496
14582
|
y: t2.y,
|
|
14497
|
-
color: t2.terrain
|
|
14583
|
+
color: MINIMAP_TERRAIN_COLORS[t2.terrain ?? ""] ?? MINIMAP_TERRAIN_COLORS.default
|
|
14498
14584
|
}));
|
|
14499
14585
|
}, [showMinimap, sortedTiles]);
|
|
14500
14586
|
const miniMapUnits = useMemo(() => {
|
|
@@ -14502,7 +14588,7 @@ function Canvas2D({
|
|
|
14502
14588
|
return units.filter((u) => u.position).map((u) => ({
|
|
14503
14589
|
x: u.position.x,
|
|
14504
14590
|
y: u.position.y,
|
|
14505
|
-
color: u.team
|
|
14591
|
+
color: MINIMAP_UNIT_COLORS[u.team ?? ""] ?? MINIMAP_UNIT_COLORS.default,
|
|
14506
14592
|
isPlayer: u.team === "player"
|
|
14507
14593
|
}));
|
|
14508
14594
|
}, [showMinimap, units]);
|
|
@@ -14539,7 +14625,7 @@ function Canvas2D({
|
|
|
14539
14625
|
}
|
|
14540
14626
|
}
|
|
14541
14627
|
} else {
|
|
14542
|
-
ctx.fillStyle =
|
|
14628
|
+
ctx.fillStyle = BACKGROUND_FALLBACK_COLOR;
|
|
14543
14629
|
ctx.fillRect(0, 0, viewportSize.width, viewportSize.height);
|
|
14544
14630
|
}
|
|
14545
14631
|
if (sortedTiles.length === 0 && units.length === 0 && features.length === 0) return;
|
|
@@ -14569,15 +14655,15 @@ function Canvas2D({
|
|
|
14569
14655
|
} else if (img && img.naturalWidth === 0) {
|
|
14570
14656
|
ctx.drawImage(img, pos.x, pos.y, scaledTileWidth, scaledTileHeight);
|
|
14571
14657
|
} else if (squareGrid) {
|
|
14572
|
-
ctx.fillStyle = tile
|
|
14658
|
+
ctx.fillStyle = resolveTileFallbackColor(tile);
|
|
14573
14659
|
ctx.fillRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
|
|
14574
|
-
ctx.strokeStyle =
|
|
14660
|
+
ctx.strokeStyle = GRID_STROKE_COLOR;
|
|
14575
14661
|
ctx.lineWidth = 1;
|
|
14576
14662
|
ctx.strokeRect(pos.x, pos.y, scaledTileWidth, scaledTileWidth);
|
|
14577
14663
|
} else {
|
|
14578
14664
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
14579
14665
|
const topY = pos.y + scaledDiamondTopY;
|
|
14580
|
-
ctx.fillStyle = tile
|
|
14666
|
+
ctx.fillStyle = resolveTileFallbackColor(tile);
|
|
14581
14667
|
ctx.beginPath();
|
|
14582
14668
|
ctx.moveTo(centerX, topY);
|
|
14583
14669
|
ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
|
|
@@ -14585,7 +14671,7 @@ function Canvas2D({
|
|
|
14585
14671
|
ctx.lineTo(pos.x, topY + scaledFloorHeight / 2);
|
|
14586
14672
|
ctx.closePath();
|
|
14587
14673
|
ctx.fill();
|
|
14588
|
-
ctx.strokeStyle =
|
|
14674
|
+
ctx.strokeStyle = GRID_STROKE_COLOR;
|
|
14589
14675
|
ctx.lineWidth = 1;
|
|
14590
14676
|
ctx.stroke();
|
|
14591
14677
|
}
|
|
@@ -14606,11 +14692,11 @@ function Canvas2D({
|
|
|
14606
14692
|
ctx.fill();
|
|
14607
14693
|
};
|
|
14608
14694
|
if (hoveredTile && hoveredTile.x === tile.x && hoveredTile.y === tile.y) {
|
|
14609
|
-
drawHighlight(
|
|
14695
|
+
drawHighlight(HIGHLIGHT_COLORS.hover);
|
|
14610
14696
|
}
|
|
14611
14697
|
const tileKey = `${tile.x},${tile.y}`;
|
|
14612
|
-
if (validMoveSet.has(tileKey)) drawHighlight(
|
|
14613
|
-
if (attackTargetSet.has(tileKey)) drawHighlight(
|
|
14698
|
+
if (validMoveSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.validMove);
|
|
14699
|
+
if (attackTargetSet.has(tileKey)) drawHighlight(HIGHLIGHT_COLORS.attack);
|
|
14614
14700
|
if (debug2) {
|
|
14615
14701
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
14616
14702
|
const centerY = squareGrid ? pos.y + scaledTileWidth / 2 : pos.y + scaledFloorHeight / 2 + scaledDiamondTopY;
|
|
@@ -14684,9 +14770,9 @@ function Canvas2D({
|
|
|
14684
14770
|
const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
|
|
14685
14771
|
const unitIsSheet = unit.spriteSheet?.url !== void 0;
|
|
14686
14772
|
const unitSrc = img && !unitIsSheet ? resolveAssetSource(img, unitAsset, bumpAtlas) : null;
|
|
14687
|
-
const SHEET_ROWS = 5;
|
|
14688
14773
|
const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
|
|
14689
|
-
const sheetFrameH = img ? img.naturalHeight /
|
|
14774
|
+
const sheetFrameH = img ? img.naturalHeight / LEGACY_SHEET_ROWS : 0;
|
|
14775
|
+
const legacyFrame = frameRect(0, 0, SHEET_COLUMNS, sheetFrameW, sheetFrameH);
|
|
14690
14776
|
const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
|
|
14691
14777
|
const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
|
|
14692
14778
|
const ar = unitIsSheet ? sheetFrameW / (sheetFrameH || 1) : unitSrc ? unitSrc.aspect : frameW / (frameH || 1);
|
|
@@ -14704,17 +14790,16 @@ function Canvas2D({
|
|
|
14704
14790
|
ctx.globalAlpha = 0.25;
|
|
14705
14791
|
if (img) {
|
|
14706
14792
|
if (unitIsSheet) {
|
|
14707
|
-
ctx.drawImage(img,
|
|
14793
|
+
ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
|
|
14708
14794
|
} else if (unitSrc) {
|
|
14709
14795
|
blit(ctx, unitSrc, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
|
|
14710
14796
|
} else {
|
|
14711
14797
|
ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
|
|
14712
14798
|
}
|
|
14713
14799
|
} else {
|
|
14714
|
-
const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
|
|
14715
14800
|
ctx.beginPath();
|
|
14716
14801
|
ctx.arc(ghostCenterX, ghostGroundY - 16 * scale, 20 * scale, 0, Math.PI * 2);
|
|
14717
|
-
ctx.fillStyle =
|
|
14802
|
+
ctx.fillStyle = resolveUnitTeamColor(unit);
|
|
14718
14803
|
ctx.fill();
|
|
14719
14804
|
}
|
|
14720
14805
|
ctx.restore();
|
|
@@ -14722,7 +14807,7 @@ function Canvas2D({
|
|
|
14722
14807
|
if (isSelected) {
|
|
14723
14808
|
ctx.beginPath();
|
|
14724
14809
|
ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
|
|
14725
|
-
ctx.strokeStyle =
|
|
14810
|
+
ctx.strokeStyle = SELECTION_RING_COLOR;
|
|
14726
14811
|
ctx.lineWidth = 3;
|
|
14727
14812
|
ctx.stroke();
|
|
14728
14813
|
}
|
|
@@ -14739,7 +14824,7 @@ function Canvas2D({
|
|
|
14739
14824
|
const spriteY = groundY - fDrawH - (frame.applyBreathing ? breatheOffset : 0);
|
|
14740
14825
|
ctx.save();
|
|
14741
14826
|
if (unit.team) {
|
|
14742
|
-
ctx.shadowColor = unit.team
|
|
14827
|
+
ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
|
|
14743
14828
|
ctx.shadowBlur = 12 * scale;
|
|
14744
14829
|
}
|
|
14745
14830
|
if (frame.flipX) {
|
|
@@ -14754,7 +14839,7 @@ function Canvas2D({
|
|
|
14754
14839
|
const spriteY = groundY - drawH - breatheOffset;
|
|
14755
14840
|
const drawUnit = (x) => {
|
|
14756
14841
|
if (unitIsSheet) {
|
|
14757
|
-
ctx.drawImage(img,
|
|
14842
|
+
ctx.drawImage(img, legacyFrame.sx, legacyFrame.sy, legacyFrame.sw, legacyFrame.sh, x, spriteY, drawW, drawH);
|
|
14758
14843
|
} else if (unitSrc) {
|
|
14759
14844
|
blit(ctx, unitSrc, x, spriteY, drawW, drawH);
|
|
14760
14845
|
} else {
|
|
@@ -14763,7 +14848,7 @@ function Canvas2D({
|
|
|
14763
14848
|
};
|
|
14764
14849
|
if (unit.team) {
|
|
14765
14850
|
ctx.save();
|
|
14766
|
-
ctx.shadowColor = unit.team
|
|
14851
|
+
ctx.shadowColor = TEAM_SHADOW_COLORS[unit.team] ?? TEAM_SHADOW_COLORS.default;
|
|
14767
14852
|
ctx.shadowBlur = 12 * scale;
|
|
14768
14853
|
drawUnit(centerX - drawW / 2);
|
|
14769
14854
|
ctx.restore();
|
|
@@ -14771,10 +14856,9 @@ function Canvas2D({
|
|
|
14771
14856
|
drawUnit(centerX - drawW / 2);
|
|
14772
14857
|
}
|
|
14773
14858
|
} else {
|
|
14774
|
-
const color = unit.team === "player" ? "#3b82f6" : unit.team === "enemy" ? "#ef4444" : "#6b7280";
|
|
14775
14859
|
ctx.beginPath();
|
|
14776
14860
|
ctx.arc(centerX, groundY - 20 * scale - breatheOffset, 20 * scale, 0, Math.PI * 2);
|
|
14777
|
-
ctx.fillStyle =
|
|
14861
|
+
ctx.fillStyle = resolveUnitTeamColor(unit);
|
|
14778
14862
|
ctx.fill();
|
|
14779
14863
|
ctx.strokeStyle = "rgba(255,255,255,0.8)";
|
|
14780
14864
|
ctx.lineWidth = 2;
|
|
@@ -15013,7 +15097,7 @@ function Canvas2D({
|
|
|
15013
15097
|
}
|
|
15014
15098
|
if (isSide) {
|
|
15015
15099
|
return /* @__PURE__ */ jsx(Box, { ref: containerRef, className: cn("relative overflow-hidden w-full h-full", className), children: /* @__PURE__ */ jsx(
|
|
15016
|
-
|
|
15100
|
+
SideCanvas2D,
|
|
15017
15101
|
{
|
|
15018
15102
|
player,
|
|
15019
15103
|
platforms: platforms && platforms.length ? platforms : DEFAULT_PLATFORMS,
|
|
@@ -15111,7 +15195,7 @@ function Canvas2D({
|
|
|
15111
15195
|
{
|
|
15112
15196
|
as: "span",
|
|
15113
15197
|
className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
|
|
15114
|
-
style: { background: unit.team
|
|
15198
|
+
style: { background: UNIT_LABEL_BG_COLORS[unit.team ?? ""] ?? UNIT_LABEL_BG_COLORS.default },
|
|
15115
15199
|
children: unit.name
|
|
15116
15200
|
}
|
|
15117
15201
|
),
|
|
@@ -15135,7 +15219,7 @@ function Canvas2D({
|
|
|
15135
15219
|
}
|
|
15136
15220
|
);
|
|
15137
15221
|
}
|
|
15138
|
-
var
|
|
15222
|
+
var LEGACY_SHEET_ROWS, DEFAULT_PLATFORMS;
|
|
15139
15223
|
var init_Canvas2D = __esm({
|
|
15140
15224
|
"components/game/2d/molecules/Canvas2D.tsx"() {
|
|
15141
15225
|
"use client";
|
|
@@ -15157,19 +15241,9 @@ var init_Canvas2D = __esm({
|
|
|
15157
15241
|
init_verificationRegistry();
|
|
15158
15242
|
init_isometric();
|
|
15159
15243
|
init_spriteSheetConstants();
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
hazard: "#c0392b",
|
|
15164
|
-
goal: "#f1c40f"
|
|
15165
|
-
};
|
|
15166
|
-
NOOP = () => {
|
|
15167
|
-
};
|
|
15168
|
-
PLAYER_COLOR = "#3498db";
|
|
15169
|
-
PLAYER_EYE_COLOR = "#ffffff";
|
|
15170
|
-
SKY_GRADIENT_TOP = "#1a1a2e";
|
|
15171
|
-
SKY_GRADIENT_BOTTOM = "#16213e";
|
|
15172
|
-
GRID_COLOR = "rgba(255, 255, 255, 0.03)";
|
|
15244
|
+
init_spriteAnimation();
|
|
15245
|
+
init_SideCanvas2D();
|
|
15246
|
+
LEGACY_SHEET_ROWS = Object.keys(SPRITE_SHEET_LAYOUT).length;
|
|
15173
15247
|
DEFAULT_PLATFORMS = [
|
|
15174
15248
|
{ x: 0, y: 368, width: 800, height: 32, type: "ground" },
|
|
15175
15249
|
{ x: 150, y: 280, width: 160, height: 16, type: "platform" },
|
|
@@ -33255,13 +33329,13 @@ var init_MapView = __esm({
|
|
|
33255
33329
|
shadowSize: [41, 41]
|
|
33256
33330
|
});
|
|
33257
33331
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
33258
|
-
const { useEffect:
|
|
33332
|
+
const { useEffect: useEffect72, useRef: useRef69, useCallback: useCallback105, useState: useState105 } = React105__default;
|
|
33259
33333
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
33260
33334
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
33261
33335
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
33262
33336
|
const map = useMap();
|
|
33263
|
-
const prevRef =
|
|
33264
|
-
|
|
33337
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
33338
|
+
useEffect72(() => {
|
|
33265
33339
|
const prev = prevRef.current;
|
|
33266
33340
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
33267
33341
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -33272,7 +33346,7 @@ var init_MapView = __esm({
|
|
|
33272
33346
|
}
|
|
33273
33347
|
function MapClickHandler({ onMapClick }) {
|
|
33274
33348
|
const map = useMap();
|
|
33275
|
-
|
|
33349
|
+
useEffect72(() => {
|
|
33276
33350
|
if (!onMapClick) return;
|
|
33277
33351
|
const handler = (e) => {
|
|
33278
33352
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -33301,7 +33375,7 @@ var init_MapView = __esm({
|
|
|
33301
33375
|
}) {
|
|
33302
33376
|
const eventBus = useEventBus2();
|
|
33303
33377
|
const [clickedPosition, setClickedPosition] = useState105(null);
|
|
33304
|
-
const handleMapClick =
|
|
33378
|
+
const handleMapClick = useCallback105((lat, lng) => {
|
|
33305
33379
|
if (showClickedPin) {
|
|
33306
33380
|
setClickedPosition({ lat, lng });
|
|
33307
33381
|
}
|
|
@@ -33310,7 +33384,7 @@ var init_MapView = __esm({
|
|
|
33310
33384
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
33311
33385
|
}
|
|
33312
33386
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
33313
|
-
const handleMarkerClick =
|
|
33387
|
+
const handleMarkerClick = useCallback105((marker) => {
|
|
33314
33388
|
onMarkerClick?.(marker);
|
|
33315
33389
|
if (markerClickEvent) {
|
|
33316
33390
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -126,7 +126,7 @@ export interface Canvas2DProps {
|
|
|
126
126
|
/**
|
|
127
127
|
* Opt-in: smooth-interpolate unit positions between LOLO tick snapshots
|
|
128
128
|
* via a `requestAnimationFrame` loop (same fixed-timestep technique
|
|
129
|
-
* `
|
|
129
|
+
* `SideCanvas2D` already uses for the player), instead of the default
|
|
130
130
|
* tick-rate-cadence redraw. DEFAULT OFF — for continuous-movement boards
|
|
131
131
|
* only; tile-snapped boards see no behavior change.
|
|
132
132
|
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SideCanvas2D
|
|
3
|
+
*
|
|
4
|
+
* Side-view platformer renderer — extracted from Canvas2D's private `SideView` branch.
|
|
5
|
+
* Physics is NOT here (it lives in the LOLO model); this only interpolates+draws the
|
|
6
|
+
* authoritative `player`/`platforms` props and translates keyboard input into the
|
|
7
|
+
* board's semantic events via keyMap/keyUpMap.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
import type { Asset, AssetUrl } from '@almadar/core';
|
|
13
|
+
import type { ActiveEffect } from '../../shared/isometricTypes';
|
|
14
|
+
import type { Platform, SidePlayer } from './Canvas2D';
|
|
15
|
+
export interface SideCanvas2DProps {
|
|
16
|
+
player?: SidePlayer;
|
|
17
|
+
platforms: Platform[];
|
|
18
|
+
worldWidth: number;
|
|
19
|
+
worldHeight: number;
|
|
20
|
+
canvasWidth: number;
|
|
21
|
+
canvasHeight: number;
|
|
22
|
+
follow: boolean;
|
|
23
|
+
bgColor: string;
|
|
24
|
+
backgroundImage?: AssetUrl | Asset;
|
|
25
|
+
playerSprite?: Asset;
|
|
26
|
+
tileSprites?: Record<string, Asset>;
|
|
27
|
+
effects: ActiveEffect[];
|
|
28
|
+
keyMap?: Record<string, string>;
|
|
29
|
+
keyUpMap?: Record<string, string>;
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function SideCanvas2D({ player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, follow, bgColor, backgroundImage: backgroundImageRaw, playerSprite, tileSprites, effects, keyMap, keyUpMap, className, }: SideCanvas2DProps): React.JSX.Element;
|
|
33
|
+
export declare namespace SideCanvas2D {
|
|
34
|
+
var displayName: string;
|
|
35
|
+
}
|
|
36
|
+
export default SideCanvas2D;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventMarker3D
|
|
3
|
+
*
|
|
4
|
+
* Floating combat/feedback marker for one `GameEvent` — billboarded text above
|
|
5
|
+
* the cell. Lifetime is LOLO-owned: boards append events on actions and expire
|
|
6
|
+
* them in their tick (same contract as the 2D effects array).
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import type { GameEvent } from '../molecules/GameCanvas3D';
|
|
12
|
+
export interface EventMarker3DProps {
|
|
13
|
+
event: GameEvent;
|
|
14
|
+
position: [number, number, number];
|
|
15
|
+
}
|
|
16
|
+
export declare function EventMarker3D({ event, position }: EventMarker3DProps): React.JSX.Element;
|
|
17
|
+
export default EventMarker3D;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SpriteBillboard3D
|
|
3
|
+
*
|
|
4
|
+
* Billboarded sprite-sheet plane for a unit. Loads the atlas's PNG sheet as a
|
|
5
|
+
* texture and crops a SINGLE frame via UV `repeat`/`offset`, advancing per
|
|
6
|
+
* animation state. Mirrors the 2D canvas: one frame, never the whole sheet.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import type { ResolvedFrame } from '../../shared/spriteAnimationTypes';
|
|
12
|
+
export interface SpriteBillboard3DProps {
|
|
13
|
+
sheetUrl: string;
|
|
14
|
+
resolveFrame: () => ResolvedFrame | null;
|
|
15
|
+
height?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function SpriteBillboard3D({ sheetUrl, resolveFrame, height, }: SpriteBillboard3DProps): React.JSX.Element | null;
|
|
18
|
+
export default SpriteBillboard3D;
|