做了一个「占领城市」的行走游戏,聊聊 CoreLocation + 像素格的实现思路

5 阅读6分钟

这个 App 是什么

我做了一个把真实行走变成像素领地占领的 iOS 游戏,叫「像素征途」。简单说就是:你出门走路,地图上经过的区域会被你的像素格"点亮",走得越多,占领的版图越大。

起因是觉得市面上运动类 App 的激励方式太单一了——步数、卡路里、公里数,这些数字对我来说已经完全没感觉。去年玩了一阵「世界迷雾」,觉得「点亮地图」这个概念有意思,但游戏感不够。我就想:加上等级、连击、每日任务,会不会更让人上瘾?

有用户评论说"和世界迷雾一样好玩,解锁成就",也有人吐槽图标太像游戏——嗯,它本来就是个游戏。

核心玩法:8×8 的区域征服

地图被切成一个个 zone,每个 zone 内部是 8×8 = 64 个像素格。走过的路线会点亮对应格子,点亮够多,zone 就算被「征服」了。

enum TerritoryRules {
    static let zoneSideCount = 8
    static let zonePerfectTileThreshold = zoneSideCount * zoneSideCount // 64
    static let zoneConqueredTileThreshold = 58
}

58/64 算征服,64/64 算完美占领。为什么是 58?因为实际走路时,zone 边角格子你很难精确踩到——可能在河里,可能在建筑物里。90% 的阈值体验好很多。这个数字调了好几次,最早 48 太容易没挑战感,62 又太苛刻,58 是反复测出来的甜点。

连击系统和每日贡献上限

为了让用户有动力连续出门,做了连续天数倍率:

enum RouteScoreRules {
    static let dailyContributionCap = 50
    static let graceDays = 1

    static func multiplier(for consecutiveDays: Int) -> Double {
        switch max(0, consecutiveDays) {
        case 5...:  return 2.0
        case 3...4: return 1.5
        default:    return 1.0
        }
    }
}

连续走 3 天 ×1.5,5 天以上 ×2.0。同时每天 50 点贡献上限——防止有人开着 GPS 漂移刷分,倍率奖励的是真正每天出门的人。

graceDays = 1 这个设计纠结了挺久。最早没有宽限期,结果自己测试时周末宅了一天,连击直接归零,说实话有点难受。加了一天宽限后舒服多了。严格连续打卡的设计反人性,下雨天谁也不想出门。

每日任务的四个维度

游戏化光靠地图不够,得有短期目标。四种任务类型:

  • unlock:今天点亮 N 个新格子
  • distance:今天走够 N 米
  • duration:今天探索时长 N 分钟
  • momentum:维持连击天数

任务完成给碎片奖励,碎片解锁地图皮肤。我试过更复杂的设计,比如"在特定区域解锁 X 个格子"、"一次行走不中断 30 分钟",最后全砍了。独立开发资源有限,与其做 10 种半成品,不如把 4 种做扎实。

热力衰减:让地图「活」起来

这是我觉得比较有意思的设计。走过的路线不会永远高亮,会随时间衰减:路线发光 4 天后开始柔和变暗,7 天后明显衰减,zone 强调效果 14 天消退,格子残留 30 天后降到 12% 不透明度。

效果就是:最近去过的地方亮,很久没去的地方暗下来。就像一张「活的」城市记忆——你能一眼看出最近的活动范围,也能看到几周前的足迹像老照片一样褪色。

这个决定犹豫了很久。「世界迷雾」那种永久点亮更让人安心,辛苦走出来的不会消失。但衰减能制造一种"得回去看看"的动力,有点像种菜游戏要定期浇水。当然,格子本身是永久解锁的,衰减的只是视觉热力亮度。这个区别得在 UI 上表达清楚,否则用户会觉得努力白费了。

格子循环:走老路也有意义

很多地图探索 App 有个问题:走过的地方就没有再去的动力。我做了 tile loop 机制——每个格子有等级、路线阶层、访问计数和每日产出上限:

struct ActiveTileLoopState {
    let tileKey: String
    let level: Int
    let levelTitle: String
    let roadTier: TileRoadTier
    let visitCount: Int
    let todayVisitCount: Int
    let todayYieldClaims: Int
    let todayYieldClaimCap: Int
    let nextYieldInVisits: Int
    let cooldownSeconds: Int
    // ...
}

说白了:你通勤每天走同一条路,经过的格子也在「成长」。等级越高产出越多,有冷却时间防止原地刷,有每日领取上限。这样日常通勤不会觉得无聊,老路线也有持续回报。

默认坐标的小细节

很小的事,但挺能体现独立开发心态的。GPS 还没定位到时地图默认显示哪里?我根据系统地区来选——中国显示上海陆家嘴,日本显示东京站,美国显示旧金山。

花了不到 20 分钟,但对第一次打开 App 的体验影响挺大。比起看到经纬度 (0,0) 的非洲海岸(经典坑),看到自己城市附近的地图,用户更愿意继续操作。

下载量是零,我准备怎么办

说实话,最近 7 天下载量是 0。对,零。

问题我分析了一下,主要两个方面:

ASO 基本没做。"像素征途"这个名字搜索量几乎为零,用户不可能通过搜索找到它。接下来我准备把副标题改成包含"行走"、"地图探索"、"步行游戏"这类关键词,关键词字段补上"世界迷雾"、"城市探索"、"步行打卡"。App Store 的关键词有 100 个字符的限制,得把每个字符都用上。

**冷启动期全在写代码,推广零投入。**之前一直在改功能修 bug,这篇文章算是正式开始做内容推广的第一步。计划是先在技术社区写实现细节,同时在小红书做「城市领地图」的截图内容——后者可能对拉新更直接。

好的一面是,现有用户评价都不错,有人主动要求加功能(探索榜、历史足迹年份放开),说明产品方向没偏,缺的是曝光。

做对了什么,做错了什么

做对的:

  • 衰减机制虽然纠结很久,但确实让地图更有「时间感」
  • 连击 graceDays 是好决定
  • 四种任务类型够用,没有为了丰富度堆功能

做错的:

  • 花了太多时间在地标系统上,但地标数据覆盖率不够,体验不如预期
  • 图标确实太像游戏了,有用户反馈在桌面上看起来不够"正经"——虽然它就是个游戏,但很多人是当运动工具看的
  • ASO 应该在上架第一天就做,而不是写了一个多月代码才想起来

对了,想问问各位做过地图类或者游戏化产品的:你们觉得地图探索的成果应该永久保留,还是像我这样做时间衰减?我到现在还不是 100% 确定这个方向。