Canvas だけでもアプリはできる!
ノート PC に、Visual Studio Community 2022 の C++ によるモバイル開発機能のインストールと、 その時点で最新だった Android Studio のインストールを完了しましたので、 Android アプリの開発環境が整ったということになりました。
「Android Studio で文字を自由に描画する」 で、独自のビューを作成して Empty Activity に設定し文字を描画、 続く「Android Studio で画像を自由に描画する」 で、PNG 画像をプロジェクトに取り込んで、描画関数 onDraw が引数で受け取った Canvas に画像を描画しました。 拡大・縮小もできていますし、画面タッチの検出もできました。
「Android Studio でタイマーによる自動画面更新」ではタイマーをセットし、 一定間隔で独自に作成したビューを無効化して、ユーザーの操作がなくても画面を更新できるようにし、 「Android Studio で効果音を鳴らす」では、クイズで正解したときなどに鳴らす 短い効果音の再生処理も実装しました。
「Android Studio で画面を準備する」では画面の事前準備として、 アクションバーの非表示、 画面を縦固定、 背景画像の描画、 そして画面のタッチからブラウザでウェブサイトを開く、といった項目を実装し、 「Android Studio でボタン表示&入力」で、 座標管理クラスを作成してボタンを表示し、どのボタンがタッチされたかを認識できました。
ここでは 「Android Studio でボタン表示&入力」で作成したゲームクラスに処理を追加して、 正解の選択肢をタッチしたときに正解音を鳴らし、赤い丸を表示し、自動的に次の問題に進む処理を実装しています。 これでだいぶゲームらしくなってきます。
ここまで作成したコードへの追記の形となっていますが、すべて必要と言うわけではありません。
過去すでに Android Studio を別のマシンで使用して 「素因数分解トレーニングアプリ」 を開発していますが、改めてちゃんとアプリを作りたいな、と思い、リスタートしています。
なお、使用している Android Studio は、2022 年 5 月中旬にインストールした、2021.2.1 Patch 1 の Chipmunk です。
なお、本サイトの
ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 July 30, 2022
ここまで「Canvas だけでもアプリはできる!」シリーズを追ってずっとコードを入れてきた場合、 アプリを起動すると背景画像に 4 つのボタンが表示され、 画面をタッチすると赤い丸が表示されて正解音(効果音)が再生されています。
今はタッチされたら処理を行っていますので、ボタンをタッチしなくても、 あるいは素数が書かれたボタンでもそうでなくても(つまり不正解でも)、関係ありません。
まずは不要なコードを削除し、正解時のみ、正解の処理を行うこととします。
今はタッチイベント処理関数 onTouchEvent に入っている赤い丸の表示を指示し、正解音を鳴らすコードを、 独自のビュー FlashSosuuView に新しく opCorrect 関数を定義し、コピーしました。 たびたび書きますが、関数名は何でも構いません。
変数 nShow に 1 を設定すると、描画関数 onDraw で赤い丸を表示するようになっています。 画面の書き換えを促すために、画面全体を無効にする invalidate() を呼び出しています。
また、効果音を再生するために、再生コードを移動してきました。
続けて、正解判定後、一定の時間が経過したら赤い丸を消して次の問題に進めるように、 現在の時刻を記録するため、 Date クラス を用意しました。
いつものように Date クラスが未定義になっていますので、 Date にマウスポインタを乗せ、表示されたポップアップにある Import class を選んで解決しておきます。
Date クラスは 2 種類あるようですので、上にある、java.util と書かれた項目を選びます。 ちなみに下にある項目には java.sql と書かれていますので、データベース操作系のものと思われます。
引数なしのコンストラクタで Date クラスを作成すると、現在の日時を取得できます。
正解の選択肢を選んだ時刻を記録するため、変数 tmStart を定義します。 定義する場所は、この独自のビュー FlashSosuuView の、コンストラクタより前です。
定義した tmStart に、正解を選んだ時刻を記録します。
Date クラス
は日付を扱うクラスで日時を管理しているのですが、
「この時刻から 2 秒経過したら、赤い丸を消して、次の問題に進む」としたいので、
「
ここでは getTime 関数を使っていますので、 基準時刻からの経過ミリ秒の値を取得しています。 つまり、リンク先の解説にある通り、グリニッジ標準時 1970 年 1 月 1 日からの経過ミリ秒数ですので、 時間の経過にともない、値は増加する一方ですから、扱いやすいです。
「Android Studio でタイマーによる自動画面更新」でタイマーを設定し、
このときは独自のビュー FlashSosuuView に対して invalidate() を実行して画面を書き換えていましたが、 代わりに FlashSosuuView の関数を呼び出すことにして、自由な処理を行いたいと思います。
投稿 July 30, 2022
現在のタイマー処理は、MainActivity でタイマーを設定し、 TimerTask クラスから派生させた、MainTimerTask クラスで、 単純に invalidate 呼び出しだけを行っています。
ここまでこのサイト記載のものと同じファイル名で保存している場合は、 MainTimerTask.java の run 関数で、 次のように、独自のビュー flashSosuuView の画面を無効化しています。
((MainActivity)ctx).flashSosuuView.invalidate();
ctx は Context ですが、MainActivity で定義した独自のビュー flashSosuuView にアクセスするには MainActivity である必要がありますので、 実体は同じですから、キャストしてからアクセスしています。
このタイマー処理は、MainActivity.java の onCreate 関数で、 200 ms ごとに呼び出設定としていますので、 invalidate() の呼び出しをやめ、 FlashSosuuView に新しい関数 onTimerProc を追加して、MainTimerTask で呼び出すことにします。
まず独自のビュー FlashSosuuView クラスに、タイマー処理用の関数を追加します。
クラス外部から呼び出せるようにするため、public で定義しておきます。 内容はこのあと記入します。
タイマー処理側は invalidate 呼び出しの代わりに、この関数を呼び出すように書き換えておきます。
投稿 July 30, 2022
正解を選んだ時刻 tmStart に設定された時刻から 2 秒経過したら、赤い丸を消して、次の問題に進むようにします。
独自のビュー FlashSosuuView の onTimerProc 関数は 200 ms ごとに呼び出されることになりましたので、 ここで正解を選んだ時刻 tmStart から 2 秒経過したかどうかを判定することになります。
まず、tmStart が 0 であれば「ここでの処理は非アクティブ」、 つまり 2 秒経過の判定の対象外ですから、何も処理を行いません。 tmStart の定義時にも 0 を設定していますので、正解を選択したときだけ有効となります。
また、今はタイマーによる画面の書き換えも必要ありませんので、invalidate() も行いません。
tmStart に値が設定されている場合は、この if にあてはまりませんので、先に進みます。
opCorrect 関数と同様に、 Date クラスを作成して現在時刻を取得し、 getTime 関数で 「基準時刻からの経過ミリ秒数」を取得して tmNow に設定しています。
基準時刻からの経過ミリ秒数は値が増加する一方ですので、 必ず tmNow のほうが、正解を選択した時刻 tmStart より大きな値になります。 ですのでその差が 2 秒、つまり 2,000 ミリ秒より小さい場合は、まだ経過していない、ということになります。
2,000 ms 以上経過したら、次の問題に進む処理を実行します。
この onTimerProc 関数は、正解したかどうかに関係なく 200 ミリ秒ごとに呼び出されていますので、 まずは正解した時刻 tmStart をクリアして、連続で「2 秒経過」と判断されないようにします。
MainActivity の game クラスに実装した CreateNew 関数を呼び出して、新しい問題を作成します。 わざわざ 2 行にして書いていますが、わけなくても問題ないでしょう。
((MainActivity)getContext()).game.CreateNew();
最後に赤い丸を非表示とするため、nShow を 0 にし、 invalidate() 呼び出しで、画面を無効にして、再描画を促します。
投稿 July 30, 2022
画面に 4 つ表示したボタンのどれがタッチされたかは、 「ボタンのタッチを認識する」で判定していますので、 それが正解かどうかを判断する関数 isCorrect を、ゲームクラス saGame に追加します。
自身 saGame クラス外である独自のビュー FlashSosuuView から呼び出しますので、public で定義します。
引数 nIndex は、ボタン 1 なら 0、ボタン 2 なら 1、ボタン 3 なら 2、ボタン 4 なら 3 を受け取ることにしています。 ですので、nIndex が 0 未満だったり 3 以上だったりするなら、プログラムに問題ありということで、-1 を返しています。
タッチされたボタンが正解である場合、正解インデックスを保持している nAnswer と一致ということになりますので、0 を返します。
タッチされたボタンが正解ではない、つまり素数ではない場合、例えば何で割り切れるのかを提示したいので、 素数リストの数 nNumSosuu だけ、小さいほうから順に割り切れるかどうかを判定しています。 % 演算子は、割り算した余りを返してくれるものです。
つまり、正解なら 0 を、不正解なら 2 以上の値を返す、ということになります。
独自のビュー FlashSosuuView のタッチイベント処理関数 onTouchEvent で、 ボタンのタッチを認識したら、この isCorrect 関数で正解かどうかを確認します。
このあと各ボタンの処理で共通に使用するため、MainActivity を変数 ma に、そして isCorrect 関数の戻り値をセットするための nValue を定義しておきます。
ボタン 1 がタッチされた場合、それを確認できるようトースト表示をしていましたが、コメントアウトします。 削除しても同じですし構いませんが、あとでまた確認したくなったら場合に備え、残しています。
MainActivity に定義したゲームクラス game の isCorrect 関数に、ボタン 1 を表すインデックス 0 を渡し、戻り値 nValue を得ます。
nValue が 0 なら正解、そうでない場合は割り切れる最小の素数が返ることになっていますので、 0 かどうかを判定し、0 なら正解処理 opCorrect 関数を実行します。
ボタン 2 から ボタン 4 までも、isCorrect 関数に渡す引数が異なるのみで、同様の判断を追加します。
タッチイベント処理関数 onTouchEvent の最後の部分では、nValue の値を検査します。 0 で初期化していますので、0 ではない値が設定されるのは不正解のボタンがタッチされた場合のみです。
不正解の場合、「2 で割り切れるよ!」のようなメッセージを作成し、 トースト表示して理由を説明しています。
実機で実行すると、正解の選択肢を選ぶと次のようになり、2 秒後には新しい問題に変わります。
不正解を選ぶと、画面の下の方に割り切れる数が表示されます。
ボタン 1 の 69 を選んでしまうと、3 で割り切れるので、「3 で割り切れるよ!」と表示されます。 何で割れるから素数ではないのかをお知らせするほうが親切です。
これでだいぶゲームらしくなりましたが、 タイムの計測もありませんし、終わりもなく無限に素数を答えることになっています。
Canvas だけでもアプリはできる! #1
Android Studio で文字を自由に描画する
このシリーズの最初です。 アプリ独自のビューを作成し、テキストを描画するまでのコードを作成しています。
Canvas だけでもアプリはできる! #2
Android Studio で画像を自由に描画する
用意した PNG 画像を表示したり、画面タッチに追従したりするコードを作成しています。
Canvas だけでもアプリはできる! #3
Android Studio でタイマーによる自動画面更新
MainActivity にタイマーを設定して、一定間隔で処理を呼び出すコードを作成しています。
Canvas だけでもアプリはできる! #4
Android Studio で効果音を鳴らす
効果音のような短い音を鳴らすコードを作成しています。
Canvas だけでもアプリはできる! #5
Android Studio で画面を準備する
アクションバーの消去、画面の縦固定指定、背景画像描画、そしてタッチでウェブサイトを開くコードを作成しています。
Canvas だけでもアプリはできる! #6
Android Studio でボタン表示&入力
座標管理クラスを作成して画面に適切なサイズのボタンを表示し、どれが押されたか判断するタッチ処理を実装しています。 トースト表示や独自クラスの作成についても書いています。
Android Studio で全画面プロジェクトを作成する
Empty Activity では画面上部に邪魔になり得るタイトル表示領域がありますが、 Fullscreen Ativity なら、それがなくなるのか、新規プロジェクトを作成して確認しています。
Android Studio で ActionBar を非表示にする
Empty Activity では画面上部に邪魔になり得るタイトル表示領域がありますが、 プロジェクト内の設定の書き換えにより、別プロジェクトにしなくても非表示にできるようです。
Android Studio で Native C++ プロジェクトを作成する
目的としている C++ ネイティブコードを併用する Activity は、 Native C++ プロジェクトを作成すれば、比較的簡単に着手できそうです。
Android Studio で AdMob プロジェクトを作成する
もうひとつの目的としては、AdMob でアプリ内に広告を入れる、です。 AdMob Ads Activity なら簡単に実装できるのでしょうか?
C++ ネイティブアプリでアプリ名を設定する方法の詳細を検討しています。
Android 開発に関する記事をまとめた Android 開発トップ もご覧ください。
以降の数学の基本となる素因数分解の基本部分を、ひたすらトレーニングするための JavaScript コードについて書いています。
因数分解の公式の一部について、ひたすらトレーニングするための JavaScript コードについて書いています。