地圖鑑 App:技術清單與開發過程

地圖鑑是一款在地圖上認行政區的 iOS 遊戲,前身是「ChiZu 嶼」。這篇整理它用到的技術和開發過程。

基本資料

  • 平台:iPhone / iPad,iOS 17 以上
  • 規模:Swift 42 個檔案、約 1.2 萬行;測試 19 個檔案
  • 內容:40 張卡、289 關,從台灣、日本一路擴充到五大洲
  • 語言:繁中、簡中、英文、日文、韓文

App 端

  • SwiftUI:所有畫面。狀態管理用 Observation(@Observable),沒有另外引入架構框架
  • MapKit:實景盤面用 MKMapView 的衛星影像,透過 UIViewRepresentable 包進 SwiftUI
  • Core Graphics:行政區自己畫在地圖上,不用 MapKit 內建的 overlay renderer(原因見下方「踩過的坑」)
  • Canvas:平滑盤面(不用網路的向量地圖)直接用 SwiftUI Canvas 畫 polygon
  • AVFoundation:8-bit 風格音效
  • String Catalog(.xcstrings):介面多語系,key 直接用繁中原文
  • Firebase Analytics:唯一的第三方套件,用 Swift Package Manager 安裝,用來看各關卡的遊玩與流失
  • PrivacyInfo.xcprivacy:隱私權清單,App Store 要求

資料端

地圖與題庫都打包在 App 內(約 43 MB 的 JSON),不用連網下載。資料由另一個 Laravel 專案產生:

  • Laravel + MySQL:存行政區邊界、層級、譯名,用 artisan 指令跑整條 pipeline
  • Python(shapely):合併幾何,例如把日本政令市底下的區併回一個市
  • OpenCC:日文新字體轉繁中、繁中轉簡中
  • Wikidata:補台灣、日本行政區的多語名稱
  • 保留拓樸的簡化:相鄰行政區的共用邊界只簡化一次,兩邊拿到同一條線,畫出來不會有縫或雙線

圖資來源:

  • 台灣:taiwan-atlas(TopoJSON)
  • 日本:GitHub 上的 TopoJSON
  • 多數國家:Natural Earth 10m
  • 法國:IGN;義大利:ISTAT
  • 印尼:印尼統計局(BPS)的縣界拼成 38 省

開發過程

版本 日期 重點
初版 2026-02 只有日本 47 都道府縣,兩階段點選:先選大區域,再選縣
1.3 2026-03 加台灣;題庫與地圖資料分開;接 Firebase
2.0 2026-09 8-bit 風格改版;新增「填圖闖關」玩法
2.1 2026-09 加韓國、美國;地名多語系
2.2 2026-09 介面五種語言;iPad 截圖腳本
2.3 2026-11 加泰國、歐洲、法德義西、馬來西亞、菲律賓
2.4 2026-11 一次加 28 張卡:亞洲、中東、非洲、中南美、大洋洲與更多歐洲國家

踩過的坑

  • 相鄰行政區之間有細縫:MapKit 一個 polygon 一個 renderer,各自做反鋸齒,邊界會透出底圖。改成一次 pass 畫完所有 polygon
  • 畫面太慢:MapKit 每個 tile 都會叫一次 draw,美國全國視角一個 tile 要 3.5 秒。座標換算只做一次,每個縮放級距快取一份 CGPath,只畫碰到這個 tile 的 polygon,結果降到 0.2 ms
  • 點擊判定不一致:有三個畫面各自寫了一份點擊判定(ray casting),只有一份有處理挖洞的 polygon,實景盤面因此把台北市的點擊算成新北市。最後統一成一份 GeoGeometry
  • 有爭議的領土:國界照聯合國認定,例如西撒哈拉單獨一格、戈蘭高地歸敘利亞

工具

  • Xcode、XCTest
  • Claude Code:寫程式、code review、App Store 截圖與送審資料
  • 自寫腳本:App Store 截圖(simctl 固定狀態列 9:41)、上架文字檢查

下載