まもなく『ポケットモンスター スカーレット・バイオレット』が発売しますが、先日、iPhone/iPad/Mac向けのポケモンパーティー構築管理アプリ、『PokeBox』をリリースしました。
ポケモンパーティー構築アプリの「PokeBox」をバージョン1.1にアップデートしました。ポケモン新規作成時の挙動改善や、わざ周りのインターフェイスがわかりやすくなっています。SV対応もしていくぞ https://t.co/p8E1GjvCeq pic.twitter.com/kbzDw885WY
— giginet (@giginet) October 16, 2022
『ポケモン剣盾』以来、ランクマッチなど、いわゆるポケモンガチ対戦にハマり、自分の需要から開発したアプリです。
『剣盾』環境では、100体近いポケモンを育成し、努力値振りや構築意図などを、秘伝のスプレッドシートで管理していましたが、あまりにも煩雑なので、ちゃんと管理できるアプリを作ろうと思いつつ、この度ようやっと開発できました。
今のところ『剣盾』での利用を想定しています。今更『剣盾』を遊んでいる人は面構えが違う廃人ばかりだと思いますが『SV』のリリース後も末永く使っていただけると幸いです。(SVでシステムが大きく変わらないことを願うばかり!)
ご意見、ご感想、機能要望はTwitterにてお待ちしてます。
特に耐久調整などあまり考えて構築できてないので、本当のガチ勢の方のユースケースなどぜひ聞きたいです。
主な機能
ポケモンエディタ
パーティーエディタ
OS標準の機能
- iPad対応(要iPadOS 16以上)
- Mac対応(要macOS Ventura以上とM1 Mac)
- 日本語、英語サポート
- ダークモードサポート
- Dynamic Typeサポート
- iCloudサポート
今後の機能追加予定
- 『ポケモンSV』サポート(新ポケモン・わざ・とくせい・もちもの、テラスタイプ)
- さらなる入力支援(最硬調整、HP調整など)
- 構築のタイプチェッカー
- 「ポケモン徹底攻略」のタイプバランスチェッカーに近い機能になりそうです
- 構築シェア機能
技術的な話
このプロジェクト自体、技術的なキャッチアップの目的も大きかったため、語りたいこともたくさんあるのですが、この記事はリリース告知に留め、技術的な注目トピックをざっくりと紹介。
詳しい話はまた他所の勉強会やカンファレンスでできればなと思っています。
ポケモンデータの構造化
この手のアプリで一番頭を悩ますのが、ゲーム内のデータをどのように構造化するかという点です。
既存の構造化されたポケモンデータとして、PokéAPIというデータソースがあります。これは、ポケモンの様々な情報を取得できるWebAPIです。GraphQLなどにも対応しています。
このPokéAPIはオープンソースで開発されていて、実はデータソースもGitHubにあります。
このリポジトリには、大量のCSVと、それらをSQLiteにdumpするPythonスクリプトがあるのですが、長らくメンテされていなかったため、いろいろPRを投げて修正しました。 SQLAlchemyのバージョンを上げたり、Docker上でのdumpをGitHub Action対応したりなどです。
ここまで来ると、あとは全データをRDBとして扱えます。
PokeBoxでは、ここから生成したSQLiteをアプリ内に保持し、SQLを投げています。アプリ容量が大きめなのはそのためです。
『SV』発売後に、この情報ソースが迅速に新仕様に対応できるかは懸念があります。この辺を自給自足できれば良いのですが、現状難しいため、発売後は別のソースも検討しないとならないかもしれません。
また、わざの習得テーブルなど、一部怪しいデータも散見されました。どうぐの細かなパラメータなども、6世代付近の情報で止まっていそうです。
SwiftUI on iOS 16
今回の裏テーマとして「SwiftUIを使って、Appleの推奨するモダンアプリケーションを正しく作る」というところを目指しました。 全てがSwiftUIでできていますし、UIは標準のメールやメモアプリを参考にしています。
業務ではあまりアプリケーションレイヤーを触らないため、長年、SwiftUIについてしっかりキャッチアップできていないという課題感を感じていました。(エアプ)
今回、1本ちゃんと作って、さまざまなハマりを経験したことで、かなり知識のアップデートができたと考えています。 この手のアプリの中では、かなり使い勝手の良いものが作れたのではと。
PokeBoxは、7月頃に開発を始めたため、WWDC 2022で登場した、iOS 16/iPad OS 16の新機能をふんだんに使っています。
What's new in SwiftUI - WWDC22 - Videos - Apple Developer
Layout
エディタ画面のレーダーチャートの実現のため、新しいCompositional Layoutの仕組みを使っています。
Compose custom layouts with SwiftUI - WWDC22 - Videos - Apple Developer
Path
でレンダリングしたグラフに、ZStack
で文字を重ね、Layout
でグラフ上に配置しています。
おかげで任意のサイズで描画できるレーダーチャートが実装できました。
当初はSwift Chartsの採用も考えましたが、試してみたところ、時系列グラフを前提として設計されていて、レーダーチャートの描画には向かなかったので早々に諦めました。
ViewThatFits
ViewThatFits
はiOS 16から登場した新しいViewで、複数の候補のうち、収まりが良いものを自動的に採用してくれる仕組みです。PokeBoxでは、わざの表示に採用しています。
文字数が少ない場合はグリッド表示、多い場合はリスト表示に自動的に切り替わります。これによりiPadで表示しても収まりが良いものとなりました。
Grid/GridRow
Grid
は、表組みのようなものを作る際に、最長の要素の幅に合わせて、自動的にレイアウトしてくれる仕組みです。
PokeBoxでは努力値エディタなどに利用しています。各パラメータについて、ラベルやスライダーの開始位置が揃っていることがわかるかと思います。
NavigationSplitView
NavigationSplitView
は新しいNavigationStackの一種で、これ1つで全プラットフォームに適したナビゲーションを構築できます。
iPadではSplitViewとなり、iPhoneやwatchOSでは、自動的に NavigationStack
のような挙動をします。
これのおかげでワンコードでサイドバー付きのiPad対応が実現しています。
素晴らしい仕組みのように見えて、iPhoneで正しく動かすには、バグが多く悩まされました・・・・・・。β版どころか、16.0になってもバグってるので注意です。
navigationDestination / NavigationPath
navigationDestination
modifierを使うことで、NavigationLink
の遷移先を従来より管理しやすくなりました。
PokeBoxではほとんどの画面遷移に用いています。
The SwiftUI cookbook for navigation - WWDC22 - Videos - Apple Developer
Variants Preview
Xcode 14から、Xcode PreviewをダークモードやDynamic Typeを適応した状態でまとめて閲覧できるようになりました。(なぜ今までなかった)
PokeBoxでは、随所でPreviewを活用してUIを作成していました。またタイプ表示といった、小さなコンポーネントもSwiftUI化できました。
こういったものを作るには非常に向いていますね。
最新の開発機能の活用
iCloudサポート
複数のiOS端末を日常から使っているため、個人的な要求として、デバイス間のデータの同期は外せない仕様でした。
今回はシンプルにデータストレージにはCoreDataを採用。CoreDataは NSPersistentCloudKitContainer
を使うだけで、簡単にマルチデバイス対応することができました。
Using Core Data With CloudKit - WWDC19 - Videos - Apple Developer
CoreDataやNSManagedObject
のAPIは、今の時代には辛かったので、なんとかして欲しいところ・・・・・・。
ローカライズ
i18nも対応しています。実は開発言語は英語で、あとから日本語ローカライズを追加しています。
先ほど紹介したデータベースでは、ポケモンの名前やフレーバーテキストは言語毎に格納されているため、発行するSQLで言語IDを変更することで、簡単にローカライズが実現できました。
英語設定だとこの通り。
StoreKit 2
有料機能のアンロックにはStoreKit 2を利用しています。StoreKit 1は業務で利用していたのですが、2は今回初。あまりの簡単さに涙が止まらなかった・・・・・・。
Meet StoreKit 2 - WWDC21 - Videos - Apple Developer
StoreKit ConfigurationやStoreKit Testingは今回利用していませんが、そのうち試してみたい。
Xcode Cloud
先日からXcode Cloudが利用可能になったので、ユニットテストの実行や、TestFlightの配信に取り込んでみました。
今回のような、プライベートリポジトリでの小規模個人開発にはまさにこれしかないソリューションに感じました。この規模のアプリであれば、pushごとに毎回ユニットテストを回しても無料枠で使えています。
ダンプしたSQLiteの置き場所にGit LFSが必要になり、GitHubへの課金が発生したのはまた別の話。
サブミット自動化
一方で、ストア提出に関してはまだまだfastlaneなど、旧来の手法に分があるように感じました。
metadataの提出が現状、Xcode Cloudだけではできないので、この辺を解決する需要はありそう。
今回はお家芸のdeliverを用いたサブミット自動化*1のほか、snapshotを使ったスクリーンショット撮影自動化にも挑戦しています。
iPadOS/iOS両対応、日英二カ国語対応程度の規模でも、40枚(4枚 * 5機種 * 2カ国語)の撮影が要求されるので、自動化しないとやってられません。
この辺の基盤作りをしっかりしたので、今後の柔軟なバージョンアップにも耐えうると思います。
ちなみに、このアプリ開発のために、iPhone 14 Proサポートを取り込むコミッター業もしました。個人アプリ開発のためにOSSの開発も進むのは良い相乗効果だなと思います。
ぜひダウンロードしてね
手短に書こうと思いつつ、長くなりましたが、良い感じのアプリが作れて大変勉強になりました。 普段UI層をあまり書かないアプリエンジニアなので、「UI作れる人すげーな」という気分。
ポケモンプレイヤーはもちろん、そうじゃない人が触っても楽しいアプリになったと思います。
*1:筆者はfastlaneコミッターです