Files
18xchat/.svn/pristine/8c/8c04e990fc8915da9fa9c3ce054b8e4f81b96521.svn-base
T
2025-07-17 17:18:21 +08:00

411 lines
14 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { _decorator, AudioSource, EditBox, isValid, Label, Node, Sprite, tween, utils, Vec3 } from 'cc';
import { GButton } from '../../Main/Common/GButton';
import Utils from '../../Main/Common/Utils';
import { ViewManager } from '../../Main/Manager/ViewManager';
import { InnerMsgCode } from '../../Main/Config/InnerMsgCode';
import li_BaseView from '../../Main/Common/li_BaseView';
import SubManager from '../SubManager';
import GameManager from '../../Main/Manager/GameManager';
import { I_LevelConfig, I_NpcTalkBack } from '../../Main/Config/CommonConfig';
import HttpUnit from '../../Main/Common/HttpUnit';
import { SDKManager } from '../../Main/Channel/SDKManager';
import ResManager from '../../Main/Manager/ResManager';
const { ccclass, property } = _decorator;
/**对话阶段 */
const enum TalkStage {
/**开场白 */
prologue,
/**我的对话 */
myTalk,
/**等待NPC回复 */
waitNpcTalk,
/**NPC对话 */
npcTalk,
}
//聊天界面
@ccclass('Talk_UI')
export class Talk_UI extends li_BaseView {
private _nodeTab: any = {};
private _data;
private dazijiInfo = {stage: 0, idx: 0, str: "", tm:0, ts:0.05, lab:null}; //打字机信息 stage:0-未开始,1-正在打字,2-打字结束
private npcTalkInfo = {stage: 0, str:"", dotStr:"...", dotIdx:0, tm:0, ts:0.3}; //等待npc回复 stage:0-未开始,1-获取中,2-获取完成
private ebTalk: EditBox;
private labNpcTalk: Label;
private AIAudioSource: AudioSource; //AI语音组件
private curStage: TalkStage = TalkStage.prologue; //当前对话阶段
private lvCfg: I_LevelConfig = null; //当前关卡配置
private lastRandTalkIdx: number = -1; //上一次随机对话的索引
private srouceCnt: number = 0; //已用对话轮次
//----重写父类接口---------------------------------------
onLoadCT() {
this.registerListenner();
Utils.parseNode(this.node, this._nodeTab)
this.ebTalk = this._nodeTab.ebTalk.getComponent(EditBox);
this.labNpcTalk = this._nodeTab.npcTalk.getComponent(Label);
this.ebTalk.node.on('editing-did-began', this.onEditingBegan, this);
this.ebTalk.node.on('editing-did-ended', this.onEditingEnded, this);
this.ebTalk.node.on('editing-return', this.onEditingReturn, this);
this.AIAudioSource = this._nodeTab.videoNode.getComponent(AudioSource);
this._nodeTab.arrowNode.active = false;
let npcNextArrow:Node = this._nodeTab.npcNextArrow
tween(npcNextArrow)
.to(0.5, {position: new Vec3(15, 0, 0)})
.to(0.5, {position: new Vec3(-15, 0, 0)})
.union()
.repeatForever()
.start()
}
openUIDataCT(data: any): void {
this._data = data
}
registerListenner() {
Utils.addInnerEL(InnerMsgCode.Data_NpcTalkBack, this, this.resiveNpcTalkBack)
}
start() {
GButton.BandClick(this._nodeTab.btnBack, this.onBackClick, this);
GButton.BandClick(this._nodeTab.btnSend, this.onSendClick, this);
GButton.BandClick(this._nodeTab.btnSuiji, this.onSuijiClick, this);
GButton.BandClick(this._nodeTab.npcTalkFrame, ()=>{
this.onNpcFramClick();
}, this, 0, null, null, false);
GButton.BandClick(this._nodeTab.btnRecord, ()=>{
ViewManager.I.openBundlesView("UI/StartUI/Record_UI")
}, this);
GButton.BandClick(this._nodeTab.btnTishi, ()=>{
ViewManager.I.openBundlesView("UI/StartUI/Tips_UI")
}, this);
GButton.BandClick(this._nodeTab.btnAD, ()=>{
console.log("观看广告")
ViewManager.I.openBundlesView("UI/StartUI/TalkAdDialog", {
adCallback: ()=>{
SDKManager.show_reward_video_ad(this.node.uuid, 1)
},
shareCallback: ()=>{
SDKManager.show_reward_share(this.node.uuid, 1)
}
})
}, this);
//ai语音开关
GButton.BandClick(this._nodeTab.btnYuyin, ()=>{
GameManager.AIVoiceSwt = !GameManager.AIVoiceSwt;
this.refreshAIVoiceState()
}, this);
this.refreshAIVoiceState()
SDKManager.register_video_reward(this.node.uuid, (tag:number)=>{
console.log("视频广告回调", tag)
if (tag == 1) {
// 加次数
SubManager.ShowPrompt("观看视频成功,获得聊天次数")
this.doAddLevelCnt(1)
}
})
SDKManager.register_share_reward(this.node.uuid, (tag:number)=>{
console.log("分享回调", tag)
if (tag == 1) {
// 加次数
SubManager.ShowPrompt("分享成功,获得聊天次数")
this.doAddLevelCnt(1)
}
})
this.lvCfg = GameManager.getLevelCfg(GameManager.CurLevelId)
//以npc开场白
this.showNpcPrologue()
//刷新状态显示
this.srouceCnt = 0
this.refreshTalkStepData()
}
onDestroy () {
if (isValid(this.ebTalk)) {
this.ebTalk.node.off('editing-did-began', this.onEditingBegan, this);
this.ebTalk.node.off('editing-did-ended', this.onEditingEnded, this);
this.ebTalk.node.off('editing-return', this.onEditingReturn, this);
}
}
update(deltaTime: number) {
//region 打字机效果逻辑
if (this.dazijiInfo.stage == 1) {
this.dazijiInfo.tm += deltaTime
if (this.dazijiInfo.tm >= this.dazijiInfo.ts) {
this.dazijiInfo.tm = 0
this.dazijiInfo.lab.string = this.dazijiInfo.str.substring(0, this.dazijiInfo.idx)
this.dazijiInfo.idx += 1
if (this.dazijiInfo.idx > this.dazijiInfo.str.length) {
this.dazijiInfo.stage = 2
}
}
} else if (this.dazijiInfo.stage == 2) {
console.log("文本打字机效果结束")
this.dazijiInfo.stage = 0
this.dazijiInfo.lab.string = this.dazijiInfo.str
this._nodeTab.arrowNode.active = true;
// if (this.curStage == TalkStage.prologue || this.curStage == TalkStage.npcTalk) {
// this.scheduleOnce(() => {
// this.turnToMyTalk()
// }, 2)
// }
}
//接收npc回复逻辑
if (this.npcTalkInfo.stage == 1) {
this.npcTalkInfo.tm += deltaTime
if (this.npcTalkInfo.tm >= this.npcTalkInfo.ts) {
this.npcTalkInfo.tm = 0
GameManager.I.getNpcTalkBack({})
this.labNpcTalk.string = this.npcTalkInfo.dotStr.substring(0, this.npcTalkInfo.dotIdx)
this.npcTalkInfo.dotIdx += 1
if (this.npcTalkInfo.dotIdx > this.npcTalkInfo.dotStr.length) {
this.npcTalkInfo.dotIdx = 0
}
}
}
}
//接收到npc回复数据流
resiveNpcTalkBack(data:I_NpcTalkBack) {
if (this.curStage != TalkStage.waitNpcTalk) return
if (data.isFinished) {
this.npcTalkInfo.stage = 0
console.log("npc回复:", data)
this.turnToNpcTalk(data)
}
}
//输入框开始编辑事件
onEditingBegan(param1:any, param2:any) {
console.log("聊天界面1 onEditingBegan", param1, param2)
}
//输入框回车事件
onEditingReturn(param1:any, param2:any) {
console.log("聊天界面2 onEditingReturn", param1, param2)
}
//输入框结束编辑事件
onEditingEnded(param1:any, param2:any) {
console.log("聊天界面3 onEditingEnded", param1, param2)
}
//刷新AI语音状态
private refreshAIVoiceState() {
let voicePath = GameManager.AIVoiceSwt ? "lv_4" : "lv_5"
let sptYuyin = this._nodeTab.sptYuyin.getComponent(Sprite)
ResManager.I.changeBundleSpriteFrame(sptYuyin, voicePath, "Zhujiemian")
}
//播放AI语音
private playAIVoice(str:string) {
if (!GameManager.AIVoiceSwt) {
return
}
HttpUnit.ins.getAIVoice({record_id: GameManager.RecordId, text:str}, (data) => {
if (data) {
console.log("播放AI语音11", data)
SDKManager.playBase64Audio(data.url, false)
// let qianzhui = "data:audio/x-wav;base64,"
// let substring = data.url.substring(qianzhui.length, data.url.length)
// this.base64ToAudio(substring, (localUrl)=>{
// console.log("播放AI语音22", localUrl)
// // 创建音频元素并播放
// const audio = new Audio(localUrl);
// audio.play();
// // ResManager.I.loadRemoteAudio(localUrl, (audio) => {
// // this.AIAudioSource.clip = audio
// // this.AIAudioSource.play()
// // this.AIAudioSource.volume = 1
// // // this.AIAudioSource.playOneShot(audio, 1)
// // })
// })
}
})
}
//显示NPC开场白
private showNpcPrologue() {
this.curStage = TalkStage.prologue
this._nodeTab.NpcTalkNode.active = true
this._nodeTab.MyTalkNode.active = false
this._nodeTab.arrowNode.active = false;
//名称
Utils.setString(this._nodeTab.npcName, this.lvCfg.name)
//开场白
this.dazijiInfo.stage = 1
this.dazijiInfo.idx = 0
this.dazijiInfo.lab = this.labNpcTalk
this.dazijiInfo.str = this.lvCfg.prologueMessage
this.dazijiInfo.tm = this.dazijiInfo.ts
GameManager.AddTalkRecord({talk:this.lvCfg.prologueMessage, isMe:false})
this.playAIVoice(this.lvCfg.prologueMessage)
}
/**切换到玩家说话状态 */
private turnToMyTalk() {
if (this.curStage == TalkStage.myTalk) return
this.curStage = TalkStage.myTalk
this._nodeTab.NpcTalkNode.active = false
this._nodeTab.MyTalkNode.active = true
this.ebTalk.string = ""
}
/**切换到等待NPC说话状态 */
private turnToWaitNpcTalk() {
if (this.curStage == TalkStage.waitNpcTalk) return
this.curStage = TalkStage.waitNpcTalk
this._nodeTab.NpcTalkNode.active = true
this._nodeTab.MyTalkNode.active = false
this._nodeTab.arrowNode.active = false;
this.labNpcTalk.string = ""
}
/**切换到NPC说话状态 */
private turnToNpcTalk(data:I_NpcTalkBack) {
if (this.curStage == TalkStage.npcTalk) return
this.curStage = TalkStage.npcTalk
this._nodeTab.NpcTalkNode.active = true
this._nodeTab.MyTalkNode.active = false
this._nodeTab.arrowNode.active = false;
GameManager.AddStepScore(data.aiScore) //记录本次分数
//npc回复
// this.labNpcTalk.string = data.aiResponse
this.dazijiInfo.stage = 1
this.dazijiInfo.idx = 0
this.dazijiInfo.lab = this.labNpcTalk
this.dazijiInfo.str = data.aiResponse
this.dazijiInfo.tm = this.dazijiInfo.ts
GameManager.AddTalkRecord({talk:data.aiResponse, isMe:false})
this.playAIVoice(data.aiResponse)
//npc表情
//分数
//对话轮次
this.srouceCnt = data.sourceCnt
this.refreshTalkStepData()
}
/**刷新当前状态显示 */
private refreshTalkStepData() {
let stepData = GameManager.CurLevelData
Utils.setString(this._nodeTab.lunciNum, `${this.srouceCnt}/${stepData.total_cnt}`)
}
//检查对话轮次是否用完
private checkIsFinish() {
// //测试代码
// if (true) {
// return this.srouceCnt >= 1
// }
let stepData = GameManager.CurLevelData
return this.srouceCnt >= stepData.total_cnt
}
//增加聊天次数
private doAddLevelCnt(add:number = 1) {
HttpUnit.ins.addTalkCnt({record_id: GameManager.RecordId, add_cnt:add}, (data) => {
if (data) {
GameManager.CurLevelData = data.level
this.refreshTalkStepData()
}
})
}
//结算
private doJiesuan() {
let [score, score_all] = GameManager.getGameScore()
HttpUnit.ins.sendLevelFinish({record_id: GameManager.RecordId, score:score, score_all:score_all}, (data) => {
if (data && data.level) {
//成功
ViewManager.I.openBundlesView("UI/StartUI/Finish_UI", data.level)
} else {
//失败
this.doClose();
Utils.sendInnerMsg(InnerMsgCode.UI_Talk_Back, {})
}
})
}
//退出聊天
onBackClick() {
SubManager.ShowConfirm({
content: "确定退出吗?",
yesCallback: () => {
this.doJiesuan();
}
})
}
//发送消息
onSendClick() {
let str = this.ebTalk.string;
if (str.length == 0) {
SubManager.ShowPrompt("请先输入内容")
return
}
this.turnToWaitNpcTalk()
this.ebTalk.string = ""
HttpUnit.ins.sendUserTalk({record_id: GameManager.RecordId, user_input: str}, (data) => {
if (data) {
GameManager.AddTalkRecord({talk:str, isMe:true})
//开始接收npc回复
this.npcTalkInfo.stage = 1
this.npcTalkInfo.str = ""
this.npcTalkInfo.tm = this.npcTalkInfo.ts
this.npcTalkInfo.dotIdx = 0
}
})
}
//随机回复对话
onSuijiClick() {
let sjLen = this.lvCfg.randomInputPool.length
let randIdx = Utils.getRandomInt(0, sjLen-1)
console.log("随机回复对话:", randIdx, sjLen)
if (randIdx == this.lastRandTalkIdx) {
randIdx++
if (randIdx >= sjLen) randIdx = 0
}
this.lastRandTalkIdx = randIdx
this.ebTalk.string = this.lvCfg.randomInputPool[randIdx]
}
//点击npc对话背景
onNpcFramClick() {
if (this.dazijiInfo.stage == 1) {
this.dazijiInfo.stage = 2
} else {
if (this.curStage == TalkStage.prologue || this.curStage == TalkStage.npcTalk) {
if (this.checkIsFinish()) {
this.doJiesuan()
} else {
this.turnToMyTalk()
}
}
}
}
}