diff --git a/assets/images/advancewars/advancewars-buildings.png b/assets/images/advancewars/advancewars-buildings.png index 2ea6d9d..91b8796 100644 Binary files a/assets/images/advancewars/advancewars-buildings.png and b/assets/images/advancewars/advancewars-buildings.png differ diff --git a/assets/images/advancewars/advancewars-terrain.png b/assets/images/advancewars/advancewars-terrain.png index 36178c8..cb21486 100644 Binary files a/assets/images/advancewars/advancewars-terrain.png and b/assets/images/advancewars/advancewars-terrain.png differ diff --git a/assets/images/advancewars/advancewars-terrain.psd b/assets/images/advancewars/advancewars-terrain.psd index c6151e0..4021e75 100644 Binary files a/assets/images/advancewars/advancewars-terrain.psd and b/assets/images/advancewars/advancewars-terrain.psd differ diff --git a/src/games/advancewars/AdvanceWarsGame.js b/src/games/advancewars/AdvanceWarsGame.js index 85169c0..fa1170e 100644 --- a/src/games/advancewars/AdvanceWarsGame.js +++ b/src/games/advancewars/AdvanceWarsGame.js @@ -424,7 +424,7 @@ export default class AdvanceWarsGame extends Phaser.Scene { const run = this.run; run.mode = 'target'; run.targets = targets; - run.view.showAttackTiles(targets.map((t) => ({ x: t.x, y: t.y }))); + run.view.showAttackTiles(targets.map((t) => ({ x: t.x, y: t.y })), { pulse: true }); } onTargetClick(tile) { diff --git a/src/games/advancewars/AdvanceWarsMapView.js b/src/games/advancewars/AdvanceWarsMapView.js index 2418f98..5ce4fbc 100644 --- a/src/games/advancewars/AdvanceWarsMapView.js +++ b/src/games/advancewars/AdvanceWarsMapView.js @@ -246,6 +246,7 @@ export class AdvanceWarsMapView { destroy() { this.flipTimer?.remove(); + this.atkPulseTween?.stop(); this.rt?.destroy(); this.moveG?.destroy(); this.atkG?.destroy(); this.fogG?.destroy(); this.pathG?.destroy(); this.cursor?.destroy(); @@ -492,15 +493,42 @@ export class AdvanceWarsMapView { } } - showAttackTiles(tiles) { + // pulse: true for "you must pick a target now" (entering FIRE target mode) + // — red fill + white border breathing to draw the eye. false (default) + // keeps the old static tint, used for the indirect-range preview shown + // while a unit is merely selected, before a move/target is committed to. + showAttackTiles(tiles, { pulse = false } = {}) { + this.atkPulseTween?.stop(); + this.atkPulseTween = null; this.atkG.clear(); - this.atkG.fillStyle(0xff3d3d, 0.42); - for (const { x, y } of tiles) { - this.atkG.fillRect(this.ox + x * this.tile + 1, this.oy + y * this.tile + 1, this.tile - 2, this.tile - 2); + if (!pulse) { + this.atkG.fillStyle(0xff3d3d, 0.42); + for (const { x, y } of tiles) { + this.atkG.fillRect(this.ox + x * this.tile + 1, this.oy + y * this.tile + 1, this.tile - 2, this.tile - 2); + } + return; } + const draw = (fillA, lineA) => { + this.atkG.clear(); + this.atkG.fillStyle(0xff3d3d, fillA); + this.atkG.lineStyle(Math.max(2, this.tile * 0.06), 0xffffff, lineA); + for (const { x, y } of tiles) { + const px = this.ox + x * this.tile + 1, py = this.oy + y * this.tile + 1, s = this.tile - 2; + this.atkG.fillRect(px, py, s, s); + this.atkG.strokeRect(px, py, s, s); + } + }; + const phase = { t: 0 }; + draw(0.30, 0.55); + this.atkPulseTween = this.scene.tweens.add({ + targets: phase, t: 1, duration: 550, yoyo: true, repeat: -1, ease: 'Sine.easeInOut', + onUpdate: () => draw(0.28 + phase.t * 0.34, 0.5 + phase.t * 0.5), + }); } clearOverlays() { + this.atkPulseTween?.stop(); + this.atkPulseTween = null; this.moveG.clear(); this.atkG.clear(); this.pathG.clear();