先日紹介した、マークアップを使ったチェック判定を応用したクイズゲームを作りました.
※価格は記事執筆時のものです. 現在の価格はApp Storeから確認ください.
レビュー時のiOSバージョン : iOS15.4
スポンサーリンク
ダウンロードと準備、使い方
またここが重要なのですが、使用する画像は少なくとも「マークアップ後にサイズが小さくならないもの」である必要があります.
マークアップ後にサイズが変わる画像を使うと、正しく座標指定できなくなります.
上のレシピではiPhon8でのマークアップ後のサイズのものを採用しています.
おそらく同世代とそれ以降のモデル、またiPadシリーズであれば差し替えは不要と思われます.
これは同じアイデアを採用する場合でも同じです.
上の画像はiPad Air3用に用意した1500×2300pxの画像ですがはてなブログの仕様で783×1200pxに縮小されています.
レシピにあるものはオリジナルサイズとなっています(後述の通りBASE64エンコードされた状態です)、手持ちの端末で一旦画像化し、マークアップを試行してそのサイズにリサイズして再びBASE64エンコードして入れ直してください.
これができれば問題ないはずです.
実行するとランダムで明るさが変わり、続けて先程の画像が出てきます.
その時点での明るさを推測し、ここだろうと思った目盛りまで塗っていきます.
画像の通り、途中が欠けていても問題ありません、最も上の部分が回答者の指定の値として判定されます.
少し待つと、ランダムで出題された明るさと回答した明るさが結果として表示されます.
ただ結果を出すのにやや時間がかかりますそこもまだまだ課題ですね.
仕様を考える
レシピの前に仕様というか方針を予め書いておきます.
アイデア自体は先日の投稿のものを使います.
つまり指定範囲の
- オリジナル部分のBASE64エンコードテキスト
- マークアップ後のBASE64エンコードテキスト
が一致するかどうか…で、塗りつぶされたかどうかを判定します.
今回は明るさの判定なのでその数が単純に考えると100箇所ということになります.
予め決めた画像のうち更に判定枠と見なした箇所を更に100等分し、順番に見ていくことになります.
処理が遅いのはそのためですね.
ただRedditにある投稿例ではそれ以上の数(カラーピッカーなので256×3)をサクッと処理していましたから、もっとエレガントなやり方があるということです.
それはともかくとして、一つ一つの判定部分を考えます.
用意した画像は1500×2300px、判定枠の左端、つまり「イメージを切り取り」アクションのX座標に相当する部分は300(ある程度の余裕を持たせた値です)とし、これはどの判定枠も同じです.
同様に幅は930pxです.
高さは目盛りの上端部分である画像上から407pxより2198pxの差1791pxを今回は明るさの目盛りに相当する100分割、つまり100-1=99で割ったものになります.
Y座標は今回の仕様では下端の2198pxを高さ一つ分だけ減らしたものからスタートし、高さ一つ分ずつ減らしていくことになります.
これで「イメージを切り取り」アクションの4要素が決まりました.
レシピ
悪戦苦闘した際の名残があります.
今回は明るさの100等分なのでこれを変数numで置きます.
「イメージを切り取り」の処理は100-1=99回行いますからこの数を変数countで置きます.
また後で元の明るさに戻すために、実行時の明るさを取得しておきます.
その後ランダムで明るさを指定するための10から100の間で乱数を発生させます(0でなく10にしたのは、暗すぎると塗りづらくなるからです).
明るさを変数で指定する場合は0から100でなく0から1なので、100で割ってから明るさを指定します.
「テキスト」アクションにBASE64エンコード済の画像を貼っておき、これを「BASE64エンコード」アクションでデコード、こうして再画像化されたものを「マークアップ」アクションでマークアップさせます.
その結果を変数afterで置きます.
マークアップの操作は済んだので画面の明るさを最初に取得しておいた実行時の状態に戻します.
オリジナルの画像をマークアップ後の幅と高さに変更し、その結果を変数beforeで置きます.
これで変数beforeとafterは、マークアップの操作を抜きにしてサイズは同じです.
続いて「イメージを切り取り」で使うX座標と幅、高さを予め計算しておきます.
マークアップ前後のサイズ変化を考慮した倍率が残っていますが上の通りに画像を用意すれば倍率は1になるので特に問題ありません.
上で書いた通りY座標だけは各々で値が異なるため、繰り返し処理の中で行います.
変数countの分だけ繰り返します.
まずオリジナル画像beforeに対してY座標の値を計算し、「イメージを切り取り」アクションで切り取った結果を更に「BASE64エンコード」でエンコードテキストを取得します.
同じことをマークアップ後の画像afterでも行います.
こうして得られた2つのBASE64コードを比較し、等しくないならば繰り返しインデックスを適当な変数に置きます.
これによってこの変数はだんだん増えていき、変化がなくなると止まるため、結果塗りつぶしの上端の値を得ることができます.
最後にランダムで変化させたときの明るさを0-100表示にするために100倍したものと、上の結果を表示されて終わります.
サイズが変化する画像だと
マークアップ後にサイズが小さくならない画像を用意すべきと書きましたが、そうでない場合どうなるか…がきになるところです.
実際iPad Air3用に用意した画像をそのままiPhone8で実行すると、こちらがどんな値で塗っても「回答」が強制的に100になってしまいました.
最初はマークアップ後のサイズになるよう後でオリジナルをリサイズし、同じ箇所を切り取って比較すれば良いんじゃないか…と考えて上のレシピを組んだわけですが、どうも初めから前後で一致する画像でないとダメのようです.
試しにiPhone8でマークアップ前後で変わらない画像を用意してそれに差し替えたところ、すんなりうまくいきました.
余裕を持って大きな画像を…と考えるのは良くないということですね.
〆
面白いアイデアなので色々なことに使えそうなんですが、現時点での課題点を改めてまとめると次の2点です
- 分割数が増えたときの処理時間
- 指定した画像サイズによる位置精度
この二つを克服すればより便利なんですけどね.