このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成 July 30, 2022
トップページ > Android 開発トップ > Android Studio でゲームクラスを更新
line
Android 開発
line

ここでは、Android Studio で正解の選択肢タッチを判断するコードについて、書いています。

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 です。

android studio chipmunk

▼ セクション一覧

正解選択時の処理を実装
タイマー処理を更新する
2 秒経過で次に進む
正解を判定する

なお、本サイトの ご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。

正解選択時の処理を実装

投稿 July 30, 2022

ここまで「Canvas だけでもアプリはできる!」シリーズを追ってずっとコードを入れてきた場合、 アプリを起動すると背景画像に 4 つのボタンが表示され、 画面をタッチすると赤い丸が表示されて正解音(効果音)が再生されています。

今はタッチされたら処理を行っていますので、ボタンをタッチしなくても、 あるいは素数が書かれたボタンでもそうでなくても(つまり不正解でも)、関係ありません。

まずは不要なコードを削除し、正解時のみ、正解の処理を行うこととします。

Toast 表示 スクリーンショット

今はタッチイベント処理関数 onTouchEvent に入っている赤い丸の表示を指示し、正解音を鳴らすコードを、 独自のビュー FlashSosuuView に新しく opCorrect 関数を定義し、コピーしました。 たびたび書きますが、関数名は何でも構いません。

opCorrect 関数

変数 nShow に 1 を設定すると、描画関数 onDraw で赤い丸を表示するようになっています。 画面の書き換えを促すために、画面全体を無効にする invalidate() を呼び出しています。

また、効果音を再生するために、再生コードを移動してきました。

opCorrect 関数

続けて、正解判定後、一定の時間が経過したら赤い丸を消して次の問題に進めるように、 現在の時刻を記録するためDate クラス を用意しました。

Date クラス

いつものように Date クラスが未定義になっていますので、 Date にマウスポインタを乗せ、表示されたポップアップにある Import class を選んで解決しておきます。

Class to Import

Date クラスは 2 種類あるようですので、上にある、java.util と書かれた項目を選びます。 ちなみに下にある項目には java.sql と書かれていますので、データベース操作系のものと思われます。

引数なしのコンストラクタで Date クラスを作成すると、現在の日時を取得できます。

正解の選択肢を選んだ時刻を記録するため、変数 tmStart を定義します。 定義する場所は、この独自のビュー FlashSosuuView の、コンストラクタより前です。

tmStart を定義

定義した tmStart に、正解を選んだ時刻を記録します。

tmStart に時刻を取得

Date クラス は日付を扱うクラスで日時を管理しているのですが、 「この時刻から 2 秒経過したら、赤い丸を消して、次の問題に進む」としたいので、 「 分またぎ ( 10 秒からなら 12 秒まで、25 秒からなら 27 秒までですが、58 秒からだと 0 秒まで、59 秒からだと 1 秒までとなります。 ) 」 があると多少面倒です。

ここでは getTime 関数を使っていますので、 基準時刻からの経過ミリ秒の値を取得しています。 つまり、リンク先の解説にある通り、グリニッジ標準時 1970 年 1 月 1 日からの経過ミリ秒数ですので、 時間の経過にともない、値は増加する一方ですから、扱いやすいです。

Android Studio でタイマーによる自動画面更新」でタイマーを設定し、 200 ミリ秒間隔 ( 1 ミリ秒は 1/1000 秒ですので、200 ミリ秒は 1 秒に 5 回となります。ミリ秒は記号では ms です。 ) で独自に作成したビューを無効化して、ユーザーの操作がなくても画面を更新できるようにしました。

このときは独自のビュー FlashSosuuView に対して invalidate() を実行して画面を書き換えていましたが、 代わりに FlashSosuuView の関数を呼び出すことにして、自由な処理を行いたいと思います。

▲ページ先頭へ

タイマー処理を更新する

投稿 July 30, 2022

現在のタイマー処理は、MainActivity でタイマーを設定し、 TimerTask クラスから派生させた、MainTimerTask クラスで、 単純に invalidate 呼び出しだけを行っています。

run 関数

ここまでこのサイト記載のものと同じファイル名で保存している場合は、 MainTimerTask.javarun 関数で、 次のように、独自のビュー flashSosuuView の画面を無効化しています。

((MainActivity)ctx).flashSosuuView.invalidate();

ctxContext ですが、MainActivity で定義した独自のビュー flashSosuuView にアクセスするには MainActivity である必要がありますので、 実体は同じですから、キャストしてからアクセスしています。

このタイマー処理は、MainActivity.javaonCreate 関数で、 200 ms ごとに呼び出設定としていますので、 invalidate() の呼び出しをやめ、 FlashSosuuView に新しい関数 onTimerProc を追加して、MainTimerTask で呼び出すことにします。

まず独自のビュー FlashSosuuView クラスに、タイマー処理用の関数を追加します。

onTimerProc 関数

クラス外部から呼び出せるようにするため、public で定義しておきます。 内容はこのあと記入します。

タイマー処理

タイマー処理側は invalidate 呼び出しの代わりに、この関数を呼び出すように書き換えておきます。

▲ページ先頭へ

2 秒経過で次に進む

投稿 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 に追加します。

isCorrect 関数

自身 saGame クラス外である独自のビュー FlashSosuuView から呼び出しますので、public で定義します。

引数 nIndex は、ボタン 1 なら 0、ボタン 2 なら 1、ボタン 3 なら 2、ボタン 4 なら 3 を受け取ることにしています。 ですので、nIndex が 0 未満だったり 3 以上だったりするなら、プログラムに問題ありということで、-1 を返しています。

タッチされたボタンが正解である場合、正解インデックスを保持している nAnswer と一致ということになりますので、0 を返します

タッチされたボタンが正解ではない、つまり素数ではない場合、例えば何で割り切れるのかを提示したいので、 素数リストの数 nNumSosuu だけ、小さいほうから順に割り切れるかどうかを判定しています。 % 演算子は、割り算した余りを返してくれるものです。

つまり、正解なら 0 を、不正解なら 2 以上の値を返す、ということになります。

独自のビュー FlashSosuuView のタッチイベント処理関数 onTouchEvent で、 ボタンのタッチを認識したら、この isCorrect 関数で正解かどうかを確認します。

onTouchEvent 関数

このあと各ボタンの処理で共通に使用するため、MainActivity を変数 ma に、そして isCorrect 関数の戻り値をセットするための nValue を定義しておきます。

ボタン 1 のタッチ処理

ボタン 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 で割り切れるよ!」と表示されます。 何で割れるから素数ではないのかをお知らせするほうが親切です。

これでだいぶゲームらしくなりましたが、 タイムの計測もありませんし、終わりもなく無限に素数を答えることになっています。

▲ページ先頭へ
line
関連トピックス
line

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++ ネイティブアプリでアプリ名を設定する方法の詳細を検討しています。

line
その他のおすすめ
line

Android 開発に関する記事をまとめた Android 開発トップ もご覧ください。

素因数分解トレーニング

以降の数学の基本となる素因数分解の基本部分を、ひたすらトレーニングするための JavaScript コードについて書いています。

因数分解トレーニング(1)

因数分解の公式の一部について、ひたすらトレーニングするための JavaScript コードについて書いています。



© 2017-2022 StraightApps.com 無断転載を禁じます。No reproduction without permission.