249 行
8.8 KiB
TypeScript
249 行
8.8 KiB
TypeScript
|
|
import { _decorator, Component, Node, Label, Sprite, Color, UITransform, Size, Layout, ScrollView } from 'cc';
|
|||
|
|
import { UITheme } from '../common/UITheme';
|
|||
|
|
import { UIBase } from '../common/UIBase';
|
|||
|
|
|
|||
|
|
const { ccclass, property } = _decorator;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 战斗界面
|
|||
|
|
* 基于江湖截图:ATB即时制战斗 + 文字战报
|
|||
|
|
* 顶部:战斗目标 + 血条
|
|||
|
|
* 中部:双方角色展示
|
|||
|
|
* 底部:战报日志 + 结束战斗按钮
|
|||
|
|
*/
|
|||
|
|
@ccclass('CombatScreen')
|
|||
|
|
export class CombatScreen extends UIBase {
|
|||
|
|
|
|||
|
|
@property(Node) combatHeader: Node = null!;
|
|||
|
|
@property(Node) characterDisplay: Node = null!;
|
|||
|
|
@property(Node) battleLog: Node = null!;
|
|||
|
|
@property(Node) combatFooter: Node = null!;
|
|||
|
|
|
|||
|
|
start() {
|
|||
|
|
this.initCombatHeader();
|
|||
|
|
this.initCharacterDisplay();
|
|||
|
|
this.initBattleLog();
|
|||
|
|
this.initCombatFooter();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 战斗头部
|
|||
|
|
* 正在讨伐 + 目标名称 + 目标血条
|
|||
|
|
*/
|
|||
|
|
private initCombatHeader() {
|
|||
|
|
if (!this.combatHeader) return;
|
|||
|
|
|
|||
|
|
const transform = this.combatHeader.getComponent(UITransform) || this.combatHeader.addComponent(UITransform);
|
|||
|
|
transform.setContentSize(new Size(720, 120));
|
|||
|
|
|
|||
|
|
// 讨伐提示
|
|||
|
|
const tipNode = new Node('Tip');
|
|||
|
|
const tipLabel = tipNode.addComponent(Label);
|
|||
|
|
tipLabel.string = '正在讨伐';
|
|||
|
|
tipLabel.fontSize = UITheme.FONT_SIZE.MD;
|
|||
|
|
tipLabel.color = this.hexToColor(UITheme.COLORS.TEXT_NORMAL);
|
|||
|
|
tipNode.setParent(this.combatHeader);
|
|||
|
|
|
|||
|
|
// 目标名称
|
|||
|
|
const targetNode = new Node('Target');
|
|||
|
|
const targetLabel = targetNode.addComponent(Label);
|
|||
|
|
targetLabel.string = '胡威';
|
|||
|
|
targetLabel.fontSize = UITheme.FONT_SIZE.LG;
|
|||
|
|
targetLabel.color = this.hexToColor(UITheme.COLORS.TEXT_RED);
|
|||
|
|
targetNode.setParent(this.combatHeader);
|
|||
|
|
|
|||
|
|
// 目标血条
|
|||
|
|
const hpBar = this.createBar(this.combatHeader, {
|
|||
|
|
width: 500, height: 20,
|
|||
|
|
fillColor: UITheme.COLORS.HP_BAR,
|
|||
|
|
bgColor: UITheme.COLORS.HP_BAR_BG,
|
|||
|
|
value: 85,
|
|||
|
|
maxValue: 100,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 剩余血量
|
|||
|
|
const hpLabel = new Node('HP');
|
|||
|
|
const hp = hpLabel.addComponent(Label);
|
|||
|
|
hp.string = 'x997';
|
|||
|
|
hp.fontSize = UITheme.FONT_SIZE.SM;
|
|||
|
|
hp.color = this.hexToColor(UITheme.COLORS.TEXT_RED);
|
|||
|
|
hpLabel.setParent(this.combatHeader);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 角色展示区
|
|||
|
|
* 己方角色 + 敌方角色
|
|||
|
|
*/
|
|||
|
|
private initCharacterDisplay() {
|
|||
|
|
if (!this.characterDisplay) return;
|
|||
|
|
|
|||
|
|
const transform = this.characterDisplay.getComponent(UITransform) || this.characterDisplay.addComponent(UITransform);
|
|||
|
|
transform.setContentSize(new Size(720, 300));
|
|||
|
|
|
|||
|
|
// 己方角色
|
|||
|
|
const playerNode = new Node('Player');
|
|||
|
|
const playerTransform = playerNode.addComponent(UITransform);
|
|||
|
|
playerTransform.setContentSize(new Size(200, 280));
|
|||
|
|
playerNode.setParent(this.characterDisplay);
|
|||
|
|
|
|||
|
|
// 己方头像
|
|||
|
|
const playerAvatar = new Node('Avatar');
|
|||
|
|
const playerAvatarLabel = playerAvatar.addComponent(Label);
|
|||
|
|
playerAvatarLabel.string = '🧙';
|
|||
|
|
playerAvatarLabel.fontSize = 80;
|
|||
|
|
playerAvatar.setParent(playerNode);
|
|||
|
|
|
|||
|
|
// 己方名称
|
|||
|
|
const playerName = new Node('Name');
|
|||
|
|
const playerNameLabel = playerName.addComponent(Label);
|
|||
|
|
playerNameLabel.string = '角色名';
|
|||
|
|
playerNameLabel.fontSize = UITheme.FONT_SIZE.SM;
|
|||
|
|
playerNameLabel.color = this.hexToColor(UITheme.COLORS.TEXT_GREEN);
|
|||
|
|
playerName.setParent(playerNode);
|
|||
|
|
|
|||
|
|
// 己方血条
|
|||
|
|
const playerHp = this.createBar(playerNode, {
|
|||
|
|
width: 180, height: 16,
|
|||
|
|
fillColor: UITheme.COLORS.HP_BAR,
|
|||
|
|
bgColor: UITheme.COLORS.HP_BAR_BG,
|
|||
|
|
value: 70,
|
|||
|
|
maxValue: 100,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 敌方角色
|
|||
|
|
const enemyNode = new Node('Enemy');
|
|||
|
|
const enemyTransform = enemyNode.addComponent(UITransform);
|
|||
|
|
enemyTransform.setContentSize(new Size(200, 280));
|
|||
|
|
enemyNode.setParent(this.characterDisplay);
|
|||
|
|
|
|||
|
|
// 敌方头像
|
|||
|
|
const enemyAvatar = new Node('Avatar');
|
|||
|
|
const enemyAvatarLabel = enemyAvatar.addComponent(Label);
|
|||
|
|
enemyAvatarLabel.string = '👹';
|
|||
|
|
enemyAvatarLabel.fontSize = 80;
|
|||
|
|
enemyAvatar.setParent(enemyNode);
|
|||
|
|
|
|||
|
|
// 敌方名称
|
|||
|
|
const enemyName = new Node('Name');
|
|||
|
|
const enemyNameLabel = enemyName.addComponent(Label);
|
|||
|
|
enemyNameLabel.string = '胡威';
|
|||
|
|
enemyNameLabel.fontSize = UITheme.FONT_SIZE.SM;
|
|||
|
|
enemyNameLabel.color = this.hexToColor(UITheme.COLORS.TEXT_RED);
|
|||
|
|
enemyName.setParent(enemyNode);
|
|||
|
|
|
|||
|
|
// 敌方血条
|
|||
|
|
const enemyHp = this.createBar(enemyNode, {
|
|||
|
|
width: 180, height: 16,
|
|||
|
|
fillColor: UITheme.COLORS.HP_BAR,
|
|||
|
|
bgColor: UITheme.COLORS.HP_BAR_BG,
|
|||
|
|
value: 85,
|
|||
|
|
maxValue: 100,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 战斗技能展示
|
|||
|
|
const skillNode = new Node('Skill');
|
|||
|
|
const skillLabel = skillNode.addComponent(Label);
|
|||
|
|
skillLabel.string = '蛟龙游离剑';
|
|||
|
|
skillLabel.fontSize = UITheme.FONT_SIZE.MD;
|
|||
|
|
skillLabel.color = this.hexToColor(UITheme.COLORS.TEXT_BLUE);
|
|||
|
|
skillNode.setParent(this.characterDisplay);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 战报日志区
|
|||
|
|
* 滚动文本区域,显示战斗过程
|
|||
|
|
*/
|
|||
|
|
private initBattleLog() {
|
|||
|
|
if (!this.battleLog) return;
|
|||
|
|
|
|||
|
|
const transform = this.battleLog.getComponent(UITransform) || this.battleLog.addComponent(UITransform);
|
|||
|
|
transform.setContentSize(new Size(720, 400));
|
|||
|
|
|
|||
|
|
// 战报内容
|
|||
|
|
const logContent = new Node('LogContent');
|
|||
|
|
const logLabel = logContent.addComponent(Label);
|
|||
|
|
logLabel.string = `【第1回合】
|
|||
|
|
你稍作运功舞出伐喃狂舞剑,顷刻间身形仿佛消失在风沙之中,接着白光一闪,未等胡威反应,已被打掉了312057点气血。
|
|||
|
|
你使出这招伐喃狂舞剑后,步伐更加灵活,在接下来的2回合内闪避和识破获得了提升!
|
|||
|
|
胡威身上的多处伤口造成了51953点气血损伤。
|
|||
|
|
|
|||
|
|
【第2回合】
|
|||
|
|
你不紧不慢的使出蛟龙游离剑,身似蛟龙般闪过,胡威来不及反应损失了155730点气血。
|
|||
|
|
你使出这招蛟龙游离剑后越战越勇,剑法威力在接下来的三回合内显著增加。`;
|
|||
|
|
logLabel.fontSize = UITheme.FONT_SIZE.SM;
|
|||
|
|
logLabel.color = this.hexToColor(UITheme.COLORS.TEXT_NORMAL);
|
|||
|
|
logLabel.overflow = Label.Overflow.CLAMP;
|
|||
|
|
logLabel.lineHeight = 28;
|
|||
|
|
logContent.setParent(this.battleLog);
|
|||
|
|
|
|||
|
|
// 战斗事件高亮
|
|||
|
|
const eventNode = new Node('Event');
|
|||
|
|
const eventLabel = eventNode.addComponent(Label);
|
|||
|
|
eventLabel.string = '【第4回合】';
|
|||
|
|
eventLabel.fontSize = UITheme.FONT_SIZE.MD;
|
|||
|
|
eventLabel.color = this.hexToColor(UITheme.COLORS.TEXT_GOLD);
|
|||
|
|
eventNode.setParent(this.battleLog);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 战斗底部
|
|||
|
|
* 结束战斗按钮
|
|||
|
|
*/
|
|||
|
|
private initCombatFooter() {
|
|||
|
|
if (!this.combatFooter) return;
|
|||
|
|
|
|||
|
|
const transform = this.combatFooter.getComponent(UITransform) || this.combatFooter.addComponent(UITransform);
|
|||
|
|
transform.setContentSize(new Size(720, 80));
|
|||
|
|
|
|||
|
|
const endBtn = this.createButton(this.combatFooter, '结束战斗', {
|
|||
|
|
width: 200, height: 50,
|
|||
|
|
bgColor: UITheme.COLORS.BG_CARD,
|
|||
|
|
textColor: UITheme.COLORS.TEXT_GOLD,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 添加战斗日志条目
|
|||
|
|
*/
|
|||
|
|
addLogEntry(text: string, type: 'normal' | 'damage' | 'heal' | 'skill' | 'event' = 'normal') {
|
|||
|
|
if (!this.battleLog) return;
|
|||
|
|
|
|||
|
|
const colorMap = {
|
|||
|
|
normal: UITheme.COLORS.TEXT_NORMAL,
|
|||
|
|
damage: UITheme.COLORS.TEXT_RED,
|
|||
|
|
heal: UITheme.COLORS.TEXT_GREEN,
|
|||
|
|
skill: UITheme.COLORS.TEXT_BLUE,
|
|||
|
|
event: UITheme.COLORS.TEXT_GOLD,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const entryNode = new Node('LogEntry');
|
|||
|
|
const label = entryNode.addComponent(Label);
|
|||
|
|
label.string = text;
|
|||
|
|
label.fontSize = UITheme.FONT_SIZE.SM;
|
|||
|
|
label.color = this.hexToColor(colorMap[type]);
|
|||
|
|
label.lineHeight = 28;
|
|||
|
|
entryNode.setParent(this.battleLog);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新敌方血条
|
|||
|
|
*/
|
|||
|
|
updateEnemyHP(current: number, max: number) {
|
|||
|
|
// 实现血条动画更新
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 显示伤害数字
|
|||
|
|
*/
|
|||
|
|
showDamageNumber(value: number, isCrit: boolean = false) {
|
|||
|
|
const node = new Node('Damage');
|
|||
|
|
const label = node.addComponent(Label);
|
|||
|
|
label.string = `-${value}`;
|
|||
|
|
label.fontSize = isCrit ? UITheme.FONT_SIZE.XL : UITheme.FONT_SIZE.LG;
|
|||
|
|
label.color = isCrit
|
|||
|
|
? this.hexToColor(UITheme.COLORS.TEXT_ORANGE)
|
|||
|
|
: this.hexToColor(UITheme.COLORS.TEXT_RED);
|
|||
|
|
node.setParent(this.characterDisplay);
|
|||
|
|
}
|
|||
|
|
}
|