欢迎访问

游戏时间

游戏时间系统完全指南 | 开发进度追踪

《蛙噻!好摊》采用独特的时间系统,将现实时间与游戏时间相结合。理解游戏时间机制对于合理安排经营策略、把握市场时机至关重要。

时间系统概览

游戏时间与现实时间的换算关系:

现实时间

8
小时

游戏时间

1

时间比例

1:3
倍速
现实时间游戏时间说明
8小时1天完成一个完整的日夜循环
24小时3天约等于游戏内三天
56小时7天完成一个季节周期
224小时(约9天)28天完成一个完整的月周期

日夜循环

每个游戏日分为六个时段,不同时段有不同的经营特点:

子时
丑时
寅卯时
辰巳时
午未时
申时
酉时
戌亥时
深夜
清晨/傍晚
上午
正午
夜晚
时段游戏时间现实时间客流加成
深夜23:00-03:00约40分钟-50%
黎明03:00-07:00约40分钟+20%
上午07:00-11:00约40分钟+30%
正午11:00-15:00约40分钟+10%
傍晚15:00-19:00约40分钟+35%
夜晚19:00-23:00约40分钟+25%

季节系统

游戏内每7个游戏日(约56小时现实时间)为一个季节:

春季

  • 种子、农具需求增加
  • 药材价格下降

夏季

  • 消暑商品热销
  • 防具需求增加

秋季

  • 收获季节,粮食充足
  • 月饼、礼品热销

冬季

  • 保暖用品需求增加
  • 年货采购高峰

离线时间

离线时长收益效率说明
0-4小时100%全额收益
4-8小时80%收益略微下降
8-12小时60%收益明显下降
12-24小时40%收益大幅下降
超过24小时停止不再累积收益

游戏时间系统开发流程

按照以下计划逐步完成开发,完成所有计划即开发成功。

0%

第一阶段:基础时间框架

