一  黑神话血条设计

二  加血效果

三 减血效果

四 加血或喝水打断效果

五 代码实现

 

一  黑神话血条设计

黑神话共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);
    }
}

  

演示效果:

 

posted on 2024-10-13 11:12  gamedaybyday  阅读(129)  评论(0)    收藏  举报