feat(catan): refine hex tile rendering with inset borders and background
- Add `background-catan-board.png` for enhanced board visuals - Implement inset polygon logic to create layered hex borders (colored swatch, dark ring, image area) - Adjust tile image scaling to fit within the innermost inset polygon - Reduce outer border line width for a crisper appearance - Add fallback resource color fill for the inner image area if texture is missing
This commit is contained in:
parent
e562ed21b8
commit
7439945416
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
|
|
@ -106,31 +106,51 @@ export default class CatanGame extends Phaser.Scene {
|
||||||
this.hexLabels.forEach((t) => t.destroy());
|
this.hexLabels.forEach((t) => t.destroy());
|
||||||
this.hexLabels = [];
|
this.hexLabels = [];
|
||||||
|
|
||||||
|
// Inset a convex hex polygon toward its center.
|
||||||
|
// s=0 collapses to point; s=1 is original. Uses inradius (79.7px) as scale reference.
|
||||||
|
const inset = (pts, cx, cy, s) =>
|
||||||
|
pts.map(p => ({ x: cx + (p.x - cx) * s, y: cy + (p.y - cy) * s }));
|
||||||
|
|
||||||
for (const hex of this.gs.hexes) {
|
for (const hex of this.gs.hexes) {
|
||||||
const pts = HEXES[hex.id].corners.map((c) => ({ x: NODES[c].x, y: NODES[c].y }));
|
const pts = HEXES[hex.id].corners.map((c) => ({ x: NODES[c].x, y: NODES[c].y }));
|
||||||
const { x, y } = this.hexPos(hex.id);
|
const { x, y } = this.hexPos(hex.id);
|
||||||
|
|
||||||
// Color fill as fallback base layer
|
// Inradius ≈ 79.7; compute scale factors for 7px colored ring + 4px dark ring
|
||||||
const color = hex.resource === 'desert' ? DESERT_COLOR : RESOURCE_INFO[hex.resource].color;
|
const s1 = 1 - 7 / (HEX_SIZE * Math.sqrt(3) / 2); // after colored border
|
||||||
g.fillStyle(color, 1);
|
const s2 = 1 - 11 / (HEX_SIZE * Math.sqrt(3) / 2); // after dark border (image area)
|
||||||
|
const innerPts = inset(pts, x, y, s1);
|
||||||
|
const imagePts = inset(pts, x, y, s2);
|
||||||
|
|
||||||
|
// Layer 1: resource swatch fill (outer colored border ring)
|
||||||
|
const swatch = hex.resource === 'desert' ? DESERT_COLOR : RESOURCE_INFO[hex.resource].swatch;
|
||||||
|
g.fillStyle(swatch, 1);
|
||||||
g.fillPoints(pts, true);
|
g.fillPoints(pts, true);
|
||||||
|
|
||||||
// Tile image clipped to hex polygon
|
// Layer 2: dark fill inset (inner black border ring)
|
||||||
|
g.fillStyle(0x111111, 1);
|
||||||
|
g.fillPoints(innerPts, true);
|
||||||
|
|
||||||
|
// Layer 3: tile image masked to innermost polygon
|
||||||
if (this.textures.exists('catan-tiles')) {
|
if (this.textures.exists('catan-tiles')) {
|
||||||
const frames = CatanGame.TILE_FRAMES[hex.resource] ?? [10, 11];
|
const frames = CatanGame.TILE_FRAMES[hex.resource] ?? [10, 11];
|
||||||
const frame = frames[Math.floor(Math.random() * 2)];
|
const frame = frames[Math.floor(Math.random() * 2)];
|
||||||
const maskG = this.make.graphics({ x: 0, y: 0, add: false });
|
const maskG = this.make.graphics({ x: 0, y: 0, add: false });
|
||||||
maskG.fillStyle(0xffffff);
|
maskG.fillStyle(0xffffff);
|
||||||
maskG.fillPoints(pts, true);
|
maskG.fillPoints(imagePts, true);
|
||||||
const img = this.add.image(x, y, 'catan-tiles', frame)
|
const img = this.add.image(x, y, 'catan-tiles', frame)
|
||||||
.setDisplaySize(HEX_W, HEX_SIZE * 2)
|
.setDisplaySize(HEX_W * s2, HEX_SIZE * 2 * s2)
|
||||||
.setMask(maskG.createGeometryMask())
|
.setMask(maskG.createGeometryMask())
|
||||||
.setDepth(D.board + 1);
|
.setDepth(D.board + 1);
|
||||||
this.hexImgs.push({ img, maskG });
|
this.hexImgs.push({ img, maskG });
|
||||||
|
} else {
|
||||||
|
// Fallback: resource color fill in the image area
|
||||||
|
const color = hex.resource === 'desert' ? DESERT_COLOR : RESOURCE_INFO[hex.resource].color;
|
||||||
|
g.fillStyle(color, 1);
|
||||||
|
g.fillPoints(imagePts, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Border on top of images
|
// Thin outer crisp stroke
|
||||||
this.hexBorderGfx.lineStyle(4, 0x6b4a1a, 0.85);
|
this.hexBorderGfx.lineStyle(2, 0x4a3210, 0.8);
|
||||||
this.hexBorderGfx.strokePoints(pts, true);
|
this.hexBorderGfx.strokePoints(pts, true);
|
||||||
|
|
||||||
// Resource label
|
// Resource label
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue