/** * WorldLand 场景类 * * 初始引导场景,显示空白背景并在用户交互或自动延迟后 * 执行过渡动画切换到下一个场景 */ export default class WorldTime extends Phaser.Scene { /** * 构造函数 * 初始化场景并设置场景键名 * @param {string} sceneKey - 场景键名 */ constructor(sceneKey = 'WorldTime') { super(sceneKey) this.nextScene = 'WorldLand' this.gameTime = 0 // 游戏中的时间戳(单位:秒) // 固定为60秒/分钟,60分钟/小时,24小时/天,30天/月,12月/年 this.minuteSec = 60 this.hourSec = 60 * this.minuteSec this.daySec = 24 * this.hourSec this.monthSec = 30 * this.daySec this.yearSec = 12 * this.monthSec this.lastRealTime = 0 // 上一次更新的现实时间戳(毫秒) this.gameTimeUpdateInterval = 1000/60 // 游戏中的每秒时间更新间隔(毫秒) this.isDay = true // 昼夜状态 this.UIDepth = 100 // UI层级深度,确保在其他元素之上 this.maskDepth = 99 // 黑夜遮罩层级,低于UI层级 } create() { // 设置场景背景颜色为深灰色 this.cameras.main.setBackgroundColor('#999999') this.initInput() // 初始化输入事件 this.initDayNight(this.toGameTime('1999-12-30 23:57:00')) // 初始化时间,白天黑夜状态 } /** * 初始化输入事件 * 监听鼠标点击和键盘按键,触发场景过渡 */ initInput() { // 监听鼠标点击事件,点击后执行场景过渡动画 this.input.on('pointerdown', () => { this.scene.start(this.nextScene); }) // 监听键盘按键事件,按键后执行场景过渡动画 this.input.keyboard.on('keydown', () => { this.scene.start(this.nextScene); }) } /** * 更新游戏时间 * 每帧调用,刷新游戏时间 */ update() { this.updateGameTime() // 更新游戏时间 this.displayTime() // 显示当前游戏时间 this.updateDayNight() // 更新昼夜状态 } /** * 初始化昼夜状态 * 设置初始为白天,添加事件监听切换状态 */ initDayNight(gameTime) { // 初始更新时间戳为当前现实时间,注意不要使用this.time.now,它是Phaser的时间戳,不是现实时间 this.lastRealTime = Date.now() this.isDay = true // 设置初始为白天 this.gameTime = gameTime // 设置游戏初始时间 // 创建时间显示文本 this.timeText = this.add.text( 20, 20, '', { fontSize: '20px', fill: '#ffffff', fontFamily: 'Arial' } ).setScrollFactor(0).setDepth(this.UIDepth) // 固定文本,不随相机移动,UI层级 // 添加黑夜遮罩 this.nightMask = this.add.rectangle( 0, 0, this.cameras.main.width, this.cameras.main.height, 0x000000 ).setOrigin(0, 0).setScrollFactor(0).setDepth(this.maskDepth) // 固定遮罩,不随相机移动,遮罩层级 this.nightMask.alpha = 0 // 初始设置为透明 } /** * 更新游戏时间 * 每帧调用,基于现实时间流逝更新游戏时间 */ updateGameTime() { // 获取当前现实时间戳 const currentRealTime = Date.now() // 计算与上次更新的时间差(毫秒) const deltaRealTime = currentRealTime - this.lastRealTime if (deltaRealTime <= this.gameTimeUpdateInterval) { // 小于更新间隔,不更新时间 return }else { let addSec = deltaRealTime / this.gameTimeUpdateInterval // 计算增加的秒数 this.gameTime += addSec // 更新游戏时间 this.lastRealTime = currentRealTime // 刷新更新时间戳 } } /** * 获取游戏中的日期 * 根据游戏时间戳计算游戏年月日时分秒,格式为YYYY-MM-DD HH:mm:ss */ getGameDate() { // 计算当前时间的年、月、日、时、分、秒 const year = Math.floor(this.gameTime / this.yearSec) const month = Math.floor((this.gameTime % this.yearSec) / this.monthSec)+1 const day = Math.floor((this.gameTime % this.monthSec) / this.daySec)+1 const hour = Math.floor((this.gameTime % this.daySec) / this.hourSec) const minute = Math.floor((this.gameTime % this.hourSec) / this.minuteSec) const second = Math.floor(this.gameTime % this.minuteSec) // 格式化日期字符串 const dateString = `${year}-${month < 10 ? '0' : ''}${month}-${day < 10 ? '0' : ''}${day} ${hour < 10 ? '0' : ''}${hour}:${minute < 10 ? '0' : ''}${minute}:${second < 10 ? '0' : ''}${second}` const formatDate = { year, month, day, hour, minute, second , dateString, } return formatDate } /** * 转换游戏时间字符串为游戏时间戳 * 接收时间字符串,格式为YYYY-MM-DD HH:mm:ss,返回游戏时间戳(单位:秒) */ toGameTime(gameTimeString) { // 解析时间字符串为秒数 const [year, month, day, hour, minute, second] = gameTimeString.split(/[- :]/).map(Number) // 计算游戏时间戳 return year * this.yearSec + (month - 1) * this.monthSec + (day - 1) * this.daySec + hour * this.hourSec + minute * this.minuteSec + second } /** * 显示当前时间 * 每帧调用,更新显示时间 */ displayTime() { const timeString = this.getGameDate().dateString const day = this.isDay ? '白天' : '黑夜' // 更新显示时间 this.timeText.setText(`${day} ${timeString}`) } /** * 更新昼夜状态 * 每帧调用,根据游戏时间切换白天黑夜状态 */ updateDayNight() { const hour = this.getGameDate().hour if (hour >= 6 && hour < 18) { this.isDay = true // 白天:隐藏黑夜遮罩 if (this.nightMask) { this.nightMask.alpha = 0 } }else { this.isDay = false // 黑夜:显示黑夜遮罩 if (this.nightMask) { this.nightMask.alpha = 0.5 } } } }