gameCtr.ts 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. import {
  2. _decorator,
  3. Animation,
  4. AnimationClip,
  5. AudioClip,
  6. AudioSource,
  7. CharacterController,
  8. Color,
  9. Component,
  10. director,
  11. EventMouse,
  12. EventTouch,
  13. Label,
  14. Node,
  15. NodeEventType,
  16. ParticleSystem2D,
  17. ProgressBar,
  18. Sprite,
  19. tween,
  20. Tween,
  21. UIOpacity,
  22. UITransform,
  23. v3,
  24. Vec2,
  25. Vec3
  26. } from "cc"
  27. import { noticePannelCtr } from "./noticePannelCtr"
  28. import { StoryPannelCtr } from "./StoryPannelCtr"
  29. import { OptionsCtr } from "./OptionsCtr"
  30. import { rankCtr } from "./rankCtr"
  31. import { RoleCtr } from "./RoleCtr"
  32. import { processCtr } from "./socket/processCtr"
  33. import { SocketClient } from "./socket/SocketClient"
  34. const { ccclass, property } = _decorator
  35. import flatObj from "./FloatObj"
  36. import floatObj from "./FloatObj"
  37. @ccclass("GameCtr")
  38. export class GameCtr extends Component {
  39. @property({ type: noticePannelCtr })
  40. public noticeCtr: noticePannelCtr | null = null
  41. @property({ type: SocketClient })
  42. public socketClient: SocketClient | null = null
  43. @property({ type: processCtr })
  44. public processCtr: processCtr | null = null
  45. @property({ type: RoleCtr })
  46. public roleCtr: RoleCtr | null = null
  47. @property({ type: StoryPannelCtr })
  48. public storyPannelCtr: StoryPannelCtr | null = null
  49. @property({ type: OptionsCtr })
  50. public optionsCtr: OptionsCtr | null = null
  51. @property({ type: rankCtr })
  52. public rankCtr: rankCtr | null = null
  53. @property({ type: Node })
  54. public titlePannel: Node = null
  55. @property({ type: Label })
  56. private dayLabel: Label | null = null
  57. @property(Animation)
  58. SunAnim: Animation = null
  59. @property(Animation)
  60. MoonAnim: Animation = null
  61. @property(Animation)
  62. BgAnim: Animation = null
  63. @property({ type: Node })
  64. BgNode: Node = null
  65. private sunIsUp: boolean = false
  66. private num: number = 1
  67. public roomId: number = 1
  68. public gameId: number = 1
  69. public resetNum: number = 1
  70. public gameStatus: string = ""
  71. public gameLine: number = 0
  72. private gameInfo: any = null
  73. private historyInfo: any[] = []
  74. private initStoryPosition: Vec3 = null
  75. private initOptionsPosition: Vec3 = null
  76. //剧情布局变化状态:0:展示剧情 ,1:出现选项框 2:已选选项下方展示剧情,3:已选移除剧情上移出现选项框
  77. public storyActionStatus: number = 0
  78. //重启动画
  79. @property({ type: Label })
  80. public resetLabel: Label = null
  81. @property({ type: ProgressBar })
  82. public progressBar: ProgressBar = null
  83. @property({ type: Node })
  84. public resetNode: Node = null
  85. private _dotsCounter: number = 0
  86. private _dotsInterval: any = null
  87. //剧情选项相关
  88. private options: any[] = []
  89. private optionsLabel: string[] = []
  90. private storyHeight = 510
  91. private selectedOptionNum: number = 4
  92. //排名相关
  93. private rankInfo: any[] = []
  94. //角色信息
  95. private npc: any[] = null
  96. private player: any[] = null
  97. //简历角色名-node 字典
  98. private roleNodes = {}
  99. private modifyHp: any[]
  100. //确认正式同步后台数据正式开始标签
  101. private realStart: boolean = false
  102. //通知相关
  103. private noticeStr: string = ""
  104. @property(AudioClip)
  105. public moveClip: AudioClip = null!
  106. @property(AudioClip)
  107. public showOptionsClip: AudioClip = null!
  108. @property(AudioClip)
  109. public selectedOptionClip: AudioClip = null!
  110. public audioSource: AudioSource = null!
  111. @property(AudioSource)
  112. public bg1AudioSource: AudioSource = null!
  113. @property(AudioSource)
  114. public bg2AudioSource: AudioSource = null!
  115. private isPlayBgm1 = true
  116. public originUrl: string = null
  117. public hostName: string = null
  118. private globalUrl: string = "https://airpg1.izouma.com"
  119. private globalHostname: string = "airpg1.izouma.com"
  120. private moveNum: number = 1
  121. private lastVote: number[] = [0, 0, 0, 0]
  122. private currentDay: number = 0
  123. init() {
  124. //播放第一个背景音乐
  125. this.bg1AudioSource.play()
  126. console.log(location.href)
  127. if (location.hostname === "localhost") {
  128. this.originUrl = this.globalUrl
  129. this.hostName = this.globalHostname
  130. } else {
  131. this.originUrl = location.origin
  132. this.hostName = location.hostname
  133. }
  134. let roomId = new URLSearchParams(location.search).get("roomId")
  135. if (roomId != null) {
  136. this.roomId = Number(roomId)
  137. console.log("get roomId from URL:" + roomId)
  138. } else {
  139. console.log("use defult roomId")
  140. }
  141. const roomUrl = `${this.originUrl}/api/room/${this.roomId}`
  142. console.log(roomUrl)
  143. fetch(roomUrl)
  144. .then((response) => {
  145. if (!response.ok) {
  146. throw new Error("Network response was not ok")
  147. }
  148. return response.json()
  149. })
  150. .then((data) => {
  151. //获取游戏ID,房间信息
  152. console.log(data.currentGameId + " " + data.active)
  153. let gameId = new URLSearchParams(location.search).get("gameId")
  154. if (gameId != null) {
  155. this.gameId = Number(gameId)
  156. console.log("get gameId from URL:" + gameId)
  157. } else {
  158. this.gameId = data.currentGameId
  159. }
  160. this.noticeStr = data.notice
  161. if (this.socketClient.socket) {
  162. this.socketClient.socket.disconnect()
  163. } else {
  164. this.socketClient.gameId = this.gameId
  165. this.socketClient.initSocketConnection()
  166. }
  167. const gameUrl = `${this.originUrl}/api/game/${this.gameId}`
  168. fetch(gameUrl)
  169. .then((response) => {
  170. if (!response.ok) {
  171. throw new Error("Network response was not ok")
  172. }
  173. return response.json()
  174. })
  175. .then((data) => {
  176. console.log(data)
  177. const historyUrl = `${this.originUrl}/api/game/${this.gameId}/history`
  178. this.gameInfo = data
  179. this.resetNum = data.resetNum
  180. if (new URLSearchParams(location.search).get("gameId") !== null) {
  181. this.gameStatus = data.status
  182. }
  183. if (this.gameStatus === "finished") {
  184. this.gameLine = 0
  185. }
  186. fetch(historyUrl)
  187. .then((response) => {
  188. if (!response.ok) {
  189. throw new Error("Network response was not ok")
  190. }
  191. return response.json()
  192. })
  193. .then((data) => {
  194. console.log("history")
  195. console.log(data)
  196. this.historyInfo = data
  197. //根据游戏信息与历史信息更新房间组件
  198. this.updateGame(this.gameInfo, this.historyInfo)
  199. if (this.gameStatus === "finished") {
  200. this.addHistoryQueue(this.historyInfo)
  201. } else {
  202. }
  203. })
  204. .catch((error) => {
  205. console.error("Fetch error:", error)
  206. })
  207. })
  208. .catch((error) => {
  209. console.error("Fetch error:", error)
  210. })
  211. })
  212. .catch((error) => {
  213. console.error("Fetch error:", error)
  214. })
  215. this.initRank(roomUrl + "/survivalRank")
  216. }
  217. initRank(url: string) {
  218. fetch(url)
  219. .then((response) => {
  220. if (!response.ok) {
  221. throw new Error("Network response was not ok")
  222. }
  223. return response.json()
  224. })
  225. .then((data) => {
  226. console.log("rank")
  227. console.log(data)
  228. this.rankInfo = data
  229. //根据游戏信息与历史信息更新房间组件
  230. this.rankCtr.updateRank(this.rankInfo)
  231. })
  232. .catch((error) => {
  233. console.error("Fetch error:", error)
  234. })
  235. }
  236. start() {
  237. //加载音频播放组件
  238. this.audioSource = this.node.getComponent(AudioSource)
  239. this.startResetAnimation()
  240. // this.scheduleOnce(() => { this.accessTargetComponent() }, 0.1)
  241. this.scheduleOnce(() => {
  242. this.init()
  243. }, 10)
  244. this.processCtr.init(this)
  245. this.schedule(this.chackGameInfo, 5 * 60)
  246. }
  247. chackGameInfo() {
  248. //轮询检查游戏信息
  249. const roomUrl = `${this.originUrl}/api/room/${this.roomId}`
  250. fetch(roomUrl)
  251. .then((response) => {
  252. if (!response.ok) {
  253. throw new Error("Network response was not ok")
  254. }
  255. return response.json()
  256. })
  257. .then((data) => {
  258. //获取游戏ID,房间信息
  259. console.log("轮询检查房间信息:" + data.currentGameId + " " + data.active)
  260. if (this.gameId == data.currentGameId) {
  261. if (this.noticeStr == data.notice) {
  262. return
  263. } else {
  264. this.noticeCtr.updateText(data.notice)
  265. this.noticeStr = data.notice
  266. }
  267. } else {
  268. director.loadScene("game")
  269. }
  270. })
  271. .catch((error) => {
  272. console.error("Fetch error:", error)
  273. })
  274. //查看历史记录,校验游戏是否还在同步中
  275. const historyUrl = `${this.originUrl}/api/game/${this.gameId}/history`
  276. fetch(historyUrl)
  277. .then((response) => {
  278. if (!response.ok) {
  279. throw new Error("Network response was not ok")
  280. }
  281. return response.json()
  282. })
  283. .then((data) => {
  284. const currentHistory: any[] = data
  285. // 计算日期差(结果单位为毫秒)
  286. const lastHistoryDate = new Date(currentHistory[currentHistory.length - 1].date)
  287. const firstHistoryDate = new Date(this.historyInfo[0].date)
  288. const differenceInMilliseconds = flatObj.subtract(lastHistoryDate.getTime(), firstHistoryDate.getTime())
  289. // 将毫秒转为天数
  290. let _differenceInMilliseconds = flatObj.divide(differenceInMilliseconds, 1000 * 60 * 60 * 24)
  291. const differenceInDays = flatObj.add(differenceInMilliseconds, 1)
  292. console.log("校验游戏进程是否同步:当前天数:" + this.currentDay + " 后台进行天数" + differenceInDays)
  293. //如果相差超过3天,则重置
  294. if (floatObj.subtract(differenceInDays, this.currentDay) > 2) {
  295. director.loadScene("game")
  296. }
  297. })
  298. .catch((error) => {
  299. console.error("Fetch error:", error)
  300. })
  301. }
  302. update(deltaTime: number) {}
  303. onButtonClick() {
  304. //director.loadScene(director.getScene().name);
  305. // this.exchangeTime()
  306. // this.noticeCtr.updateText(
  307. // "在 Cocos Creator 编辑器中,将富文本组件拖放到脚本的 richText 属性框中。运行游戏,现在你应该可以看到富文本的内容逐字出现。"
  308. // )
  309. //options初始化
  310. this.moveNum++
  311. // this.optionsCtr.showVotes(this.moveNum)
  312. // this.optionsCtr.selectOption(3)
  313. //重置测试
  314. //this.startResetAnimation()
  315. //测试排行切换
  316. // this.rankCtr.updateRankTop()
  317. //测试剧情Pannel移动
  318. // this.optionsAppearAction()
  319. //测试被攻击
  320. this.roleCtr.attack(this.roleCtr.node.getChildByName("role_icon_npc1"))
  321. // this.roleCtr.attack(this.roleCtr.node.getChildByName('role_icon_npc3'));
  322. this.roleCtr.treat(this.roleCtr.node.getChildByName("role_icon_npc2"))
  323. // this.roleCtr.newPlayer(this.roleCtr.node.getChildByName('role_icon_player1'));
  324. }
  325. //重启动画相关
  326. startResetAnimation() {
  327. // Fade in the black mask
  328. if (this._dotsInterval) {
  329. clearInterval(this._dotsInterval)
  330. this._dotsInterval = null
  331. }
  332. this.resetNode.getComponent(UIOpacity).opacity = 0
  333. this.progressBar.progress = 0
  334. this.resetNode.active = true
  335. this.BgNode.getComponent(UIOpacity).opacity = 0
  336. tween(this.resetNode.getComponent(UIOpacity))
  337. .to(1, { opacity: 255 })
  338. .call(() => this.showResetTextAndProgress())
  339. .start()
  340. }
  341. showResetTextAndProgress() {
  342. this.updateDots()
  343. this._dotsInterval = setInterval(() => this.updateDots(), 500)
  344. // Simulate progress
  345. let progress = 0
  346. const progressInterval = setInterval(() => {
  347. progress += 0.1
  348. this.progressBar.progress = progress
  349. if (progress >= 1) {
  350. clearInterval(progressInterval)
  351. this.endResetAnimation()
  352. }
  353. }, 1000)
  354. }
  355. updateDots() {
  356. const dots = ".".repeat((this._dotsCounter % 3) + 1)
  357. this.resetLabel.string = `世界重置中${dots}`
  358. this._dotsCounter++
  359. }
  360. endResetAnimation() {
  361. clearInterval(this._dotsInterval)
  362. // Fade out the black mask and reset
  363. tween(this.resetNode.getComponent(UIOpacity))
  364. .to(1, { opacity: 0 })
  365. .call(() => {
  366. this.progressBar.progress = 0
  367. this.resetNode.active = false
  368. this.BgNode.getComponent(UIOpacity).opacity = 255
  369. })
  370. .start()
  371. }
  372. handleStoryPannelMove(data: any) {
  373. this.storyPannelCtr.storyContent = data.data
  374. this.storyPannelCtr.isOnProcess = true
  375. //0:初始化后第一次收到剧情,直接展示剧情
  376. //3:接收到了最后一次剧情展示后清除队列
  377. if (this.storyActionStatus == 0 || this.storyActionStatus == 3) {
  378. if (this.storyPannelCtr) {
  379. this.storyPannelCtr.updateStory(data.data)
  380. } else {
  381. console.log("plot error")
  382. }
  383. this.realStart = true
  384. this.noticeCtr.updateText(this.noticeStr)
  385. } else if (this.storyActionStatus == 2) {
  386. this.optionsAppearAction()
  387. }
  388. }
  389. //处理收到选项事件
  390. handleOptions(data: any) {
  391. if (this.realStart) {
  392. this.options = data.data
  393. //更新optionsLabel
  394. for (let i = 0; i < 4; i++) {
  395. this.optionsLabel[i] = this.options[i].content
  396. }
  397. if (this.storyActionStatus === 0 || this.storyActionStatus === 3) {
  398. this.optionsAppearAction()
  399. //重置记票
  400. this.lastVote = [0, 0, 0, 0]
  401. } else {
  402. console.log("handleOptions处理失败" + " storyActionStatus" + this.storyActionStatus)
  403. this.processCtr.doneProcessing()
  404. }
  405. } else {
  406. console.log("handleOptions处理完成处理下一个")
  407. this.processCtr.doneProcessing()
  408. }
  409. }
  410. //处理投票进度
  411. handleVotes(data: any) {
  412. let vote: number[] = data.data
  413. if (this.realStart && Math.max(...vote) > 0 && JSON.stringify(this.lastVote) !== JSON.stringify(vote)) {
  414. // console.log("this22222"+this+" processCtr!!!!!"+this.processCtr)
  415. this.optionsCtr.showVotes(vote, this.lastVote, this.processCtr)
  416. this.lastVote = vote
  417. } else {
  418. console.log(
  419. "handle votes do nothing:" +
  420. this.realStart +
  421. " " +
  422. this.storyActionStatus +
  423. " " +
  424. Math.max(...(data.data as number[]))
  425. )
  426. this.processCtr.doneProcessing()
  427. }
  428. }
  429. //处理收到被选项事件
  430. handleVoteResul(data: any) {
  431. if (this.realStart) {
  432. this.modifyHp = data.data.modifyHp
  433. for (let i = 0; i < 4; i++) {
  434. if (this.options[i].content == data.data.content) {
  435. this.selectedOptionNum = i
  436. }
  437. }
  438. if (this.storyActionStatus === 1) {
  439. this.optionsAppearAction()
  440. } else {
  441. console.log("handleVoteResul处理失败" + " storyActionStatus" + this.storyActionStatus)
  442. }
  443. } else {
  444. console.log("handleVoteResul未处理")
  445. this.processCtr.doneProcessing()
  446. }
  447. }
  448. //处理新玩家加入
  449. handleNewPlayer(data: any) {
  450. this.player.push(data.data)
  451. let playerIndex = this.player.length - 1
  452. if (playerIndex === 8) {
  453. return
  454. }
  455. const rolePannelName: string = "role_icon_player" + (playerIndex + 1)
  456. const role: Node = this.roleCtr.node.getChildByName(rolePannelName)
  457. role.active = true
  458. console.log("new player@!!!!!!:" + data.data)
  459. this.roleCtr.newPlayer(role, this.player[playerIndex])
  460. this.roleNodes[data.data.name] = role
  461. console.log("handleNewPlayer处理完成处理下一个")
  462. this.processCtr.doneProcessing()
  463. }
  464. //单独处理死亡
  465. handleDeath(data: any) {
  466. this.roleCtr.deathNodes = data.data
  467. this.processCtr.doneProcessing()
  468. }
  469. //处理收到state时间:如果realStart == false ,则更新游戏初始状态
  470. handleStateResul(data: any) {
  471. if (!this.realStart) {
  472. console.log("处理开始前的status")
  473. this.historyInfo.push(data.data)
  474. this.updateGame(this.gameInfo, this.historyInfo)
  475. console.log("handleStateResul处理完成处理下一个")
  476. this.processCtr.doneProcessing()
  477. } else {
  478. console.log("处理开始后的status完成,处理下一个")
  479. this.processCtr.doneProcessing()
  480. }
  481. }
  482. //处理重置
  483. handleReset(data: any) {
  484. //director.reset()
  485. console.log("处理重置消息")
  486. this.roleCtr.dealDeath(this.roleNodes)
  487. this.scheduleOnce(() => {
  488. director.loadScene("game")
  489. }, 5)
  490. this.processCtr.doneProcessing()
  491. }
  492. //处理所有剧情、选项的移动逻辑
  493. optionsAppearAction() {
  494. console.log("storyActionStatus:" + this.storyActionStatus)
  495. //展示选项,折叠剧情,开启投票统计
  496. if (this.storyActionStatus == 0) {
  497. const storyNode = this.storyPannelCtr.node
  498. const storyUI = storyNode.getComponent(UITransform)
  499. if (storyUI.height > this.storyHeight) {
  500. this.initStoryPosition = storyNode.position.clone()
  501. tween(this.storyPannelCtr.node)
  502. .by(0.5, { position: new Vec3(0, storyUI.height - this.storyHeight, 0) })
  503. .call(() => {
  504. this.optionsCtr.setOptions(this.optionsLabel, this)
  505. //此处需要额外处理死亡,因为前一步有演示播放攻击动画,不排除死亡名单中有攻击后自然死亡角色,最后一个死亡的没啥用,暂没处理
  506. this.roleCtr.dealDeath(this.roleNodes)
  507. })
  508. .start()
  509. } else {
  510. this.optionsCtr.setOptions(this.optionsLabel, this)
  511. }
  512. this.playShowOptionsOneShot()
  513. } else if (this.storyActionStatus === 1) {
  514. //选中备选项
  515. this.optionsCtr.resetVotes()
  516. console.log("selectedOptionNum:" + this.selectedOptionNum)
  517. this.playSelectedOneShot()
  518. this.optionsCtr.selectOption(this.selectedOptionNum + 1, this)
  519. } else if (this.storyActionStatus === 2) {
  520. this.scheduleOnce(() => {
  521. // 隐藏未被选中选项
  522. for (let i = 0; i < 4; i++) {
  523. var optionNode: Node = this.optionsCtr.optionNodes[i]
  524. if (i !== this.selectedOptionNum) {
  525. const optionTween = tween(optionNode.getComponent(UIOpacity))
  526. optionTween.to(2.5, { opacity: 0 }).start()
  527. }
  528. }
  529. //播放移动声音
  530. this.playMoveOneShot()
  531. //隐藏上边剧情面板
  532. tween(this.storyPannelCtr.node.parent.getComponent(UIOpacity))
  533. .to(2.5, { opacity: 0 })
  534. .call(() => {
  535. this.storyPannelCtr.node.getComponent(Label).string = ""
  536. this.storyPannelCtr.node.position = new Vec3(0, 0, 0)
  537. this.initOptionsPosition = this.optionsCtr.node.position.clone()
  538. const storyY = this.storyPannelCtr.node.parent.position.y
  539. const optionsY = this.optionsCtr.node.position.y
  540. const selectedOption = this.optionsCtr.optionNodes[this.selectedOptionNum]
  541. const selectedOptionHeight = selectedOption.getComponent(UITransform).contentSize.height
  542. //选中选项上移
  543. tween(this.optionsCtr.node)
  544. .by(1.5, {
  545. position: new Vec3(
  546. 0,
  547. storyY - optionsY - selectedOption.position.y - selectedOptionHeight / 2,
  548. 0
  549. )
  550. })
  551. .call(() => {
  552. this.storyPannelCtr.node.parent.getComponent(UIOpacity).opacity = 255
  553. //剧情面板在下方出现并开始展示
  554. tween(this.storyPannelCtr.node)
  555. .by(0.01, { position: new Vec3(0, -selectedOptionHeight, 0) })
  556. .call(() => {
  557. this.storyPannelCtr.isOnProcess = true
  558. this.storyPannelCtr.updateStory(this.storyPannelCtr.storyContent)
  559. this.storyActionStatus = 3
  560. //延时触发扣血加血动画
  561. this.scheduleOnce(() => {
  562. this.updateHp()
  563. }, 2)
  564. })
  565. .start()
  566. })
  567. .start()
  568. })
  569. .start()
  570. }, 2)
  571. } else if (this.storyActionStatus == 3) {
  572. const selectedOption = this.optionsCtr.optionNodes[this.selectedOptionNum]
  573. //顶部备选项消失
  574. tween(selectedOption.getComponent(UIOpacity))
  575. .to(0.5, { opacity: 1 })
  576. .call(() => {
  577. //重置选项位置与透明度
  578. this.optionsCtr.node.position = this.initOptionsPosition
  579. // 这是被选中的选项
  580. selectedOption.getChildByName("text_option").getComponent(Label).color = Color.WHITE
  581. // 移除选中背景图
  582. const spriteComponent = selectedOption.getComponent(Sprite)
  583. if (spriteComponent) {
  584. spriteComponent.spriteFrame = this.optionsCtr.notSelectedSprite.spriteFrame
  585. }
  586. //剧情上移开始展示
  587. tween(this.storyPannelCtr.node)
  588. .to(0.2, { position: new Vec3(0, 0, 0) })
  589. .call(() => {
  590. this.storyActionStatus = 0
  591. this.optionsAppearAction()
  592. // console.log("剧情上移处理完成,处理下一个")
  593. // this.processCtr.doneProcessing()
  594. })
  595. .start()
  596. })
  597. .start()
  598. }
  599. }
  600. addHistoryQueue(historyInfo) {
  601. if (this.gameLine < historyInfo.length) {
  602. let nowHistory = historyInfo[this.gameLine]
  603. if (this.gameLine > 0) {
  604. let date1 = new Date(historyInfo[this.gameLine].date).getDate()
  605. let date2 = new Date(historyInfo[this.gameLine - 1].date).getDate()
  606. console.log(date1)
  607. console.log(date2)
  608. let evetsimgs = ["evening"]
  609. if (
  610. date1 !== date2 ||
  611. evetsimgs.indexOf(historyInfo[this.gameLine].time) !==
  612. evetsimgs.indexOf(historyInfo[this.gameLine - 1].time)
  613. ) {
  614. this.processCtr.messageQueue.push({
  615. type: "timeChange",
  616. data: {
  617. time: nowHistory.time,
  618. date: nowHistory.date
  619. }
  620. })
  621. }
  622. if (historyInfo[this.gameLine].charactors.length > historyInfo[this.gameLine - 1].charactors.length) {
  623. let playerNames = this.player.map((item) => {
  624. return item.name
  625. })
  626. let newCharactor = historyInfo[this.gameLine].charactors.forEach((item) => {
  627. if (playerNames.indexOf(item.name) === -1) {
  628. this.processCtr.messageQueue.push({
  629. type: "newCharactor",
  630. data: item
  631. })
  632. }
  633. })
  634. }
  635. }
  636. if (nowHistory.plot) {
  637. this.processCtr.messageQueue.push({
  638. type: "plot",
  639. data: nowHistory.plot
  640. })
  641. }
  642. if (nowHistory.options && nowHistory.options.length > 0) {
  643. this.processCtr.messageQueue.push({
  644. type: "options",
  645. data: nowHistory.options
  646. })
  647. }
  648. if (nowHistory.choice) {
  649. this.processCtr.messageQueue.push({
  650. type: "voteResult",
  651. data: nowHistory.choice
  652. })
  653. }
  654. this.gameLine++
  655. this.addHistoryQueue(historyInfo)
  656. } else {
  657. this.processCtr.doneProcessing()
  658. }
  659. }
  660. updateGame(gameInfo: any, historyInfo: any[]) {
  661. if (gameInfo && history) {
  662. const firstHistory = historyInfo[0]
  663. const nowHistory = historyInfo[this.gameLine]
  664. const lastHistory = historyInfo[historyInfo.length - 1]
  665. let charactors: any[] = lastHistory.charactors
  666. //初始化剧情!!!
  667. //触发剧情框文字
  668. if (this.storyPannelCtr && this.gameStatus !== "finished") {
  669. this.storyPannelCtr.initStory(lastHistory.plot)
  670. } else {
  671. console.log("plot error")
  672. }
  673. if (this.gameStatus === "finished") {
  674. charactors = firstHistory.charactors
  675. this.updateDateByHistory(historyInfo[0], firstHistory)
  676. } else {
  677. this.updateDateByHistory(historyInfo[0], historyInfo[historyInfo.length - 1])
  678. }
  679. //初始化角色!!!
  680. this.player = []
  681. this.npc = []
  682. this.roleNodes = {}
  683. for (let i = 0; i < charactors.length; i++) {
  684. if (charactors[i].danmuUserId) {
  685. this.player.push(charactors[i])
  686. } else {
  687. this.npc.push(charactors[i])
  688. }
  689. }
  690. for (let i = 0; i < this.npc.length; i++) {
  691. const rolePannelName: string = "role_icon_npc" + (i + 1)
  692. console.log(rolePannelName)
  693. const role: Node = this.roleCtr.node.getChildByName(rolePannelName)
  694. role.active = true
  695. this.roleCtr.newPlayer(role, this.npc[i])
  696. this.roleNodes[this.npc[i].name] = role
  697. }
  698. for (let i = 0; i < this.player.length; i++) {
  699. const rolePannelName: string = "role_icon_player" + (i + 1)
  700. const role: Node = this.roleCtr.node.getChildByName(rolePannelName)
  701. role.active = true
  702. this.roleCtr.newPlayer(role, this.player[i])
  703. this.roleNodes[this.player[i].name] = role
  704. }
  705. } else {
  706. throw new Error("gameInfo or historyInfo is null")
  707. }
  708. }
  709. //更新日期
  710. updateDateByHistory(firstHistory: any, lastHistory: any) {
  711. //初始化标题与天数!!!
  712. const time: string = lastHistory.time
  713. if (time === "evening") {
  714. this.sunIsUp = false
  715. this.exchangeTime()
  716. }
  717. this.titlePannel.getChildByName("text_title").getComponent(Label).string = this.gameInfo.name
  718. this.titlePannel.getChildByName("text_gameNo").getComponent(Label).string = "No." + (this.resetNum + 1)
  719. // 计算日期差(结果单位为毫秒)
  720. const lastHistoryDate = new Date(lastHistory.date)
  721. const firstHistoryDate = new Date(firstHistory.date)
  722. const differenceInMilliseconds = lastHistoryDate.getTime() - firstHistoryDate.getTime()
  723. // 将毫秒转为天数
  724. const differenceInDays = differenceInMilliseconds / (1000 * 60 * 60 * 24) + 1
  725. this.dayLabel.string = "第" + differenceInDays + "天"
  726. this.currentDay = differenceInDays
  727. }
  728. updateDateByWS(data: any) {
  729. const time: string = data.data.time
  730. if (time === "evening") {
  731. this.sunIsUp = false
  732. this.exchangeTime()
  733. } else {
  734. this.sunIsUp = true
  735. this.exchangeTime()
  736. }
  737. this.titlePannel.getChildByName("text_title").getComponent(Label).string = this.gameInfo.name
  738. this.titlePannel.getChildByName("text_gameNo").getComponent(Label).string = "No." + (this.resetNum + 1)
  739. // 计算日期差(结果单位为毫秒)
  740. const lastHistoryDate = new Date(data.data.date)
  741. const firstHistoryDate = new Date(this.historyInfo[0].date)
  742. console.log(lastHistoryDate)
  743. console.log(firstHistoryDate)
  744. const differenceInMilliseconds = lastHistoryDate.getTime() - firstHistoryDate.getTime()
  745. // 将毫秒转为天数
  746. const differenceInDays = differenceInMilliseconds / (1000 * 60 * 60 * 24) + 1
  747. this.dayLabel.string = "第" + differenceInDays + "天"
  748. this.currentDay = differenceInDays
  749. console.log("更新日期处理完成,处理下一个")
  750. this.processCtr.doneProcessing()
  751. }
  752. exchangeTime() {
  753. if (this.sunIsUp) {
  754. this.MoonAnim.play("moonUp")
  755. this.MoonAnim.on(Animation.EventType.FINISHED, () => {
  756. this.SunAnim.play("sunDown")
  757. this.MoonAnim.off(Animation.EventType.FINISHED)
  758. })
  759. this.sunIsUp = false
  760. } else {
  761. this.SunAnim.play("sunUp")
  762. this.SunAnim.on(
  763. Animation.EventType.FINISHED,
  764. () => {
  765. this.MoonAnim.play("moonDown")
  766. this.SunAnim.off(Animation.EventType.FINISHED)
  767. },
  768. this
  769. )
  770. this.sunIsUp = true
  771. }
  772. }
  773. updateHp() {
  774. if (this.modifyHp) {
  775. let changBgm2 = false
  776. for (let i = 0; i < this.modifyHp.length; i++) {
  777. const roleNode: Node = this.roleNodes[this.modifyHp[i].name]
  778. const pbNode: Node = roleNode.getChildByName("progressbar_hp")
  779. const orgHp = pbNode.getComponent(ProgressBar).progress
  780. //已死亡不触发
  781. if (orgHp == 0) {
  782. continue
  783. }
  784. let _newHp = flatObj.divide(this.modifyHp[i].changeValue, 100)
  785. let newHp = flatObj.add(orgHp, _newHp)
  786. if (newHp <= 0) {
  787. newHp = 0
  788. } else if (newHp > 1) {
  789. newHp = 1
  790. }
  791. pbNode.getComponent(ProgressBar).progress = newHp
  792. console.log("updata HP: name:" + this.modifyHp[i].name + " orgHp:" + orgHp + " newHp:" + newHp)
  793. console.log(pbNode)
  794. if (this.modifyHp[i].changeValue > 0) {
  795. this.roleCtr.treat(roleNode)
  796. } else {
  797. this.roleCtr.attack(roleNode)
  798. //发生战斗,更换BGM
  799. changBgm2 = true
  800. }
  801. }
  802. if (changBgm2 && this.isPlayBgm1) {
  803. this.bg1AudioSource.pause()
  804. this.bg2AudioSource.play()
  805. this.isPlayBgm1 = false
  806. } else if (!changBgm2 && !this.isPlayBgm1) {
  807. this.bg2AudioSource.pause()
  808. this.bg1AudioSource.play()
  809. this.isPlayBgm1 = true
  810. }
  811. }
  812. }
  813. playMoveOneShot() {
  814. this.audioSource.playOneShot(this.moveClip, 0.2)
  815. }
  816. playSelectedOneShot() {
  817. this.audioSource.playOneShot(this.selectedOptionClip, 0.2)
  818. }
  819. playShowOptionsOneShot() {
  820. this.audioSource.playOneShot(this.showOptionsClip, 0.2)
  821. }
  822. }