Phaser 每日签到日历:连续天数、补签、时区和奖励预览要可信

讲解 Phaser 每日签到系统的客户端实现,包括日历展示、连续签到、补签、时区边界、奖励状态和失败恢复。

为什么这个系统不能临时拼

玩家每天打开游戏看到签到日历,连续 7 天有大奖,漏签可以用补签券补一次,月底活动自动结算。

真实项目里,最容易出问题的不是第一版能不能跑,而是后续能不能解释、能不能复现、能不能被内容团队稳定使用。签到看似简单,但时区、跨天、补签、奖励预览和重复领取都会出问题;本地时间不能作为权威。 这类系统一旦和奖励、存档、关卡进度或玩家输入有关,就不能只写在某个 Scene 的按钮回调里。更稳的做法是把规则层、表现层和调试层拆开:规则层只处理数据和状态,表现层负责 Phaser 动画、粒子、音效和 UI,调试层负责把中间状态暴露出来。

本文按一个可上线的小型系统来拆。它不追求一次覆盖所有商业项目的复杂度,而是把边界先立住:哪些数据进入模型,哪些事件触发表现,哪些失败可以恢复,哪些日志能帮助线上排查。只要这些边界清楚,后续加活动、加难度、加皮肤或加服务端同步,都不会把系统推倒重写。

核心架构

flowchart TD
  A["输入:玩家每天打开游戏看到签到日历,连续 7 天有大奖,漏签可以用补签券补一次,月底活动自动结算。"] --> B["ServerClock"]
  B --> C["CalendarResolver"]
  C --> D["StreakModel"]
  D --> E["ClaimService"]
  E --> F["LoginRewardView"]
  F --> G["Phaser 表现层:动画、UI、音效"]
  G --> H["调试与日志:复现、校验、上线观察"]

这个结构的重点是单向流动。玩法对象向系统提交意图或事件,核心系统计算结果,Phaser 层根据结果播放反馈。不要让 Sprite 的动画进度、按钮显示状态或粒子是否存在反过来决定规则。只要规则是纯数据,就能测试、回放、存档和迁移。

签到以服务器日期为准

客户端可以显示倒计时,但今天是哪一天应来自服务器时间或可信偏移。玩家本地改时间不应提前领奖。跨时区产品要明确按 UTC、服务器区还是玩家区。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

连续天数和累计天数不同

连续签到用于 streak,累计签到用于月奖励。漏一天会断连续,但累计不应清零。UI 要分别展示,否则玩家会误解。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

补签是正式交易

补签消耗补签券或货币,目标日期必须可补,奖励必须和当日配置一致。补签成功和普通领取一样要幂等。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

奖励预览要来自配置

日历格子显示未来奖励,但实际领取仍以服务端配置版本为准。活动配置变更时,要保护已经展示且可领取的奖励,避免玩家看到 A 领到 B。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

跨天刷新要平滑

玩家停在签到页跨过 0 点,状态应刷新但不能重复弹窗。可以提示“新的一天已开始”,让玩家手动领取。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

失败恢复

领取请求超时后不要本地标记已领。下次打开重新拉状态。若服务端已成功,客户端同步为已领并播放补偿式反馈。

在实现时,建议把这部分写成可以单独调用的服务或 resolver。Scene 只把当前上下文传进去,再根据返回结果更新画面。这样不仅便于测试,也能让调试面板复用同一套计算结果。若这部分逻辑未来需要服务端复算,迁移成本也会低很多。

TypeScript 实现骨架

interface DayReward { day: string; claimed: boolean; missed: boolean }

export function resolveClaimState(day: DayReward, today: string) {
  if (day.claimed) return "claimed";
  if (day.day === today) return "claimable";
  if (day.missed) return "makeup";
  return day.day < today ? "missed" : "locked";
}

这段代码只展示核心判断,不直接创建 Phaser 对象。实际项目里,你可以在 Scene 中把输入、时间、对象状态整理成快照,再交给这个函数或类。返回值用于驱动动画、音效和 UI,而不是让 UI 自己猜发生了什么。这样写的好处是很直接的:你可以为它写单元测试,也可以在调试面板里把输入和输出打印出来。

数据结构和配置边界

配置要尽量表达设计意图,而不是暴露太多底层实现细节。内容团队更关心“这个节点需要什么条件”“这个阶段持续多久”“这个奖励来自哪里”,不应该被迫理解 Phaser 的坐标、Tween 名称或对象池实现。底层字段可以存在,但要由工具生成或校验。

每份配置都应该有版本。只要系统会进入存档、奖励、关卡成绩或玩家长期进度,就不能假设配置永远不变。版本号能帮助你判断旧数据如何迁移,日志如何解释,客服如何复现。配置更新后,旧玩家的状态要么安全迁移,要么明确补偿或重置,不能静默损坏。

UI 和玩家反馈

玩家不需要看到所有内部数字,但必须理解关键结果。按钮为什么灰掉,失败为什么发生,奖励为什么没有到账,系统为什么选择了这个目标,这些都要有可见反馈。反馈可以很轻:一行原因、一个高亮、一个短音效、一个图标状态。比起华丽动画,可信的解释更能减少挫败。

移动端尤其要注意误触和信息密度。交互区域要足够大,状态变化不要只靠颜色,关键提示不要被刘海屏、虚拟摇杆或系统手势挡住。桌面端则要考虑键盘、鼠标、手柄和窗口失焦。Phaser 能同时覆盖很多平台,系统设计不能只按开发机体验来定。

