版本:2.4.4
一 功能需求
游戏中有剧情对话时会用到打字机效果

功能需求
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);
}
}
显示效果

浙公网安备 33010602011771号