版本:2.4.4

参考:cocos论坛-富文本打字机效果

 

一 功能需求

游戏中有剧情对话时会用到打字机效果

 

功能需求

1 对话字符串需要逐字显示,那么就得用计时器来获取字符进行显示。

2 关键字需要高亮显示,所以要用到富文本cc.RichText。

3 需要主动换行,在字符串里加入 \n 就可以换行了,不需要额外处理。

4 点击屏幕空白处,文字会一次性全部显示出来,让急性子玩家快速过剧情。

5 打字结束后需要监听结束事件,以便处理其它事情。

 

二 打字机实现

1. 用cc.director.getScheduler做计时器,逐字显示。

2. 富文本只支持一层<color></color>,不能嵌套<color><color></color></color>。chatAt来检查当前字符是否是标签开头"<",如果是则跳过显示标签收尾">"的后一个文字。

3. finishNow()让文字一次性全部显示出来。

4. isFinish()可以检查文字打印效果是否完成。

5. 继承cc.EventTarget,这样class PringEffect才能派发和监听事件,监听PrintEffect.FINISH事件可以在打字结束后处理其它事件。

PrintEffect.ts

const { ccclass, property } = cc._decorator;

/**
 * 打字机效果
 * @author chenkai 2022.8.31
 */
@ccclass
export default class PrintEffect extends cc.EventTarget {
    /**打字效果播放完成 */
    public static FINISH: string = "PrintEffect_FINISH";

    /**消息文本 cc.Label或cc.RichText*/
    private msgLab: any;
    /**需要显示的消息,支持一层richText <color=#ffffffff>xxx</color> */
    private msg: string;
    /**当前显示的消息字符串位置 */
    private curMsgIndex: number;
    /**打字机效果是否已播放完成 */
    private bFinish: boolean = false;
    /**文字显示速度 单位s */
    private textSpeed: number = 0.05;
    /**是否需要增加</color>符号 */
    private bNeedFlag: boolean = false;

    /**
     * 播放打字机效果
     * @param msgLab    消息文本 cc.Label或cc.RichText
     * @param msg       消息 支持一层richText <color=#ffffffff>xxx</color>
     * @param textSpeed 打印速度
     */
    public play(msgLab: any, msg: string, textSpeed: number = 0.05) {
        this.bFinish = false;
        this.bNeedFlag = false;
        this.msgLab = msgLab;
        this.msg = msg;
        this.curMsgIndex = 0;
        this.msgLab.string = "";
        this.textSpeed = textSpeed;
        let sch = cc.director.getScheduler();
        sch.enableForTarget(this);
        sch.schedule(this.onSchedule, this, this.textSpeed);
    }

    /**定时处理 */
    private onSchedule() {
        //如果是"<"标签开头,将curMsgIndex移动到<>标签的后一位。
        if (this.msg.charAt(this.curMsgIndex) == "<") {
            //如果bNeedFlag=false不需要增加符号,则表示当前是开头标签<>,将bNeedFlag取反为true,后面的文字需要增加符号<>。
            //如果bNeedFlag=true需要增加符号,则表示当前是收尾标签<>,将bNeedFlag取反为false,后面的文字不需要增加符号<>。
            this.bNeedFlag = !this.bNeedFlag;
            for (let i = this.curMsgIndex; i < this.msg.length; i++) {
                //显示位置移动1位
                this.curMsgIndex++;
                //检查是否是">",如果是,则将标签移动1位,显示标签">"后的文字
                if (this.msg.charAt(this.curMsgIndex) == ">") {
                    this.curMsgIndex++;
                    break;
                }
            }
        }
        //显示字符串
        this.curMsgIndex++;
        if (this.bNeedFlag) {
            this.msgLab.string = this.msg.substr(0, this.curMsgIndex) + "</color>";
        } else {
            this.msgLab.string = this.msg.substr(0, this.curMsgIndex);
        }
        //结束
        if (this.curMsgIndex >= this.msg.length) {
            let sch = cc.director.getScheduler();
            sch.unschedule(this.onSchedule, this);
            this.bFinish = true;
            this.emit(PrintEffect.FINISH);
        }
    }

    /**
     * 检查是否打印动画播放完成
     * @returns true完成 false未完成
     */
    public isFinish() {
        return this.bFinish;
    }

    /**立即结束,并显示全部消息 */
    public finishNow() {
        let sch = cc.director.getScheduler();
        sch.enableForTarget(this);
        sch.unschedule(this.onSchedule, this);
        this.msgLab && (this.msgLab.string = this.msg);
        this.bFinish = true;
        this.emit(PrintEffect.FINISH);
    }

    /**停止并清理文本 */
    public clear() {
        let sch = cc.director.getScheduler();
        sch.enableForTarget(this);
        sch.unschedule(this.onSchedule, this);
        this.msgLab && (this.msgLab.string = "");
        this.bFinish = true;
    }
}

  

三 使用打字机

MainScene.ts:

const { ccclass, property } = cc._decorator;

/**
 * 打字机效果
 * @author chenkai 2022.8.31
 */
@ccclass
export default class PrintEffectDemo extends cc.Component {

    @property({ type: cc.RichText, tooltip: "消息文本" })
    msgLab: cc.RichText = null;


    onLoad() {
        let str = "打字机效果<color=#0fffff>打字机效果打字机</color>打字机效果打字机效果\n打字机效果<color=#0fffff>打字机效果打字机</color>效果打字机效果打字机效果\n打字机效果";
        let printEffect: PrintEffect = new PrintEffect();
        //清理打印效果
        printEffect.clear();
        //检查是否打印完成
        console.log("是否打印完成:", printEffect.isFinish());
        //监听打印完成事件
        printEffect.on(PrintEffect.FINISH, () => {
            console.log("监听到打印完成事件");
        }, this);
        //点击屏幕,立即结束打印效果
        this.node.on(cc.Node.EventType.TOUCH_END, () => {
            printEffect.finishNow();
        }, this);
        //开始打印
        printEffect.play(this.msgLab, str, 0.2);
    }
}

  

显示效果

 

 

 

 

posted on 2022-08-31 17:01  gamedaybyday  阅读(709)  评论(4编辑  收藏  举报