预计耗时:2-3小时 难度:简单
  • 任务1.1:创建时间管理类 GameTime

    创建 js/game-time.js 文件,定义 GameTime 类,包含基础属性和方法

    class GameTime { constructor() { this.realStartTime = Date.now(); // 现实开始时间 this.gameStartTime = 0; // 游戏开始时间(毫秒) this.timeRatio = 3; // 时间比例:现实1秒 = 游戏3秒 this.paused = false; // 是否暂停 } // 获取当前游戏时间(毫秒) getGameTime() { if (this.paused) return this.gameStartTime; const elapsed = Date.now() - this.realStartTime; return this.gameStartTime + elapsed * this.timeRatio; } // 获取游戏时间详情 getTimeDetails() { const gameTime = this.getGameTime(); return { totalMs: gameTime, day: Math.floor(gameTime / (8 * 60 * 60 * 1000)), // 游戏天数 hour: Math.floor((gameTime % (8 * 60 * 60 * 1000)) / (60 * 60 * 1000 / 3)), minute: Math.floor((gameTime % (60 * 60 * 1000 / 3)) / (60 * 1000 / 3)) }; } }
  • 任务1.2:实现时间换算函数

    现实8小时 = 游戏1天,实现双向换算

    // 现实时间转游戏时间 function realToGame(realMs) { // 现实8小时 = 游戏24小时 // 现实1秒 = 游戏3秒 return realMs * 3; } // 游戏时间转现实时间 function gameToReal(gameMs) { return gameMs / 3; } // 获取游戏内时间(小时:分钟) function getGameClock(gameMs) { const dayMs = 8 * 60 * 60 * 1000; // 现实8小时为一天 const gameDayMs = gameMs % dayMs; const hour = Math.floor(gameDayMs / (dayMs / 24)); const minute = Math.floor((gameDayMs % (dayMs / 24)) / (dayMs / 24 / 60)); return { hour, minute }; }
  • 任务1.3:创建时间显示UI组件

    在页面右上角显示当前游戏时间

    // HTML <div id="game-clock"> <span id="game-day">第1天</span> <span id="game-time">08:00</span> </div> // CSS #game-clock { position: fixed; top: 10px; right: 10px; background: rgba(0,0,0,0.7); color: white; padding: 8px 16px; border-radius: 4px; font-family: monospace; } // JS更新 function updateClock() { const details = gameTime.getTimeDetails(); document.getElementById('game-day').textContent = '第' + (details.day + 1) + '天'; document.getElementById('game-time').textContent = String(details.hour).padStart(2, '0') + ':' + String(details.minute).padStart(2, '0'); } setInterval(updateClock, 1000);

验证方法

打开页面,观察时间显示是否正常跳动,每现实1秒,游戏时间应前进3秒。

第二阶段:日夜循环系统

预计耗时:3-4小时 难度:中等
  • 任务2.1:定义时段数据

    定义六个时段及其属性

    const TIME_PERIODS = [ { name: '深夜', start: 23, end: 3, trafficBonus: -0.5, bgColor: '#1a237e' }, { name: '黎明', start: 3, end: 7, trafficBonus: 0.2, bgColor: '#ff9800' }, { name: '上午', start: 7, end: 11, trafficBonus: 0.3, bgColor: '#ffc107' }, { name: '正午', start: 11, end: 15, trafficBonus: 0.1, bgColor: '#ffeb3b' }, { name: '傍晚', start: 15, end: 19, trafficBonus: 0.35, bgColor: '#e65100' }, { name: '夜晚', start: 19, end: 23, trafficBonus: 0.25, bgColor: '#4a148c' } ]; function getCurrentPeriod(hour) { for (let period of TIME_PERIODS) { if (period.start > period.end) { // 跨午夜时段 if (hour >= period.start || hour < period.end) return period; } else { if (hour >= period.start && hour < period.end) return period; } } return TIME_PERIODS[0]; }
  • 任务2.2:实现时段切换事件

    当时段变化时触发事件

    class GameTime { constructor() { // ... 其他属性 this.currentPeriod = null; this.onPeriodChange = null; // 时段变化回调 } update() { const details = this.getTimeDetails(); const newPeriod = getCurrentPeriod(details.hour); if (this.currentPeriod !== newPeriod) { this.currentPeriod = newPeriod; if (this.onPeriodChange) { this.onPeriodChange(newPeriod); } } } } // 使用示例 gameTime.onPeriodChange = function(period) { console.log('进入' + period.name + '时段'); // 更新UI背景色 document.body.style.backgroundColor = period.bgColor; };
  • 任务2.3:实现客流加成计算

    根据时段返回客流加成

    function getTrafficBonus() { const details = gameTime.getTimeDetails(); const period = getCurrentPeriod(details.hour); return period.trafficBonus; } // 应用客流加成 function calculateCustomerCount(baseCount) { const bonus = getTrafficBonus(); return Math.floor(baseCount * (1 + bonus)); }

验证方法

观察页面背景色是否随时段变化,客流加成是否正确计算。

第三阶段:季节系统

预计耗时:2-3小时 难度:中等
  • 任务3.1:定义季节数据

    四季循环,每7游戏日换季

    const SEASONS = [ { name: '春季', color: '#4caf50', priceModifier: { food: 1.0, medicine: 0.85, equipment: 1.0 } }, { name: '夏季', color: '#ff9800', priceModifier: { food: 1.1, medicine: 1.0, equipment: 1.1 } }, { name: '秋季', color: '#795548', priceModifier: { food: 0.8, medicine: 1.1, equipment: 1.0 } }, { name: '冬季', color: '#2196f3', priceModifier: { food: 1.15, medicine: 1.2, equipment: 1.15 } } ]; const DAYS_PER_SEASON = 7; // 每7个游戏日换季 function getCurrentSeason(gameDay) { const seasonIndex = Math.floor(gameDay / DAYS_PER_SEASON) % 4; return SEASONS[seasonIndex]; }
  • 任务3.2:实现季节价格修正

    根据季节调整商品价格

    function getSeasonalPrice(basePrice, itemType) { const details = gameTime.getTimeDetails(); const season = getCurrentSeason(details.day); const modifier = season.priceModifier[itemType] || 1.0; return Math.floor(basePrice * modifier); }
  • 任务3.3:实现季节变化事件

    换季时触发通知

    class GameTime { constructor() { this.currentSeason = null; this.onSeasonChange = null; } update() { const details = this.getTimeDetails(); const newSeason = getCurrentSeason(details.day); if (this.currentSeason !== newSeason) { this.currentSeason = newSeason; if (this.onSeasonChange) { this.onSeasonChange(newSeason); } } } }

验证方法

模拟时间快速前进,观察季节是否每7天切换一次,价格是否正确调整。

第四阶段:离线时间处理

预计耗时:2-3小时 难度:中等
  • 任务4.1:保存最后在线时间

    使用 localStorage 保存

    function saveLastOnlineTime() { localStorage.setItem('lastOnlineTime', Date.now().toString()); } function loadLastOnlineTime() { const saved = localStorage.getItem('lastOnlineTime'); return saved ? parseInt(saved) : Date.now(); } function calculateOfflineTime() { const lastOnline = loadLastOnlineTime(); const now = Date.now(); return now - lastOnline; }
  • 任务4.2:计算离线收益

    根据离线时长计算收益,最长24小时

    const OFFLINE_EFFICIENCY = [ { maxHours: 4, efficiency: 1.0 }, { maxHours: 8, efficiency: 0.8 }, { maxHours: 12, efficiency: 0.6 }, { maxHours: 24, efficiency: 0.4 } ]; function calculateOfflineEarnings(stall) { const offlineMs = Math.min(calculateOfflineTime(), 24 * 60 * 60 * 1000); const offlineHours = offlineMs / (60 * 60 * 1000); let efficiency = 0.4; for (let tier of OFFLINE_EFFICIENCY) { if (offlineHours <= tier.maxHours) { efficiency = tier.efficiency; break; } } // 计算基础收益 let baseEarnings = 0; stall.listedItems.forEach(item => { const avgSellTime = 2 * 60 * 60 * 1000; // 平均2小时卖出 const expectedSales = offlineMs / avgSellTime; baseEarnings += item.price * expectedSales; }); return Math.floor(baseEarnings * efficiency); }
  • 任务4.3:显示离线结算界面

    玩家上线时显示离线收益

    function showOfflineSummary() { const offlineTime = calculateOfflineTime(); if (offlineTime < 5 * 60 * 1000) return; // 少于5分钟不显示 const earnings = calculateOfflineEarnings(player.currentStall); // 显示弹窗 const modal = document.createElement('div'); modal.className = 'offline-modal'; modal.innerHTML = ` <h2>欢迎回来!</h2> <p>您离线了 ${formatTime(offlineTime)}</p> <p>离线收益:${earnings} 文</p> <button onclick="this.parentElement.remove()">领取</button> `; document.body.appendChild(modal); // 发放收益 player.money += earnings; }

验证方法

关闭页面后等待几分钟重新打开,检查是否正确显示离线收益。

第五阶段:定时事件系统

预计耗时:2-3小时 难度:中等
  • 任务5.1:定义定时事件

    每日事件和周期性事件

    const DAILY_EVENTS = [ { name: '早市刷新', gameHour: 5, action: 'refreshMarket' }, { name: '商会任务', gameHour: 0, action: 'refreshQuests' } ]; const PERIODIC_EVENTS = [ { name: '集市大集', interval: 7, unit: 'days', action: 'startFair' }, { name: '季节更替', interval: 7, unit: 'days', action: 'changeSeason' }, { name: '物价重置', interval: 28, unit: 'days', action: 'resetPrices' } ];
  • 任务5.2:实现事件调度器

    检查并触发事件

    class EventScheduler { constructor(gameTime) { this.gameTime = gameTime; this.lastCheckedDay = -1; this.lastCheckedHour = -1; } check() { const details = this.gameTime.getTimeDetails(); // 检查每日事件 if (details.hour !== this.lastCheckedHour) { this.lastCheckedHour = details.hour; DAILY_EVENTS.forEach(event => { if (event.gameHour === details.hour) { this.triggerEvent(event); } }); } // 检查周期性事件 if (details.day !== this.lastCheckedDay) { this.lastCheckedDay = details.day; PERIODIC_EVENTS.forEach(event => { if (details.day % event.interval === 0) { this.triggerEvent(event); } }); } } triggerEvent(event) { console.log('触发事件:' + event.name); // 根据event.action执行对应逻辑 } }
  • 任务5.3:集成到游戏循环

    每秒检查事件

    const scheduler = new EventScheduler(gameTime); function gameLoop() { gameTime.update(); scheduler.check(); updateClock(); } setInterval(gameLoop, 1000);

验证方法

模拟时间快速前进,观察事件是否在正确时间触发。

第六阶段:数据持久化

预计耗时:1-2小时 难度:简单
  • 任务6.1:保存游戏时间状态

    保存到 localStorage

    function saveGameTime() { const data = { realStartTime: gameTime.realStartTime, gameStartTime: gameTime.gameStartTime, paused: gameTime.paused }; localStorage.setItem('gameTime', JSON.stringify(data)); } function loadGameTime() { const saved = localStorage.getItem('gameTime'); if (saved) { const data = JSON.parse(saved); gameTime.realStartTime = data.realStartTime; gameTime.gameStartTime = data.gameStartTime; gameTime.paused = data.paused; } } // 页面关闭时保存 window.addEventListener('beforeunload', saveGameTime); // 页面加载时恢复 window.addEventListener('load', loadGameTime);
  • 任务6.2:实现时间加速(调试用)

    开发调试时可加速时间

    // 调试模式下加速时间 const DEBUG_MODE = true; const DEBUG_SPEED = 60; // 60倍速 class GameTime { constructor() { this.timeRatio = DEBUG_MODE ? 3 * DEBUG_SPEED : 3; } }

验证方法

刷新页面后检查时间是否继续,不会重置。

完成清单

完成以下所有任务即表示游戏时间系统开发成功:

阶段任务数状态
第一阶段:基础时间框架3待完成
第二阶段:日夜循环系统3待完成
第三阶段:季节系统3待完成
第四阶段:离线时间处理3待完成
第五阶段:定时事件系统3待完成
第六阶段:数据持久化2待完成
总计170/17 完成

开发提示

  • 建议按顺序完成各阶段,后续阶段依赖前面的基础
  • 每完成一个任务,在代码中标记为已完成
  • 使用调试模式快速验证时间相关功能
  • 注意处理跨午夜的时间计算