Enlarge battle UI icons

This commit is contained in:
2026-07-02 21:35:48 +09:00
parent e5706dc71f
commit 79e535c2bb
4 changed files with 172 additions and 109 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -3,7 +3,7 @@ import Phaser from 'phaser';
import battleUiIconsUrl from '../../assets/images/ui/battle-ui-icons.png';
export const battleUiIconTextureKey = 'battle-ui-icons';
export const battleUiIconFrameSize = 48;
export const battleUiIconFrameSize = 64;
export const battleUiIconFrames = {
hp: 0,
@@ -27,7 +27,11 @@ export const battleUiIconFrames = {
terrain: 18,
counter: 19,
advantage: 20,
success: 21
success: 21,
heal: 22,
focus: 23,
fire: 24,
shout: 25
} as const;
export type BattleUiIconKey = keyof typeof battleUiIconFrames;
@@ -38,7 +42,7 @@ export const battleUiIconManifest = {
frameWidth: battleUiIconFrameSize,
frameHeight: battleUiIconFrameSize,
columns: 5,
rows: 5,
rows: 6,
frames: battleUiIconFrames
} as const;

View File

@@ -4170,12 +4170,12 @@ export class BattleScene extends Phaser.Scene {
background.setInteractive({ useHandCursor: true });
background.setDepth(15);
const iconFrame = this.add.rectangle(left + 27, centerY, 26, 26, 0x0a0f14, 0.86);
const iconFrame = this.add.rectangle(left + 28, centerY, 30, 30, 0x0a0f14, 0.86);
iconFrame.setStrokeStyle(1, command === 'wait' ? palette.gold : palette.blue, 0.58);
iconFrame.setDepth(16);
this.commandMenuObjects.push(iconFrame);
const icon = this.createBattleUiIcon(left + 27, centerY, this.commandIcon(command, unit), 22);
const icon = this.createBattleUiIcon(left + 28, centerY, this.commandIcon(command, unit), 26);
icon.setDepth(17);
this.commandMenuObjects.push(icon);
@@ -4294,22 +4294,22 @@ export class BattleScene extends Phaser.Scene {
}
private renderUsableMenuPill(x: number, y: number, width: number, icon: BattleUiIconKey, label: string, tone: number) {
const pill = this.add.rectangle(x, y, width, 22, 0x0b1118, 0.92);
const pill = this.add.rectangle(x, y, width, 26, 0x0b1118, 0.92);
pill.setOrigin(0);
pill.setDepth(16);
pill.setStrokeStyle(1, tone, 0.54);
this.commandMenuObjects.push(pill);
const iconImage = this.createBattleUiIcon(x + 12, y + 11, icon, 16);
const iconImage = this.createBattleUiIcon(x + 14, y + 13, icon, 20);
iconImage.setDepth(17);
this.commandMenuObjects.push(iconImage);
const text = this.add.text(x + 25, y + 5, label, {
const text = this.add.text(x + 30, y + 6, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '10px',
fontSize: '11px',
color: '#d4dce6',
fontStyle: '700',
fixedWidth: width - 29
fixedWidth: width - 34
});
text.setDepth(17);
this.commandMenuObjects.push(text);
@@ -4334,9 +4334,9 @@ export class BattleScene extends Phaser.Scene {
this.hideCommandMenu();
const menuWidth = 322;
const menuWidth = 348;
const titleHeight = 36;
const rowHeight = 72;
const rowHeight = 82;
const padding = 9;
const menuHeight = padding * 2 + titleHeight + usables.length * rowHeight;
const { left, top } = this.commandMenuPosition(pointerX, pointerY, menuWidth, menuHeight);
@@ -4368,26 +4368,26 @@ export class BattleScene extends Phaser.Scene {
bg.setInteractive({ useHandCursor: true });
this.commandMenuObjects.push(bg);
const iconFrame = this.add.rectangle(left + 31, rowTop + 32, 38, 38, 0x0a0f14, 0.9);
const iconFrame = this.add.rectangle(left + 36, rowTop + 38, 50, 50, 0x0a0f14, 0.9);
iconFrame.setStrokeStyle(1, accent, 0.66);
iconFrame.setDepth(16);
this.commandMenuObjects.push(iconFrame);
const icon = this.createBattleUiIcon(left + 31, rowTop + 32, this.usableIcon(usable), 32);
const icon = this.createBattleUiIcon(left + 36, rowTop + 38, this.usableIcon(usable), 44);
icon.setDepth(17);
this.commandMenuObjects.push(icon);
const stock = this.usableStockLabel(unit, usable);
const name = this.add.text(left + 56, rowTop + 7, usable.name, {
const name = this.add.text(left + 68, rowTop + 8, usable.name, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '17px',
fontSize: '18px',
color: '#f2e3bf',
fontStyle: '700'
});
name.setDepth(16);
this.commandMenuObjects.push(name);
const stockText = this.add.text(left + menuWidth - 24, rowTop + 9, stock, {
const stockText = this.add.text(left + menuWidth - 24, rowTop + 10, stock, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: command === 'item' ? '#f4dfad' : '#9fb0bf',
@@ -4398,22 +4398,22 @@ export class BattleScene extends Phaser.Scene {
this.commandMenuObjects.push(stockText);
const summary = this.add.text(
left + 56,
rowTop + 31,
left + 68,
rowTop + 34,
`${this.usableEffectLabel(usable)} · ${this.usableTargetLabel(usable)} · 사거리 ${usable.range} · 대상 ${this.usableTargetCount(unit, usable)}`,
{
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#aeb7c2',
fixedWidth: menuWidth - 74
fixedWidth: menuWidth - 88
}
);
summary.setDepth(16);
this.commandMenuObjects.push(summary);
this.renderUsableMenuPill(left + 56, rowTop + 43, 78, this.usableIcon(usable), this.usableEffectLabel(usable), accent);
this.renderUsableMenuPill(left + 140, rowTop + 43, 86, 'move', `거리 ${usable.range}`, accent);
this.renderUsableMenuPill(left + 232, rowTop + 43, 82, usable.target === 'enemy' ? 'hit' : 'success', this.usablePowerLabel(usable), accent);
this.renderUsableMenuPill(left + 68, rowTop + 49, 82, this.usableIcon(usable), this.usableEffectLabel(usable), accent);
this.renderUsableMenuPill(left + 156, rowTop + 49, 90, 'move', `거리 ${usable.range}`, accent);
this.renderUsableMenuPill(left + 252, rowTop + 49, 86, usable.target === 'enemy' ? 'hit' : 'success', this.usablePowerLabel(usable), accent);
const choose = (choicePointer: Phaser.Input.Pointer) => {
if (choicePointer.rightButtonDown()) {
@@ -4943,24 +4943,24 @@ export class BattleScene extends Phaser.Scene {
roleLabel: string,
label: string
) {
const chip = this.trackSideObject(this.add.rectangle(x, y, width, 30, 0x0b1118, 0.96));
const chip = this.trackSideObject(this.add.rectangle(x, y, width, 34, 0x0b1118, 0.96));
chip.setOrigin(0);
chip.setStrokeStyle(1, 0x647485, 0.58);
const iconFrame = this.trackSideObject(this.add.rectangle(x + 16, y + 15, 24, 24, 0x16212d, 0.92));
const iconFrame = this.trackSideObject(this.add.rectangle(x + 18, y + 17, 30, 30, 0x16212d, 0.92));
iconFrame.setStrokeStyle(1, 0x53606c, 0.55);
this.trackSideIcon(x + 16, y + 15, icon, 22);
this.trackSideObject(this.add.text(x + 33, y + 3, roleLabel, {
this.trackSideIcon(x + 18, y + 17, icon, 27);
this.trackSideObject(this.add.text(x + 38, y + 4, roleLabel, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '10px',
color: '#9fb0bf',
fontStyle: '700'
}));
this.trackSideObject(this.add.text(x + 33, y + 15, label, {
this.trackSideObject(this.add.text(x + 38, y + 17, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#d4dce6',
fontStyle: '700',
wordWrap: { width: width - 42, useAdvancedWrap: true }
wordWrap: { width: width - 48, useAdvancedWrap: true }
}));
}
@@ -4973,16 +4973,16 @@ export class BattleScene extends Phaser.Scene {
value: string,
tone = 0x647485
) {
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 36, 0x16212d, 0.94));
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 40, 0x16212d, 0.94));
bg.setOrigin(0);
bg.setStrokeStyle(1, tone, 0.62);
this.trackSideIcon(x + 16, y + 18, icon, 23);
this.trackSideObject(this.add.text(x + 33, y + 5, label, {
this.trackSideIcon(x + 18, y + 20, icon, 28);
this.trackSideObject(this.add.text(x + 38, y + 6, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#9fb0bf'
}));
const valueText = this.trackSideObject(this.add.text(x + width - 8, y + 18, value, {
const valueText = this.trackSideObject(this.add.text(x + width - 8, y + 20, value, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '17px',
color: '#f2e3bf',
@@ -4994,18 +4994,18 @@ export class BattleScene extends Phaser.Scene {
private renderPreviewForecastRow(preview: CombatPreview, x: number, y: number, width: number, accent: number) {
const projectedHp = Math.max(0, preview.defender.hp - preview.damage);
const label = preview.action === 'strategy' ? '성공 시 HP' : '명중 시 HP';
const row = this.trackSideObject(this.add.rectangle(x, y, width, 20, 0x0b1118, 0.94));
const row = this.trackSideObject(this.add.rectangle(x, y, width, 24, 0x0b1118, 0.94));
row.setOrigin(0);
row.setStrokeStyle(1, accent, 0.48);
this.trackSideIcon(x + 12, y + 10, 'hp', 17);
this.trackSideObject(this.add.text(x + 26, y + 4, label, {
this.trackSideIcon(x + 14, y + 12, 'hp', 20);
this.trackSideObject(this.add.text(x + 30, y + 6, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: '#9fb0bf',
fontStyle: '700'
}));
this.drawGauge(x + 96, y + 6, width - 170, 8, projectedHp / preview.defender.maxHp, projectedHp <= 0 ? 0xb64a45 : 0x59d18c);
const hpText = this.trackSideObject(this.add.text(x + width - 8, y + 4, `${preview.defender.hp} -> ${projectedHp}`, {
this.drawGauge(x + 102, y + 8, width - 176, 8, projectedHp / preview.defender.maxHp, projectedHp <= 0 ? 0xb64a45 : 0x59d18c);
const hpText = this.trackSideObject(this.add.text(x + width - 8, y + 6, `${preview.defender.hp} -> ${projectedHp}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: projectedHp <= 0 ? '#ff8f5f' : '#f2e3bf',
@@ -5015,11 +5015,11 @@ export class BattleScene extends Phaser.Scene {
}
private renderSupportForecastRow(preview: SupportPreview, x: number, y: number, width: number, accent: number) {
const row = this.trackSideObject(this.add.rectangle(x, y, width, 22, 0x0b1118, 0.94));
const row = this.trackSideObject(this.add.rectangle(x, y, width, 24, 0x0b1118, 0.94));
row.setOrigin(0);
row.setStrokeStyle(1, accent, 0.48);
const isHeal = preview.usable.effect === 'heal';
this.trackSideIcon(x + 12, y + 11, isHeal ? 'hp' : 'leadership', 17);
this.trackSideIcon(x + 14, y + 12, isHeal ? 'heal' : 'focus', 20);
this.trackSideObject(this.add.text(x + 26, y + 5, isHeal ? '적용 후 HP' : '강화 결과', {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
@@ -5028,8 +5028,8 @@ export class BattleScene extends Phaser.Scene {
}));
if (isHeal) {
this.drawGauge(x + 100, y + 7, width - 178, 8, preview.projectedHp / preview.target.maxHp, 0x59d18c);
const hpText = this.trackSideObject(this.add.text(x + width - 8, y + 5, `${preview.target.hp} -> ${preview.projectedHp}`, {
this.drawGauge(x + 104, y + 8, width - 182, 8, preview.projectedHp / preview.target.maxHp, 0x59d18c);
const hpText = this.trackSideObject(this.add.text(x + width - 8, y + 6, `${preview.target.hp} -> ${preview.projectedHp}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#f2e3bf',
@@ -5041,7 +5041,7 @@ export class BattleScene extends Phaser.Scene {
const buffText = this.trackSideObject(this.add.text(
x + width - 8,
y + 5,
y + 6,
`공+${preview.attackBonus} / 명+${preview.hitBonus} / 치+${preview.criticalBonus} / ${preview.duration}`,
{
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
@@ -5054,15 +5054,15 @@ export class BattleScene extends Phaser.Scene {
}
private renderPreviewBadge(x: number, y: number, icon: BattleUiIconKey, label: string, maxRight?: number) {
const width = Phaser.Math.Clamp(label.length * 8 + 42, 68, 138);
const width = Phaser.Math.Clamp(label.length * 8 + 48, 76, 146);
if (maxRight && x + width > maxRight) {
return x;
}
const badge = this.trackSideObject(this.add.rectangle(x, y, width, 23, 0x0b1118, 0.95));
const badge = this.trackSideObject(this.add.rectangle(x, y, width, 26, 0x0b1118, 0.95));
badge.setOrigin(0);
badge.setStrokeStyle(1, 0x53606c, 0.58);
this.trackSideIcon(x + 13, y + 11.5, icon, 18);
this.trackSideObject(this.add.text(x + 27, y + 5, label, {
this.trackSideIcon(x + 15, y + 13, icon, 21);
this.trackSideObject(this.add.text(x + 31, y + 6, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: '#d4dce6'
@@ -6025,21 +6025,21 @@ export class BattleScene extends Phaser.Scene {
const visibleGains = gains.filter((gain) => gain.amount > 0).slice(0, 5);
let cursorX = x;
visibleGains.forEach((gain) => {
const chipWidth = Phaser.Math.Clamp(gain.label.length * 12 + 42, 64, 92);
const chipWidth = Phaser.Math.Clamp(gain.label.length * 12 + 50, 72, 102);
if (cursorX + chipWidth > x + maxWidth) {
return;
}
const bg = this.add.rectangle(cursorX, y, chipWidth, 24, 0x0b1118, 0.9);
const bg = this.add.rectangle(cursorX, y, chipWidth, 28, 0x0b1118, 0.9);
bg.setOrigin(0);
bg.setStrokeStyle(1, 0x53606c, 0.5);
const icon = this.createBattleUiIcon(cursorX + 13, y + 12, gain.icon, 18);
const text = this.add.text(cursorX + 26, y + 5, `+${gain.amount}`, {
const icon = this.createBattleUiIcon(cursorX + 15, y + 14, gain.icon, 22);
const text = this.add.text(cursorX + 31, y + 6, `+${gain.amount}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#a8ffd0',
fontStyle: '700'
});
const label = this.add.text(cursorX + 48, y + 5, gain.label, {
const label = this.add.text(cursorX + 54, y + 6, gain.label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: '#d4dce6'
@@ -7920,21 +7920,21 @@ export class BattleScene extends Phaser.Scene {
bg.setDepth(depth);
bg.setStrokeStyle(1, accent, 0.66);
const actionFrame = this.trackCombatObject(this.add.rectangle(x + 24, y + 22, 36, 36, 0x101820, 0.9));
const actionFrame = this.trackCombatObject(this.add.rectangle(x + 25, y + 23, 42, 42, 0x101820, 0.9));
actionFrame.setDepth(depth + 1);
actionFrame.setStrokeStyle(1, accent, 0.68);
this.trackCombatIcon(x + 24, y + 22, this.actionIcon(result), 31, depth + 2);
this.trackCombatIcon(x + 25, y + 23, this.actionIcon(result), 37, depth + 2);
const attackerWeapon = getItem(result.attacker.equipment.weapon.itemId);
const defenderArmor = getItem(result.defender.equipment.armor.itemId);
const weaponFrame = this.trackCombatObject(this.add.rectangle(x + 134, y + 22, 30, 30, 0x16212d, 0.9));
const weaponFrame = this.trackCombatObject(this.add.rectangle(x + 134, y + 22, 34, 34, 0x16212d, 0.9));
weaponFrame.setDepth(depth + 1);
weaponFrame.setStrokeStyle(1, 0x647485, 0.58);
this.trackCombatIcon(x + 134, y + 22, this.itemIcon(attackerWeapon, 'weapon'), 25, depth + 2);
const armorFrame = this.trackCombatObject(this.add.rectangle(x + 244, y + 22, 30, 30, 0x16212d, 0.9));
this.trackCombatIcon(x + 134, y + 22, this.itemIcon(attackerWeapon, 'weapon'), 30, depth + 2);
const armorFrame = this.trackCombatObject(this.add.rectangle(x + 244, y + 22, 34, 34, 0x16212d, 0.9));
armorFrame.setDepth(depth + 1);
armorFrame.setStrokeStyle(1, 0x647485, 0.58);
this.trackCombatIcon(x + 244, y + 22, this.itemIcon(defenderArmor, 'armor'), 25, depth + 2);
this.trackCombatIcon(x + 244, y + 22, this.itemIcon(defenderArmor, 'armor'), 30, depth + 2);
const actionLabel = this.trackCombatObject(this.add.text(x + 46, y + 9, result.usable?.name ?? commandLabels[result.action], {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
@@ -7999,13 +7999,13 @@ export class BattleScene extends Phaser.Scene {
badge.setOrigin(0);
badge.setDepth(depth);
badge.setStrokeStyle(1, 0x53606c, 0.48);
this.trackCombatIcon(x + 12, y + 11, icon, 17, depth + 1);
const text = this.trackCombatObject(this.add.text(x + 25, y + 5, label, {
this.trackCombatIcon(x + 13, y + 11, icon, 19, depth + 1);
const text = this.trackCombatObject(this.add.text(x + 28, y + 5, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '10px',
color: '#f2e3bf',
fontStyle: '700',
fixedWidth: width - 30
fixedWidth: width - 33
}));
text.setDepth(depth + 1);
}
@@ -8130,22 +8130,22 @@ export class BattleScene extends Phaser.Scene {
bg.setDepth(depth);
bg.setStrokeStyle(1, accent, 0.66);
const actionFrame = this.trackCombatObject(this.add.rectangle(x + 24, y + 22, 36, 36, 0x101820, 0.9));
const actionFrame = this.trackCombatObject(this.add.rectangle(x + 25, y + 23, 42, 42, 0x101820, 0.9));
actionFrame.setDepth(depth + 1);
actionFrame.setStrokeStyle(1, accent, 0.68);
this.trackCombatIcon(x + 24, y + 22, this.usableIcon(result.usable), 31, depth + 2);
this.trackCombatIcon(x + 25, y + 23, this.usableIcon(result.usable), 37, depth + 2);
const sourceItem = getItem(result.usable.command === 'strategy' ? result.user.equipment.weapon.itemId : result.user.equipment.accessory.itemId);
const sourceSlot: EquipmentSlot = result.usable.command === 'strategy' ? 'weapon' : 'accessory';
const sourceFrame = this.trackCombatObject(this.add.rectangle(x + 136, y + 22, 30, 30, 0x16212d, 0.9));
const sourceFrame = this.trackCombatObject(this.add.rectangle(x + 136, y + 22, 34, 34, 0x16212d, 0.9));
sourceFrame.setDepth(depth + 1);
sourceFrame.setStrokeStyle(1, 0x647485, 0.58);
this.trackCombatIcon(x + 136, y + 22, this.itemIcon(sourceItem, sourceSlot), 25, depth + 2);
this.trackCombatIcon(x + 136, y + 22, this.itemIcon(sourceItem, sourceSlot), 30, depth + 2);
const targetFrame = this.trackCombatObject(this.add.rectangle(x + 256, y + 22, 30, 30, 0x16212d, 0.9));
const targetFrame = this.trackCombatObject(this.add.rectangle(x + 256, y + 22, 34, 34, 0x16212d, 0.9));
targetFrame.setDepth(depth + 1);
targetFrame.setStrokeStyle(1, 0x647485, 0.58);
this.trackCombatIcon(x + 256, y + 22, result.usable.effect === 'heal' ? 'hp' : 'leadership', 25, depth + 2);
this.trackCombatIcon(x + 256, y + 22, result.usable.effect === 'heal' ? 'heal' : 'focus', 30, depth + 2);
const actionLabel = this.trackCombatObject(this.add.text(x + 46, y + 9, result.usable.name, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
@@ -8573,8 +8573,8 @@ export class BattleScene extends Phaser.Scene {
}
private renderGrowthGaugeRow(entry: GrowthGaugeEntry, x: number, y: number, width: number, depth: number): GrowthGaugeView {
this.trackCombatIcon(x + 8, y + 8, this.growthEntryIcon(entry), 16, depth);
const label = this.trackCombatObject(this.add.text(x + 22, y - 3, `${entry.owner} ${entry.label}`, {
this.trackCombatIcon(x + 10, y + 8, this.growthEntryIcon(entry), 20, depth);
const label = this.trackCombatObject(this.add.text(x + 28, y - 3, `${entry.owner} ${entry.label}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '13px',
color: '#d4dce6',
@@ -11116,9 +11116,9 @@ export class BattleScene extends Phaser.Scene {
header.setOrigin(0);
header.setStrokeStyle(1, factionColor, 0.76);
const classIcon = this.trackSideIcon(left + 23, top + 31, this.unitMoveIcon(unit), 30);
const classIcon = this.trackSideIcon(left + 26, top + 31, this.unitMoveIcon(unit), 38);
classIcon.setAlpha(acted ? 0.86 : 0.96);
const headerTextX = left + 48;
const headerTextX = left + 58;
this.trackSideObject(this.add.text(headerTextX, top + 9, `${rosterLabels[unit.faction]} / ${unitClass.family}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '14px',
@@ -11155,7 +11155,7 @@ export class BattleScene extends Phaser.Scene {
backText.setOrigin(0.5);
}
this.trackSideIcon(left + 10, top + 88, 'hp', 20);
this.trackSideIcon(left + 13, top + 88, 'hp', 26);
this.trackSideObject(this.add.text(left + 26, top + 78, '병력', {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '17px',
@@ -11169,7 +11169,7 @@ export class BattleScene extends Phaser.Scene {
fontStyle: '700'
}));
hpValue.setOrigin(1, 0);
this.drawGauge(left + 92, top + 84, width - 176, 10, unit.hp / unit.maxHp, 0x59d18c);
this.drawGauge(left + 102, top + 84, width - 186, 10, unit.hp / unit.maxHp, 0x59d18c);
const attackBonus = this.equipmentAttackBonus(unit);
const summaryGap = 6;
@@ -11191,23 +11191,23 @@ export class BattleScene extends Phaser.Scene {
});
const positionText = `위치 ${unit.x + 1}, ${unit.y + 1} / ${terrainRule.label} ${terrainRating}% / 이동 ${unit.move}${acted ? ' / 행동완료' : ''}`;
this.trackSideIcon(left + 11, top + 315, acted ? 'counter' : this.unitMoveIcon(unit), 20);
this.trackSideObject(this.add.text(left + 28, top + 306, positionText, {
this.trackSideIcon(left + 13, top + 294, acted ? 'counter' : this.unitMoveIcon(unit), 24);
this.trackSideObject(this.add.text(left + 28, top + 285, positionText, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '14px',
color: acted ? '#bdbdbd' : '#9fb0bf',
wordWrap: { width: width - 24, useAdvancedWrap: true }
}));
this.renderEquipmentSummary(unit, left, top + 334, width);
this.renderEquipmentSummary(unit, left, top + 308, width);
if (message) {
this.renderPanelMessage(message, left, top + 472, width, 48);
this.renderPanelMessage(message, left, top + 474, width, 40);
}
this.showFacingIndicator(unit);
}
private renderEquipmentSummary(unit: UnitData, x: number, y: number, width: number) {
this.trackSideIcon(x + 11, y + 11, 'mastery', 22);
this.trackSideIcon(x + 14, y + 11, 'mastery', 26);
this.trackSideObject(this.add.text(x + 31, y, '장비 / 숙련도', {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '16px',
@@ -11216,7 +11216,7 @@ export class BattleScene extends Phaser.Scene {
}));
equipmentSlots.forEach((slot, index) => {
this.renderEquipmentRow(unit, slot, x, y + 26 + index * 33, width);
this.renderEquipmentRow(unit, slot, x, y + 26 + index * 37, width);
});
}
@@ -11225,22 +11225,22 @@ export class BattleScene extends Phaser.Scene {
const item = getItem(state.itemId);
const next = equipmentExpToNext(state.level);
const isTreasure = item.rank === 'treasure';
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 32, isTreasure ? 0x1f2430 : 0x101820, isTreasure ? 0.97 : 0.94));
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 36, isTreasure ? 0x1f2430 : 0x101820, isTreasure ? 0.97 : 0.94));
bg.setOrigin(0);
bg.setStrokeStyle(1, isTreasure ? palette.gold : 0x53606c, isTreasure ? 0.66 : 0.5);
const iconFrame = this.trackSideObject(this.add.rectangle(x + 17, y + 16, 26, 26, 0x0a0f14, 0.86));
const iconFrame = this.trackSideObject(this.add.rectangle(x + 20, y + 18, 32, 32, 0x0a0f14, 0.86));
iconFrame.setStrokeStyle(1, isTreasure ? palette.gold : 0x53606c, isTreasure ? 0.78 : 0.54);
this.trackSideIcon(x + 17, y + 16, this.itemIcon(item, slot), 24);
this.trackSideIcon(x + 20, y + 18, this.itemIcon(item, slot), 29);
this.trackSideObject(this.add.text(x + 38, y + 5, equipmentSlotLabels[slot], {
this.trackSideObject(this.add.text(x + 44, y + 3, equipmentSlotLabels[slot], {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#9fb0bf',
fontStyle: '700'
}));
this.trackSideObject(this.add.text(x + 84, y + 5, item.name, {
this.trackSideObject(this.add.text(x + 88, y + 3, item.name, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '14px',
color: isTreasure ? '#f4dfad' : '#d4dce6',
@@ -11248,21 +11248,21 @@ export class BattleScene extends Phaser.Scene {
}));
const bonusText = this.itemBonusText(item);
this.trackSideObject(this.add.text(x + width - 130, y + 8, bonusText, {
this.trackSideObject(this.add.text(x + width - 126, y + 6, bonusText, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: '#9fb0bf'
}));
this.trackSideIcon(x + width - 73, y + 16, 'mastery', 17);
const expText = this.trackSideObject(this.add.text(x + width - 56, y + 7, `${state.exp}/${next}`, {
this.trackSideIcon(x + width - 78, y + 18, 'mastery', 18);
const expText = this.trackSideObject(this.add.text(x + width - 58, y + 9, `${state.exp}/${next}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
color: '#9fb0bf'
}));
expText.setOrigin(1, 0);
const levelText = this.trackSideObject(this.add.text(x + width - 8, y + 4, `Lv ${state.level}`, {
const levelText = this.trackSideObject(this.add.text(x + width - 8, y + 6, `Lv ${state.level}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '14px',
color: isTreasure ? '#f2e3bf' : '#d4dce6',
@@ -11270,7 +11270,7 @@ export class BattleScene extends Phaser.Scene {
}));
levelText.setOrigin(1, 0);
this.drawGauge(x + 84, y + 25, width - 194, 5, state.exp / next, isTreasure ? 0xd8b15f : 0x58aee0);
this.drawGauge(x + 88, y + 27, width - 198, 5, state.exp / next, isTreasure ? 0xd8b15f : 0x58aee0);
}
private createBattleUiIcon(x: number, y: number, icon: BattleUiIconKey, size = 22) {
@@ -11349,16 +11349,19 @@ export class BattleScene extends Phaser.Scene {
private usableIcon(usable: BattleUsable): BattleUiIconKey {
if (usable.command === 'item') {
return usable.effect === 'heal' ? 'hp' : 'accessory';
return usable.effect === 'heal' ? 'heal' : 'accessory';
}
if (usable.effect === 'heal') {
return 'hp';
return 'heal';
}
if (usable.effect === 'focus') {
return 'leadership';
return 'focus';
}
if (usable.id === 'fireTactic') {
return 'fire';
}
if (usable.id.toLowerCase().includes('roar')) {
return 'might';
return 'shout';
}
return 'strategy';
}
@@ -11407,18 +11410,18 @@ export class BattleScene extends Phaser.Scene {
}
private renderCompactValueBox(x: number, y: number, width: number, icon: BattleUiIconKey, label: string, value: string) {
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 42, 0x16212d, 0.97));
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 46, 0x16212d, 0.97));
bg.setOrigin(0);
bg.setStrokeStyle(1, 0x647485, 0.72);
const iconFrame = this.trackSideObject(this.add.rectangle(x + 15, y + 21, 26, 26, 0x0a0f14, 0.82));
const iconFrame = this.trackSideObject(this.add.rectangle(x + 18, y + 23, 32, 32, 0x0a0f14, 0.82));
iconFrame.setStrokeStyle(1, 0x53606c, 0.52);
this.trackSideIcon(x + 15, y + 21, icon, 23);
this.trackSideObject(this.add.text(x + 31, y + 7, label, {
this.trackSideIcon(x + 18, y + 23, icon, 29);
this.trackSideObject(this.add.text(x + 38, y + 7, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: '#9fb0bf'
}));
const valueText = this.trackSideObject(this.add.text(x + width - 8, y + 23, value, {
const valueText = this.trackSideObject(this.add.text(x + width - 8, y + 25, value, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '15px',
color: '#f2e3bf',
@@ -11428,15 +11431,15 @@ export class BattleScene extends Phaser.Scene {
}
private renderStatRow(key: keyof UnitStats, label: string, value: number, x: number, y: number, width: number) {
this.trackSideIcon(x + 11, y + 10, this.statIcon(key), 22);
this.trackSideObject(this.add.text(x + 30, y, label, {
this.trackSideIcon(x + 13, y + 10, this.statIcon(key), 26);
this.trackSideObject(this.add.text(x + 36, y, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '16px',
color: '#d4dce6',
fontStyle: '700'
}));
this.drawGauge(x + 96, y + 8, width - 150, 10, value / 100, value >= 80 ? 0xd8b15f : 0x58aee0);
this.drawGauge(x + 104, y + 8, width - 158, 10, value / 100, value >= 80 ? 0xd8b15f : 0x58aee0);
const valueText = this.trackSideObject(this.add.text(x + width, y - 1, `${value}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',