Rework combat preview readability

This commit is contained in:
2026-07-03 17:21:57 +09:00
parent 907e8e6275
commit ea6acefe7b
5 changed files with 77 additions and 53 deletions

View File

@@ -6301,12 +6301,12 @@ export class BattleScene extends Phaser.Scene {
private equipmentPreviewBonusText(preview: CombatPreview) {
const parts = [
preview.equipmentDamageBonus > 0 ? `피해 +${preview.equipmentDamageBonus}%` : '',
preview.equipmentDamageReduction > 0 ? `피해 -${preview.equipmentDamageReduction}%` : '',
preview.equipmentHitBonus > 0 ? `명중 +${preview.equipmentHitBonus}` : '',
preview.equipmentCriticalBonus > 0 ? `치명 +${preview.equipmentCriticalBonus}` : ''
preview.equipmentDamageBonus > 0 ? `피해+${preview.equipmentDamageBonus}%` : '',
preview.equipmentDamageReduction > 0 ? `감소-${preview.equipmentDamageReduction}%` : '',
preview.equipmentHitBonus > 0 ? `명중+${preview.equipmentHitBonus}` : '',
preview.equipmentCriticalBonus > 0 ? `치명+${preview.equipmentCriticalBonus}` : ''
].filter(Boolean);
return parts.join(' / ') || '보정 없음';
return parts.join(' ') || '보정 없음';
}
private battleBuffShortText(buff: BattleBuffState) {
@@ -6466,7 +6466,7 @@ export class BattleScene extends Phaser.Scene {
const { panelX, panelWidth } = this.layout;
const left = panelX + 24;
const width = panelWidth - 48;
const height = locked ? 438 : 402;
const height = locked ? 464 : 430;
const y = this.sideContentTop();
const accent = this.previewAccentColor(preview);
const distance = this.tileDistance(preview.attacker, preview.defender);
@@ -6484,34 +6484,34 @@ export class BattleScene extends Phaser.Scene {
bg.setOrigin(0);
bg.setStrokeStyle(2, accent, locked ? 0.95 : 0.78);
const actionFrame = this.trackSideObject(this.add.rectangle(left + 42, y + 42, 74, 74, 0x0a0f14, 0.95));
const actionFrame = this.trackSideObject(this.add.rectangle(left + 46, y + 46, 84, 84, 0x0a0f14, 0.96));
actionFrame.setStrokeStyle(1, accent, 0.82);
this.trackSideIcon(left + 42, y + 42, this.actionIcon(preview), 66);
this.trackSideIcon(left + 46, y + 46, this.actionIcon(preview), 70);
this.trackSideObject(this.add.text(left + 88, y + 9, `${preview.attacker.name}${preview.defender.name}`, {
this.trackSideObject(this.add.text(left + 98, y + 10, `${preview.attacker.name}${preview.defender.name}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '20px',
color: '#f4dfad',
fontStyle: '700',
fixedWidth: width - 98
fixedWidth: width - 108
}));
this.trackSideObject(this.add.text(left + 88, y + 37, `${this.previewActionLabel(preview)} · ${this.previewActionTypeLabel(preview)}`, {
this.trackSideObject(this.add.text(left + 98, y + 39, `${this.previewActionLabel(preview)} · ${this.previewActionTypeLabel(preview)}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '13px',
color: '#d4dce6',
fontStyle: '700',
fixedWidth: width - 98
fixedWidth: width - 108
}));
this.trackSideObject(this.add.text(left + 88, y + 57, `거리 ${distance}/${range} · ${locked ? '선택됨' : '대상 후보'}`, {
this.trackSideObject(this.add.text(left + 98, y + 61, `거리 ${distance}/${range} · ${locked ? '선택됨' : '대상 후보'}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: locked ? '#f2e3bf' : '#9fb0bf',
fixedWidth: width - 98
fixedWidth: width - 108
}));
const metricGap = 6;
const metricWidth = (width - 20 - metricGap * 2) / 3;
const metricTop = y + 90;
const metricTop = y + 96;
this.renderPreviewDecisionCard(left + 10, metricTop, metricWidth, this.previewDamageIcon(preview), isStrategy ? '책략 피해' : '예상 피해', `${preview.damage}`, 0xb64a45);
this.renderPreviewDecisionCard(
left + 10 + metricWidth + metricGap,
@@ -6534,13 +6534,13 @@ export class BattleScene extends Phaser.Scene {
const chipGap = 8;
const chipWidth = (width - 20 - chipGap) / 2;
this.renderPreviewEquipmentChip(left + 10, y + 184, chipWidth, sourceIcon, sourceLabel, sourceName);
this.renderPreviewEquipmentChip(left + 10 + chipWidth + chipGap, y + 184, chipWidth, this.itemIcon(defenderArmor, 'armor'), defenseLabel, defenderArmor.name);
this.renderPreviewEquipmentChip(left + 10, y + 214, chipWidth, sourceIcon, sourceLabel, sourceName);
this.renderPreviewEquipmentChip(left + 10 + chipWidth + chipGap, y + 214, chipWidth, this.itemIcon(defenderArmor, 'armor'), defenseLabel, defenderArmor.name);
this.renderPreviewForecastRow(preview, left + 10, y + 238, width - 20, accent);
this.renderPreviewModifierCards(left + 10, y + 278, width - 20, this.previewModifierSummaries(preview), accent);
this.renderPreviewForecastRow(preview, left + 10, y + 272, width - 20, accent);
this.renderPreviewModifierCards(left + 10, y + 312, width - 20, this.previewModifierSummaries(preview), accent);
const badgeY = y + 346;
const badgeY = y + 382;
const maxBadgeRight = left + width - 10;
let badgeX = left + 10;
if (isStrategy) {
@@ -6556,7 +6556,7 @@ export class BattleScene extends Phaser.Scene {
this.renderPreviewBadge(detailBadgeX, badgeY, 'mastery', '장비 보정', maxBadgeRight);
}
if (locked) {
this.renderPreviewConfirmBar(left + 10, y + 402, width - 20, accent, `${preview.defender.name} 선택됨`);
this.renderPreviewConfirmBar(left + 10, y + 426, width - 20, accent, `${preview.defender.name} 선택됨`);
}
}
@@ -6564,7 +6564,7 @@ export class BattleScene extends Phaser.Scene {
const { panelX, panelWidth } = this.layout;
const left = panelX + 24;
const width = panelWidth - 48;
const height = locked ? 438 : 402;
const height = locked ? 464 : 430;
const y = this.sideContentTop();
const accent = this.usableAccentColor(preview.usable);
const isHeal = preview.usable.effect === 'heal';
@@ -6574,34 +6574,34 @@ export class BattleScene extends Phaser.Scene {
bg.setOrigin(0);
bg.setStrokeStyle(2, accent, locked ? 0.95 : 0.78);
const actionFrame = this.trackSideObject(this.add.rectangle(left + 42, y + 42, 74, 74, 0x0a0f14, 0.95));
const actionFrame = this.trackSideObject(this.add.rectangle(left + 46, y + 46, 84, 84, 0x0a0f14, 0.96));
actionFrame.setStrokeStyle(1, accent, 0.82);
this.trackSideIcon(left + 42, y + 42, this.usableIcon(preview.usable), 66);
this.trackSideIcon(left + 46, y + 46, this.usableIcon(preview.usable), 70);
this.trackSideObject(this.add.text(left + 88, y + 9, `${preview.user.name}${preview.target.name}`, {
this.trackSideObject(this.add.text(left + 98, y + 10, `${preview.user.name}${preview.target.name}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '20px',
color: '#f4dfad',
fontStyle: '700',
fixedWidth: width - 98
fixedWidth: width - 108
}));
this.trackSideObject(this.add.text(left + 88, y + 37, `${preview.usable.name} · ${this.usableEffectLabel(preview.usable)}`, {
this.trackSideObject(this.add.text(left + 98, y + 39, `${preview.usable.name} · ${this.usableEffectLabel(preview.usable)}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '13px',
color: '#d4dce6',
fontStyle: '700',
fixedWidth: width - 98
fixedWidth: width - 108
}));
this.trackSideObject(this.add.text(left + 88, y + 57, `거리 ${distance}/${preview.usable.range} · ${locked ? '선택됨' : '대상 후보'}`, {
this.trackSideObject(this.add.text(left + 98, y + 61, `거리 ${distance}/${preview.usable.range} · ${locked ? '선택됨' : '대상 후보'}`, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '12px',
color: locked ? '#f2e3bf' : '#9fb0bf',
fixedWidth: width - 98
fixedWidth: width - 108
}));
const metricGap = 6;
const metricWidth = (width - 20 - metricGap * 2) / 3;
const metricTop = y + 90;
const metricTop = y + 96;
if (isHeal) {
this.renderPreviewDecisionCard(left + 10, metricTop, metricWidth, this.usablePowerIcon(preview.usable), '회복', `+${preview.healAmount}`, 0x59d18c);
this.renderPreviewDecisionCard(left + 10 + metricWidth + metricGap, metricTop, metricWidth, 'success', '적용', '100%', accent);
@@ -6616,7 +6616,7 @@ export class BattleScene extends Phaser.Scene {
const chipWidth = (width - 20 - chipGap) / 2;
this.renderPreviewEquipmentChip(
left + 10,
y + 184,
y + 214,
chipWidth,
this.usableIcon(preview.usable),
this.usableChannelLabel(preview.usable),
@@ -6624,17 +6624,17 @@ export class BattleScene extends Phaser.Scene {
);
this.renderPreviewEquipmentChip(
left + 10 + chipWidth + chipGap,
y + 184,
y + 214,
chipWidth,
this.usableTargetIcon(preview.usable),
this.usableTargetLabel(preview.usable),
preview.target.name
);
this.renderSupportForecastRow(preview, left + 10, y + 238, width - 20, accent);
this.renderPreviewModifierCards(left + 10, y + 278, width - 20, this.supportPreviewModifierSummaries(preview), accent);
this.renderSupportForecastRow(preview, left + 10, y + 272, width - 20, accent);
this.renderPreviewModifierCards(left + 10, y + 312, width - 20, this.supportPreviewModifierSummaries(preview), accent);
const badgeY = y + 346;
const badgeY = y + 382;
const maxBadgeRight = left + width - 10;
let badgeX = left + 10;
badgeX = this.renderPreviewBadge(badgeX, badgeY, this.usableIcon(preview.usable), this.usableEffectLabel(preview.usable), maxBadgeRight);
@@ -6644,7 +6644,7 @@ export class BattleScene extends Phaser.Scene {
detailBadgeX = this.renderPreviewBadge(detailBadgeX, badgeY, 'critical', `치명 +${preview.criticalBonus}`, maxBadgeRight);
}
if (locked) {
this.renderPreviewConfirmBar(left + 10, y + 402, width - 20, accent, `${preview.target.name} 선택됨`);
this.renderPreviewConfirmBar(left + 10, y + 426, width - 20, accent, `${preview.target.name} 선택됨`);
}
}
@@ -6657,17 +6657,17 @@ export class BattleScene extends Phaser.Scene {
value: string,
tone: number
) {
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 84, 0x16212d, 0.97));
const bg = this.trackSideObject(this.add.rectangle(x, y, width, 104, 0x16212d, 0.98));
bg.setOrigin(0);
bg.setStrokeStyle(1, tone, 0.72);
bg.setStrokeStyle(1, tone, 0.82);
const iconFrame = this.trackSideObject(this.add.rectangle(x + width / 2, y + 25, 44, 44, 0x0a0f14, 0.92));
iconFrame.setStrokeStyle(1, tone, 0.58);
this.trackSideIcon(x + width / 2, y + 25, icon, 40);
const iconFrame = this.trackSideObject(this.add.rectangle(x + width / 2, y + 34, 60, 60, 0x0a0f14, 0.94));
iconFrame.setStrokeStyle(1, tone, 0.66);
this.trackSideIcon(x + width / 2, y + 34, icon, 54);
const labelText = this.trackSideObject(this.add.text(x + width / 2, y + 47, label, {
const labelText = this.trackSideObject(this.add.text(x + width / 2, y + 66, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '11px',
fontSize: '12px',
color: '#9fb0bf',
fontStyle: '700',
fixedWidth: width - 8,
@@ -6676,9 +6676,9 @@ export class BattleScene extends Phaser.Scene {
labelText.setOrigin(0.5, 0);
const valueHasKorean = /[가-힣]/.test(value);
const valueText = this.trackSideObject(this.add.text(x + width / 2, y + 62, value, {
const valueText = this.trackSideObject(this.add.text(x + width / 2, y + 82, value, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: valueHasKorean || value.length > 4 ? '17px' : '22px',
fontSize: valueHasKorean || value.length > 4 ? '18px' : '26px',
color: '#f2e3bf',
fontStyle: '700',
fixedWidth: width - 8,
@@ -6724,7 +6724,7 @@ export class BattleScene extends Phaser.Scene {
}
const gap = 6;
const cardWidth = (width - gap * 2) / 3;
const cardWidth = (width - gap * (visible.length - 1)) / visible.length;
visible.forEach((summary, index) => {
const cardX = x + index * (cardWidth + gap);
const card = this.trackSideObject(this.add.rectangle(cardX, y, cardWidth, 58, 0x0b1118, 0.96));
@@ -6821,24 +6821,24 @@ export class BattleScene extends Phaser.Scene {
roleLabel: string,
label: string
) {
const chip = this.trackSideObject(this.add.rectangle(x, y, width, 52, 0x0b1118, 0.97));
const chip = this.trackSideObject(this.add.rectangle(x, y, width, 52, 0x0b1118, 0.98));
chip.setOrigin(0);
chip.setStrokeStyle(1, 0x647485, 0.62);
const iconFrame = this.trackSideObject(this.add.rectangle(x + 27, y + 26, 46, 46, 0x16212d, 0.93));
const iconFrame = this.trackSideObject(this.add.rectangle(x + 29, y + 26, 50, 50, 0x16212d, 0.94));
iconFrame.setStrokeStyle(1, 0x53606c, 0.55);
this.trackSideIcon(x + 27, y + 26, icon, 42);
this.trackSideObject(this.add.text(x + 58, y + 6, roleLabel, {
this.trackSideIcon(x + 29, y + 26, icon, 46);
this.trackSideObject(this.add.text(x + 62, y + 6, roleLabel, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '10px',
color: '#9fb0bf',
fontStyle: '700'
}));
this.trackSideObject(this.add.text(x + 58, y + 24, label, {
this.trackSideObject(this.add.text(x + 62, y + 24, label, {
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
fontSize: '13px',
color: '#d4dce6',
fontStyle: '700',
fixedWidth: width - 66
fixedWidth: width - 70
}));
}