feat(advancewars): add HP text display to battle animations and procedural cursor
- Add HP text readout to battle animations showing 1-10 scale HP (matching Advance Wars' classic HP display), with smooth tweening - Extract cursor drawing into procedural texture, keeping it independent of the UI sheet - Add advancewars-ui.png sprite sheet and update artwork config
This commit is contained in:
parent
c0ad354458
commit
f96f2d491c
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
|
@ -20,7 +20,7 @@
|
||||||
},
|
},
|
||||||
"uiSheet": {
|
"uiSheet": {
|
||||||
"key": "advancewars-ui",
|
"key": "advancewars-ui",
|
||||||
"path": null,
|
"path": "assets/images/advancewars/advancewars-ui.png",
|
||||||
"frameWidth": 48,
|
"frameWidth": 48,
|
||||||
"frameHeight": 48
|
"frameHeight": 48
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { playSound } from '../../ui/Sounds.js';
|
||||||
|
|
||||||
const W = 760;
|
const W = 760;
|
||||||
const H = 380;
|
const H = 380;
|
||||||
|
const HP_TEXT_PADDING = 20;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Battle backgrounds: one backdrop image per terrain/building a fighter can
|
// Battle backgrounds: one backdrop image per terrain/building a fighter can
|
||||||
|
|
@ -232,7 +233,14 @@ export function playBattleAnim(scene, rules, state, texKey, battles, onDone) {
|
||||||
const bar = scene.add.rectangle(cx + side * W / 4 - 108, cy - H / 2 + 58, 216, 12,
|
const bar = scene.add.rectangle(cx + side * W / 4 - 108, cy - H / 2 + 58, 216, 12,
|
||||||
0x7dff9a, 1).setOrigin(0, 0.5).setDepth(52);
|
0x7dff9a, 1).setOrigin(0, 0.5).setDepth(52);
|
||||||
objs.push(barBg, bar);
|
objs.push(barBg, bar);
|
||||||
return { img, bar, spec };
|
// remaining-HP readout in the outer top corner of this fighter's half —
|
||||||
|
// same font/size as the capture cut-in's points counter. 1-10 scale
|
||||||
|
// (AW's classic HP display), zero being the floor.
|
||||||
|
const hpText = scene.add.text(cx + side * W / 2 - side * HP_TEXT_PADDING, cy - H / 2 + HP_TEXT_PADDING, '',
|
||||||
|
{ fontFamily: FONT, fontSize: '64px', color: '#ffe14d', stroke: '#000000', strokeThickness: 6 })
|
||||||
|
.setOrigin(side > 0 ? 1 : 0, 0).setDepth(51);
|
||||||
|
objs.push(hpText);
|
||||||
|
return { img, bar, spec, hpText };
|
||||||
};
|
};
|
||||||
|
|
||||||
// starting HP = hp before the volleys (event carries post-hit hp; rebuild)
|
// starting HP = hp before the volleys (event carries post-hit hp; rebuild)
|
||||||
|
|
@ -249,8 +257,18 @@ export function playBattleAnim(scene, rules, state, texKey, battles, onDone) {
|
||||||
f.bar.width = Math.max(0, 216 * (hp / 100));
|
f.bar.width = Math.max(0, 216 * (hp / 100));
|
||||||
f.bar.setFillStyle(hp > 50 ? 0x7dff9a : hp > 25 ? 0xffe14d : 0xff5a5a, 1);
|
f.bar.setFillStyle(hp > 50 ? 0x7dff9a : hp > 25 ? 0xffe14d : 0xff5a5a, 1);
|
||||||
};
|
};
|
||||||
|
const hpDisplay = (hp) => Math.max(0, Math.ceil(hp / 10));
|
||||||
|
const animateHp = (f, fromHp, toHp) => {
|
||||||
|
const proxy = { hp: fromHp };
|
||||||
|
scene.tweens.add({
|
||||||
|
targets: proxy, hp: toHp, duration: 500, ease: 'Sine.easeOut',
|
||||||
|
onUpdate: () => f.hpText.setText(String(hpDisplay(proxy.hp))),
|
||||||
|
});
|
||||||
|
};
|
||||||
setBar(left, leftHp);
|
setBar(left, leftHp);
|
||||||
setBar(right, rightHp);
|
setBar(right, rightHp);
|
||||||
|
left.hpText.setText(String(hpDisplay(leftHp)));
|
||||||
|
right.hpText.setText(String(hpDisplay(rightHp)));
|
||||||
|
|
||||||
const flip = scene.time.addEvent({
|
const flip = scene.time.addEvent({
|
||||||
delay: 220, loop: true, callback: () => {
|
delay: 220, loop: true, callback: () => {
|
||||||
|
|
@ -290,8 +308,17 @@ export function playBattleAnim(scene, rules, state, texKey, battles, onDone) {
|
||||||
objs.push(flash);
|
objs.push(flash);
|
||||||
scene.tweens.add({ targets: flash, alpha: 0, duration: 450, onComplete: () => flash.destroy() });
|
scene.tweens.add({ targets: flash, alpha: 0, duration: 450, onComplete: () => flash.destroy() });
|
||||||
scene.cameras.main.shake(120, 0.004);
|
scene.cameras.main.shake(120, 0.004);
|
||||||
if (fromLeft) { rightHp = b.defender.hp; setBar(right, rightHp); }
|
if (fromLeft) {
|
||||||
else { leftHp = b.defender.hp; setBar(left, leftHp); }
|
const prevHp = rightHp;
|
||||||
|
rightHp = b.defender.hp;
|
||||||
|
setBar(right, rightHp);
|
||||||
|
animateHp(right, prevHp, rightHp);
|
||||||
|
} else {
|
||||||
|
const prevHp = leftHp;
|
||||||
|
leftHp = b.defender.hp;
|
||||||
|
setBar(left, leftHp);
|
||||||
|
animateHp(left, prevHp, leftHp);
|
||||||
|
}
|
||||||
if (b.killed) {
|
if (b.killed) {
|
||||||
scene.tweens.add({ targets: victim.img, alpha: 0, y: victim.img.y + 16, duration: 550 });
|
scene.tweens.add({ targets: victim.img, alpha: 0, y: victim.img.y + 16, duration: 550 });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,25 @@ function mkCanvasSheet(scene, key, spec, count) {
|
||||||
|
|
||||||
const ground = (c, color) => { c.fillStyle = color; c.fillRect(0, 0, CELL, CELL); };
|
const ground = (c, color) => { c.fillStyle = color; c.fillRect(0, 0, CELL, CELL); };
|
||||||
|
|
||||||
|
// Tile cursor is always the built-in procedural corner-bracket art — kept
|
||||||
|
// independent of the UI sheet even once it's painted, per explicit request.
|
||||||
|
function drawCursor(c) {
|
||||||
|
c.strokeStyle = '#ffffff'; c.lineWidth = 4;
|
||||||
|
for (const [sx, sy, dx, dy] of [[3, 3, 1, 1], [45, 3, -1, 1], [3, 45, 1, -1], [45, 45, -1, -1]]) {
|
||||||
|
c.beginPath(); c.moveTo(sx + dx * 12, sy); c.lineTo(sx, sy); c.lineTo(sx, sy + dy * 12); c.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CURSOR_TEX_KEY = 'advancewars-cursor-proc';
|
||||||
|
|
||||||
|
function ensureCursorTexture(scene) {
|
||||||
|
if (scene.textures.exists(CURSOR_TEX_KEY)) return CURSOR_TEX_KEY;
|
||||||
|
const tex = scene.textures.createCanvas(CURSOR_TEX_KEY, CELL, CELL);
|
||||||
|
drawCursor(tex.getContext());
|
||||||
|
tex.refresh();
|
||||||
|
return CURSOR_TEX_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
const PROC_PAINTERS = {
|
const PROC_PAINTERS = {
|
||||||
terrain(scene, key, spec) {
|
terrain(scene, key, spec) {
|
||||||
const { at, finish } = mkCanvasSheet(scene, key, spec, spec.frames);
|
const { at, finish } = mkCanvasSheet(scene, key, spec, spec.frames);
|
||||||
|
|
@ -180,12 +199,7 @@ const PROC_PAINTERS = {
|
||||||
|
|
||||||
ui(scene, key, spec) {
|
ui(scene, key, spec) {
|
||||||
const { at, finish } = mkCanvasSheet(scene, key, spec, spec.frames);
|
const { at, finish } = mkCanvasSheet(scene, key, spec, spec.frames);
|
||||||
at(UI_FRAMES.cursor, (c) => {
|
at(UI_FRAMES.cursor, drawCursor);
|
||||||
c.strokeStyle = '#ffffff'; c.lineWidth = 4;
|
|
||||||
for (const [sx, sy, dx, dy] of [[3, 3, 1, 1], [45, 3, -1, 1], [3, 45, 1, -1], [45, 45, -1, -1]]) {
|
|
||||||
c.beginPath(); c.moveTo(sx + dx * 12, sy); c.lineTo(sx, sy); c.lineTo(sx, sy + dy * 12); c.stroke();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const boom = (r) => (c) => {
|
const boom = (r) => (c) => {
|
||||||
c.fillStyle = '#ffb02f';
|
c.fillStyle = '#ffb02f';
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
|
|
@ -244,7 +258,7 @@ export class AdvanceWarsMapView {
|
||||||
this.atkG = scene.add.graphics().setDepth(this.depths.atkOv);
|
this.atkG = scene.add.graphics().setDepth(this.depths.atkOv);
|
||||||
this.fogG = scene.add.graphics().setDepth(this.depths.fog);
|
this.fogG = scene.add.graphics().setDepth(this.depths.fog);
|
||||||
this.pathG = scene.add.graphics().setDepth(this.depths.path);
|
this.pathG = scene.add.graphics().setDepth(this.depths.path);
|
||||||
this.cursor = scene.add.image(0, 0, this.tex.ui, UI_FRAMES.cursor)
|
this.cursor = scene.add.image(0, 0, ensureCursorTexture(scene))
|
||||||
.setDisplaySize(this.tile, this.tile)
|
.setDisplaySize(this.tile, this.tile)
|
||||||
.setDepth(this.depths.cursor).setVisible(false);
|
.setDepth(this.depths.cursor).setVisible(false);
|
||||||
this.syncUnits();
|
this.syncUnits();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue