黑神话共4条血条
白色血条:当前生命值
绿色血条:恢复生命后生命值
暗红血条:第一次伤害前血量
浅红血条:当前伤害距离上一次伤害的的血量
加血效果,先有一个绿色条显示血量会恢复到哪,间隔一小段时间后,白色血条缓动和绿色血量一样长。
1 当前血量50
2 喝药恢复到100,则绿色血条立即100,白色血条仍旧50
3 间隔1s后,白色血条缓动到100。

白色血量直接显示伤害后血量,暗红血条显示第一次伤害前血量位置,浅红血条显示连击的每次伤害血量位置。
每次连击,浅红血条都会显示该次攻击的伤害量。
间隔一小段时间,浅红血条和白色血条一样长,无连击一小段时间后,暗红血条缓动到和白色血条一样长。
1 当前血量100,第一次伤害10,白色血条90,暗红血条100,浅红血条100
2 第二次伤害10,白色血条80,暗红血条100,浅红血条90
3 第三次伤害10,白色血条70,暗红血条100,浅红血条80
4 无伤害0.5s,浅红血条消失
5 无伤害1s,暗红血条缓动到白色血条一样长

伤害时喝药,暗红和浅红血条都消失,走绿色血条逻辑。
喝药时受伤害,绿色血条消失,白色血条直接显示当当前生命位置,走暗红和浅色血条逻辑。
HpProgress.ts:
import { _decorator, Component, Node, Tween, tween, UITransform, v3 } from 'cc';
const { ccclass, property } = _decorator;
/**
* 血条
*/
@ccclass('HpProgress')
export class HpProgress extends Component {
@property({ type: Node, tooltip: "暗红" })
bigRed: Node = null;
@property({ type: Node, tooltip: "浅红" })
smallRed: Node = null;
@property({ type: Node, tooltip: "绿色" })
green: Node = null;
@property({ type: Node, tooltip: "白色" })
write: Node = null;
/**当前进度 */
private rate: number = 1;
/**是否连击中。产生伤害时,连击开始=true。当喝血或者暗红色血条消失时,连击结束=false */
private keepHit: boolean = false;
/**白色血条、绿色血条、暗红血条持续时间 */
private time1: number = 2;
/**持续时间结束后,白色血条或暗红血条tween缓动时间 */
private time2: number = 0.5;
/**浅红血条持续时间 */
private time3: number = 1;
/**持续时间结束后,浅红血条tween缓动时间 */
private time4: number = 0.2;
/**减血时白色血条、加血时绿色血条变化tween时间 */
private time5: number = 0.1;
/**血条原始宽度 */
private oriWidth: number;
protected onLoad(): void {
this.oriWidth = this.bigRed.getComponent(UITransform).width;
}
/**设置血条原始长度 */
public setOriWidth(oriWidth: number) {
this.oriWidth = oriWidth;
}
/**
* 设置时间
* @param time1
* @param time2
* @param time3
*/
public setTime(time1: number, time2: number, time3: number) {
this.time1 = time1;
this.time2 = time2;
this.time3 = time3;
}
/**
* 设置血条进度
* @param rate 进度 [0,1]
* @param bTween 是否有缓动动画,true直接设置,false缓动动画
*/
public setHpPro(rate: number, bTween: boolean) {
rate = Math.max(0, rate);
rate = Math.min(1, rate);
//无动画
if (bTween == false) {
//停止所有计时器
this.stopWriteTimer();
this.stopBigRedTimer();
this.stopSamllRedTimer();
this.stopGreenTween();
//血条直接设置到当前血量位置
this.bigRed.getComponent(UITransform).width = this.oriWidth * rate;
this.smallRed.getComponent(UITransform).width = this.oriWidth * rate;
this.green.getComponent(UITransform).width = this.oriWidth * rate;
this.write.getComponent(UITransform).width = this.oriWidth * rate;
this.rate = rate;
return;
}
//减血,有动画
if (rate < this.rate) {
//停止绿色、白色血条计时器
this.stopWriteTimer();
this.stopGreenTween();
//白色血条缓动到血量位置
tween(this.write.getComponent(UITransform)).to(this.time5, { width: this.oriWidth * rate }).start();
//绿色血条直接设置到血量
this.green.getComponent(UITransform).width = this.oriWidth * rate;
//非连击,即第一次伤害,暗红和浅红血条保持在第一次伤害前血量位置
if (this.keepHit == false) {
this.bigRed.getComponent(UITransform).width = this.oriWidth * this.rate;
this.smallRed.getComponent(UITransform).width = this.oriWidth * this.rate;
//连击
this.keepHit = true;
//连击,暗红血条不动,浅红血条设置在上一次伤害时血量
} else {
this.smallRed.getComponent(UITransform).width = this.oriWidth * this.rate;
}
//保存进度
this.rate = rate;
//启动浅红血条计时器
this.stopSamllRedTimer();
this.startSmallRedTimer();
//启动暗红血条计时器
this.stopBigRedTimer();
this.startBigRedTimer();
//加血,有动画
} else if (rate > this.rate) {
//连击停止
this.keepHit = false;
//停止绿色、暗红、浅红血条计时器
this.stopSamllRedTimer();
this.stopBigRedTimer();
this.stopGreenTween();
//绿色血条缓动到血量位置
tween(this.green.getComponent(UITransform)).to(this.time5, { width: this.oriWidth * rate }).start();
//白色血条不动
//暗红血条、浅色血条设置到白色血条位置
this.bigRed.getComponent(UITransform).width = this.write.getComponent(UITransform).width;
this.smallRed.getComponent(UITransform).width = this.write.getComponent(UITransform).width;
//保存进度
this.rate = rate;
//启动白色血条计时器
this.stopWriteTimer();
this.startWriteTimer();
}
}
/**启动浅红血条计时器 */
private startSmallRedTimer() {
this.scheduleOnce(this.onSmallRedTimer, this.time3);
}
/**浅红血条缓动到到白色血条位置 */
private onSmallRedTimer() {
tween(this.smallRed.getComponent(UITransform)).to(this.time4, { width: this.write.getComponent(UITransform).width }).start();
}
/**停止浅红血条计时器 */
private stopSamllRedTimer() {
this.unschedule(this.onSmallRedTimer);
Tween.stopAllByTarget(this.smallRed.getComponent(UITransform));
}
/**启动暗红血条计时器 */
private startBigRedTimer() {
this.scheduleOnce(this.onBigRedTimer, this.time1);
}
/**暗红血条间隔时间到,开始缓动到白色血条位置 */
private onBigRedTimer() {
Tween.stopAllByTarget(this.bigRed.getComponent(UITransform));
tween(this.bigRed.getComponent(UITransform)).to(this.time2, { width: this.write.getComponent(UITransform).width }).call(() => {
//连击停止
this.keepHit = false;
}).start();
}
/**停止暗红血条计时器 */
private stopBigRedTimer() {
this.unschedule(this.onBigRedTimer);
Tween.stopAllByTarget(this.bigRed.getComponent(UITransform));
}
/**启动白色血条计时器 */
private startWriteTimer() {
this.scheduleOnce(this.onWriteTimer, this.time1);
}
/**白色血条间隔时间到,开始缓动到绿色血条位置 */
private onWriteTimer() {
Tween.stopAllByTarget(this.write.getComponent(UITransform));
tween(this.write.getComponent(UITransform)).to(this.time2, { width: this.green.getComponent(UITransform).width }).start();
}
/**停止白色血条计时器 */
private stopWriteTimer() {
this.unschedule(this.onWriteTimer);
Tween.stopAllByTarget(this.write.getComponent(UITransform));
}
/**停止绿色血条tween */
private stopGreenTween() {
Tween.stopAllByTarget(this.green.getComponent(UITransform));
}
}
场景中有如下节点,hpProgress上绑定HpProgress.ts组件

HpProgressDemo.ts:
import { _decorator, Component, Node } from 'cc';
import { HpProgress } from '../../src/framework/component/HpProgress';
const { ccclass, property } = _decorator;
@ccclass('HpProgressDemo')
export class HpProgressDemo extends Component {
@property({ type: HpProgress, tooltip: "血条" })
hpProgress: HpProgress = null;
@property({ type: Node, tooltip: "加血" })
addBtn: Node = null;
@property({ type: Node, tooltip: "减血" })
reduceBtn: Node = null;
@property({ type: Node, tooltip: "直接设置" })
setBtn: Node = null;
private cur: number = 1000; //当前血量
private total: number = 1000; //总血量
protected onLoad(): void {
this.addBtn.on(Node.EventType.TOUCH_END, this.onAddBtn, this);
this.reduceBtn.on(Node.EventType.TOUCH_END, this.onReduceBtn, this);
this.setBtn.on(Node.EventType.TOUCH_END, this.onSetBtn, this);
}
private onAddBtn() {
let rand: number = Math.round(Math.random() * 100) + 10;
this.cur = Math.min(this.total, this.cur + rand);
console.log("加血:", rand);
this.hpProgress.setHpPro(this.cur / this.total, true);
}
private onReduceBtn() {
let rand: number = Math.round(Math.random() * 100) + 10;
this.cur = Math.max(0, this.cur - rand);
console.log("减血:", rand);
this.hpProgress.setHpPro(this.cur / this.total, true);
}
private onSetBtn() {
this.cur = this.total / 2;
this.hpProgress.setHpPro(this.cur / this.total, false);
}
}
演示效果:

浙公网安备 33010602011771号