頭と尻尾はくれてやる!

iOSアプリなどの開発日記です


iOSアプリ、ポケモンGO用「わざタイプ相性表」をリリース

pokegochart_iconR.png
わざタイプ相性表

ポケモンGOに登場するポケモンたちの、わざとポケモンのタイプの相性を調べるアプリです。
レイドバトルでレイドボスに有効なわざを確認したり、GOバトルリーグで「XXXが出てきた時、どのポケモンに交代すれば有利だったのか?」など復習できます。
ポケモンGOで実装されていないポケモンのデータはありません。随時追加していきますので反映されるまで時間がかかります。
このアプリはポケモンGOの一ファンが作成したもので、公式なものではありません。


スクリーンショット

↑アップしたアプリの説明文、スクショがこんな感じ。

アプリ名に「ポケモンGO」という文字列を入れられないのはAppleの規約に従ってる。実際入ってるのがApp Storeには並んでいるのだが、これは審査する人によるんだろう。前のアプリ(個体値カメラ)で「for ポケモンGO」の文字列を入れて申請しリジェクトされてるので、再度やったら何されるかわからない(アカウント剥奪が怖い)ので、今回は大人しく最初からタイトルには「for ポケモンGO」は入れてない。けどアプリ内での表示やlaunch screenには入れてる。


一昨日の夕方に申請し、今朝4時頃に審査開始、通過してた。このアプリは日本語版のみなので審査の時間ってどうなるのかと思ってたがいつも通り朝起きたら審査が終わってた、というパターンだった。


申請直前の段階で最新のデータを入れたにもかかわらず、今朝いきなりポケモンGOにメガシンカが実装され、近所のジムでメガカメックスがレイドに登場してた、、、なるべく早くデータ更新版を申請せねば。


今回のアプリ、当初はGOバトルリーグでリアルタイムで対戦してる時に使えるように、相手のポケモンや自分のチームのポケモンの交代を音声でできるように開発してた。
ところがiOSで使える本家の音声認識(SFSpeechRecognizer等による)はポケモンの名前を聞かせてもそれに近い日本語を探すようになっていた。
なので「カイリキー!」と言っても「怪力」という文字列が返ってくるのだ。
それでは「怪力」だったら「カイリキー」と変換するようにやってみようと、自分の発声で返ってきた単語を片っ端からリストアップし、

変換例

↑こんな感じで変換を実装していたが、、、あまりにもキリがない。音声だけでポケモンを特定するのは無理筋だな、と思い撤退。
ポケモンの選択は普通にキーボードで手入力とし、対戦後に復習したい時に使えるような感じにまとめた。


可能なら英語版も、と思ったもののポケモン名やわざの名称を得られる信頼できそうなサイトが見つからず結局日本語版のみになった。


アプリはportraitでもlandscapeでも可能で、レイアウト切り替えやアニメーション時の移動などはほぼAutoLayoutの制約を書き直してる。だいぶ自分の中では使い慣れてきたなあ、と感じてきたが時代はSwiftUIですか、そうですか、、、


iOSアプリ「個体値カメラ」をリリースしました(ポケモンGO用)

個体値カメラのアイコン
個体値カメラ
↑リリースしました。

このアプリを使うには
ポケモンGOアプリが入っているiOSデバイスと
このアプリを入れた別のiOSデバイス
の2台が必要です。



↑このようにポケモンGOアプリで個体値を表すグラフを表示させ、それをこのアプリのカメラを通して見るとARっぽく個体値(%)を表示します。
当アプリの画面をタップすると画像を保存します。



↑保存した画像はこのようにまとめて見ることができます。


※権利に配慮し動画内ではポケモンGOアプリの画面にはボカシを入れていますが、アプリではそのまま表示されます


ARKitの画像トラッキングにおける画像平面の初期姿勢

ARKitの画像トラッキング(ARImageTrackingConfigurationを使うやつね)で対象の画像を見つけた場合に得られるARAnchorオブジェクト。それをanchorとするとanchor.transformでその位置・姿勢を得ることができる。

これをつかってごにょごにょ(※1)する時なんかにあれ?と思ったのはこのtransformがmatrix_identity_float4x4の状態にはこの平面はx-z平面にある、ということ。
x-y平面にあるものと思ってコード書いててなんかうまくいかねえ?となり気付いたんだが。
ちなみにMDLMeshのnewPlane(withDimensions:segments:geometryType:allocator:)で作成する平面はx-y平面に作成される。うー、なんかややこしいのう。


※1 ↓こういうのをやってたのです。



VRゴーグルに穴をあけたARゴーグルで世界を見る実験

iPhoneのバックカメラを使ったARアプリの検討ということである実験をしてみた。

VRゴーグル

↑だいぶ前に購入したVRゴーグルに、、、

VRゴーグル(穴あけ状態)

↑えいやと穴をあけてiPhoneを設置。そのカメラで得た画像(動画)を

カメラ画像を2つ並べたスクショ

↑このようにならべて見てみるとどんな感じだろうか?というものだ。