调试工具

这个系统至少需要一个开发模式面板,显示当前状态、最近事件、配置版本和失败原因。调试面板不是奢侈品,而是内容生产工具。没有它,设计师只能通过反复试玩猜测系统为什么不工作;有了它,问题会变成可讨论的事实。

日志也要分层。开发环境可以详细记录每一步,正式环境只记录关键事件、异常和玩家失败前后的上下文。日志字段要稳定,不要只输出一段中文字符串。结构化日志能被脚本分析,也能帮助客服和运营复现问题。

上线前检查清单

  • 日期来自 ServerClock
  • 连续和累计分开
  • 补签幂等
  • 奖励配置有版本
  • 跨天自动刷新
  • 失败不会丢奖励
  • 配置有版本,旧数据有迁移或回退策略
  • UI 能解释失败原因和当前状态
  • 关键操作有幂等保护,重复点击不会造成重复收益或重复扣费
  • 低端设备有降级方案,不改变核心规则
  • 调试面板能显示最近事件和当前计算结果

常见坑

第一,把表现当规则。动画没播完就不结算、粒子存在就算命中、按钮亮着就允许领奖,这些都会在暂停、跳过、切后台或弱网时出问题。

第二,只有成功路径。真实玩家会取消、重试、断网、切场景、连点、误触、读旧存档。每一个关键状态都要有失败恢复和安全回退。

第三,配置无校验。内容越多,拼写错误、引用缺失、数值越界越常见。启动时或导出时做校验,能拦住大量线上事故。

第四,缺少版本意识。只要系统会被存档、回放、排行榜、奖励或活动引用,就必须知道当时使用的是哪一版配置。

收束

这个 Phaser 每日签到日历:连续天数、补签、时区和奖励预览要可信,真正难点不在于 Phaser API 本身,而在于规则能否被长期维护。把核心计算从 Scene 中拿出来,把配置、状态、表现和日志分清楚,系统就会从“能演示”变成“能上线”。这也是 Phaser 做中小型 Web 游戏时最值得坚持的工程习惯:用轻量工具快速表现,用清晰模型守住规则。

月历、循环和新玩家补齐

签到可以按自然月,也可以按 7 日循环。自然月适合运营活动,循环适合新玩家随时加入。若 3 月 20 日新玩家进入自然月签到,前 19 天是否显示错过?是否能补签?这些规则要明确。循环签到则每个玩家有自己的第 1 天,运营统计更简单但节日感弱。

客户端 UI 要根据活动类型展示。自然月用日历格,循环签到用进度条或 7 日卡片。不要用同一个 UI 硬套所有规则。玩家一眼要知道自己今天能领什么、连续奖励还差几天、错过的是否能补。

奖励动画和背包容量

签到奖励可能包含货币、道具、皮肤、抽奖券。领取前要检查背包容量或让奖励进入邮箱。若容量不足,不要把签到标记为已领。领取成功后,奖励动画可以合并展示,不要十个道具飞十次。若奖励进入邮箱,签到页要显示“已发送至邮箱”,避免玩家以为没到账。

签到页常在启动时弹出,但不要每次都强弹。今天已领后,再进大厅不应继续打扰。玩家可以从活动入口重新打开。弹窗频率控制比动画华丽更重要。

时区和夏令时边界

签到最容易在跨天边界出问题。若产品按 Asia/Shanghai 计算,海外玩家也应看到明确倒计时。若按玩家本地时区计算,玩家旅行或系统时区变化时要有策略。夏令时地区会出现一天 23 或 25 小时,不能简单按 24 小时毫秒数判断连续天数。使用服务器给出的 dateKey 更稳。

客户端内部不要用本地 Date 直接拼今天字符串。ServerClock 返回当前活动 dateKey、下一次刷新时间和时区说明。UI 展示倒计时,领取请求提交 dateKey。这样跨天、补签和客服排查都有共同语言。

补签的产品边界

补签可以挽回漏签,但不能让连续奖励完全失去意义。可以限制每周期补签次数、只允许补最近几天、补签不恢复最高连续奖励,或者消耗补签券。规则要提前写在 UI 中。玩家点击补签前,应看到会获得什么、是否恢复连续、消耗什么。

补签失败常见原因包括日期不可补、补签券不足、活动已结束、奖励配置变化。每种失败都要有独立文案,而不是统一“操作失败”。

签到和启动流程

签到弹窗不要阻塞首屏加载。可以先进入大厅,再以轻量弹窗提示今日可领。若玩家正在战斗回流,不应立刻弹签到。启动流程要区分强制公告、登录奖励和普通活动入口,优先级不清会让玩家刚进游戏就被弹窗淹没。

客服排查字段

签到日志应包含 dateKey、rewardId、claimId、serverNow、streakBefore、streakAfter 和 configVersion。玩家反馈漏签时,这些字段比截图更有用。

月末边界也要测试。3 月 31 日领取后,4 月 1 日应进入新周期,旧奖励不应继续可领。若活动跨月,dateKey 和活动周期要分开,避免自然月切换误伤长期签到。

如果签到奖励包含外观或限定道具,错过后的获取方式也要说明。绝版、返场、补签可得三种规则会影响玩家预期,不能藏在活动说明角落。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页