通常VRアプリは少し異なる画像を左右それぞれの目で見るわけだが、これが同じ映像だとどうなるのかピンとこなかった。
使ったのはiPhone XS Max。
画面いっぱいはもちろん、Safe Areaを左右半分にして画像を写しても大きすぎるのかVRゴーグルの仕様のせいかともかく焦点が合わないのでSafe Areaの9割を使っている(後述)。


【結果】
現時点で最新機種のiPhone XS Maxとは言え、カメラの映像はリアルより遅延があってそのせいか、酔った。おえーっ。
当然立体感はない。
通常の目で見る感覚より何もかも大きく見えるのですぐ近くのコップを掴むのもたどたどしい。歩くのも危ない。
捉える物体にピントが合うのに時間がかかる、、、これはコードがぬるいせいかもしれない。何かその辺りの設定できたんだっけ、、、


【感想】
そもそもは自作の’ARゴーグル’を使って現実世界に何か情報を表示する、という方向での技術的な蓄積、つまり‘iGlass’的なデバイスが登場した時の準備、なんて考えてたんだけどかなりやる気が失せた。

むしろ、iOS 13(現在beta 3らしい)のARKitで人物や自分の手を捉えるというデモ動画を見たので、それと合わせてVRアプリで操作するのに自分の手を使う、という方向を模索した方が面白いかも。

VR CROSS ROAD スクショ4
↑だいぶ前に作成したVRアプリ。みんなVRに興味あるのか今でもダウンロードされてる。
VR CROSS ROAD
このアプリでは音声を使って自機を動かすんだけど、カメラを使ってジェスチャーで操作なんてこともできるかもしれない。



【おまけ1】
DIYで使う木工用ドリルを使って、VRゴーグルに穴を開けたんだが6mmのドリルじゃ穴も小さいしそもそも位置もよくなかった、、、ということで、

VRゴーグル(さらに穴あけた状態)

↑試行錯誤しつつ穴を広げて行ってたところ、、、

部品が外れたVRゴーグル

↑パカっと部品が取れた、、、?
お、お前、取れるんか!
最初から穴なんて開けなくてもよかったやん!!!


【おまけ2】
コードについて。

storyboardでのviewの設定

↑storyboardでUIViewオブジェクトを作成。自分の場合はSafe Areaの横幅x0.9となるようにconstraintを設定。
中央の棒(UIViewオブジェクト)はただの中心の位置決め用(ゴーグルにセットする時に欲しい)。

使ったコードは一部だけど以下のような感じ。CAReplicatorLayerを使えば複数の画面を並べるだけなら簡単にできる。
class ViewController: UIViewController {
var cameraPosition : AVCaptureDevice.Position!
var captureSession : AVCaptureSession!

func setupBasic() {
cameraPosition = AVCaptureDevice.Position.back
captureSession = AVCaptureSession()
}

//↓画面タップでコールされる
func openCameraSession() {

do {
let videoCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video)
let captureDeviceInput = try AVCaptureDeviceInput(device: videoCaptureDevice!)

captureSession.addInput(captureDeviceInput)

captureSession.beginConfiguration()
captureSession.sessionPreset = AVCaptureSession.Preset.hd1280x720
captureSession.commitConfiguration()

let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer.connection?.videoOrientation =
AVCaptureVideoOrientation.landscapeRight
previewLayer.frame = CGRect(x:0, y:0,
width:mainView!.bounds.size.width/2,
height:mainView!.bounds.size.height)

let replicatorLayer = CAReplicatorLayer()
replicatorLayer.frame = CGRect(x:0, y:0,
width:mainView!.bounds.size.width/2,
height:mainView!.bounds.size.height)
replicatorLayer.instanceCount = 2
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(
mainView!.bounds.size.width / 2,0.0, 0.0);

replicatorLayer.addSublayer(previewLayer)
mainView!.layer.addSublayer(replicatorLayer)

captureSession.startRunning()

} catch {
print(error);
}
}
}


// in AppDelegate.swift
func applicationDidBecomeActive(_ application: UIApplication) {
application.isIdleTimerDisabled = true
}
↑あと、ゴーグルにセットして時間が経つとスリープしないようにする設定。
applicationWillResignActive(_:) でfalseに戻す。

※iOS12.3.1 , Swift 5.1


iOSアプリ「旗当番表メーカー」をリリースしました(現在無料)

小学生の子供がいると旗持ち当番(旗振り当番とも言うようです)をしなければいけないところもあるでしょう。
そして場合によっては自分がその当番表を作成することになるかもしれません。
そんな時にお手伝いするアプリです。

メンバーを入れて、期間や曜日を設定し、文言を設定すれば、、、

作成した旗当番表

↑このようなPDFファイルを作成してくれます(このブログではPDFファイルのアップロードができないので編集時の画像を表示しています)。

現在無料です。今のうちにダウンロードを!
App Storeはこちら↓

旗当番表メーカーのアイコン
旗当番表メーカー




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.