75才からのモバイルアプリ作成

MIT App Inventor 2 を使ったアプリ作成

MIT App Inventor 2で遊ぶ (GlobalChat 6)

2024-09-04 07:10:20 | 日記

GlobalChat 6 用に、Firebase RealtimeDatabase内に、新たにチャットを保存する「GlobalChatRoom」とnicknameを保存する「NickName List2」を設けた。

個人情報として、nicknameの他に趣味とアバターの登録を追加した。

新たに登録したnicknameでツイートを追加したら、うまくいかなかったが、「Reload」ボタンをタップしたら追加したツイートも表示された。今回Firebase Realtime DBに新しくdirectoryを設けたが、その途端、やりとりがうまくいかない時が出てきた。(ビデオの通り)う〜ん、難しい。前回のGlobalChat 5 とブロック・コードの内容も同じなのに????

アプリ実行のビデオ:

スクリーンのデザイン:

                                                     

ブロック・コード:

追加・変更部分のみ。

1. nicknameの入力boxとしてPasswordTextBoxを使っていたが、入力内容を非表示にする理由に乏しいので、表示することとした。(通常のtextBoxにすればよのだが、とりあえず「入力内容を表示」に設定を変更した)

2. avatarの選択ボタン(以下5つ)をリストに保存(今のところnicknameの登録も5人に制限)

3. 変数avatarNumberを作成し、選択されたavatarの順番(1から5まで)を格納。

選択したavatarの番号がすでにFirebase Realtime DBに保存されている場合は、タップした番号はすでに選択済みなので、他のavatarを選択するよう促すメッセージを表示。選択されていない場合は、avatar番号(index番号)をavatarNumberに格納し、label componentであるselectedAvatarNumberに表示。

4. 「Register」ボタンをタップすると、管理者パスワードの入力を促すウインドウが表示。

管理者パスワードである「123」を入力すれば、nicknameに加え、hobyyとavatarNumberがFirebase Reatime DBの所定のURLのDirectory (NickNameList2) にPOSTされる。

                                                             

5. 「List of registered nicknames」のListViewにnicknameとともにhobbyとavatar画像を表示させるため、Firebase Realtime DBより取得したデータよりhobbyのみを取り出し変数hobbyListに格納。

また、同じく、Firebase Realtime DBより取得したデータよりavatar番号のみを取り出しリスト形式でavatarListに格納。

6. Firebase Realtime DBより取得したデータよりnickname, hobby, avatar番号のデータを統合してリスト形式で変数dataForListViewに格納。avatar画像については、「avatar」 + avatar番号 + 「.png」で画像のファイル名を作成。

 なお、このアプリが立ち上がった時に、Firebase Realtime DBよりnickname, hobby, avatar番号を保存しているディレクトリー「NickNameList2」よりデータを取得するが、そのデータよりnickname, hoby, avatar番号に分けてそれぞれをリスト形式で保存する関数makeNicknameList, makeHobbyList, makeAvatarList(上記)を実行しておく。またそれらリストを統合しLIstViewに表示するためのリストを生成する関数makeDataForListViewも実行する。

ブロックの説明がわかりにくいが、要するに、アプリ立ち上げ時にnickname, hobby, avatar番号の情報を取得し、nicknameについてはログインのためのデータとして使用し、個人の情報の登録では、List of registered nicknamesにこれら情報を表示。また、新規登録した場合は、しかるべきFirebase 側のURLにデータをPOSTし保存。保存されれば、List of registered nicknamesが更新される。

List of registered nicknamesは、今やnicknameだけではないので、変更した方が良いかもしれない。

                                        **********************************************************************

前回までのブログ(CRUDの内Uを除くCRDを実装):

MIT App Inventor 2で遊ぶ (GlobalChat 4 (5) - 再々追加 -)

MIT App Inventor 2で遊ぶ (GlobalChat 4 -追加-)

MIT App Inventor 2で遊ぶ (GlobalChat 4)

MIT App Inventor 2で遊ぶ (GlobalChat 3)

MIT App Inventor 2で遊ぶ (GlobalChat 2)

MIT App Inventor 2で遊ぶ (GlobalChat 1)


MIT App Inventor 2であのアプリを作ってみる (Tic-Tac-Toe 2 -勝ち負けなしの場合-)

2024-08-31 07:33:24 | 日記

勝ち負けなしの判定が抜けていたので、追加した。

これはてこずるのではないかと思っていたが、意外と簡単に解決方法が見つかった。

アプリ実行のビデオ:

スクリーンのデザイン:

上記ビデオの通りだが、それぞれの場合のスクリーンは以下の通り。

               Circle wins                                      Cross wins                               No wins or losses

        

ブロック・コード:

1. 9つのボタンのいずれかをタップした回数を格納するtapCountを設定。これらボタンは、一度タップすると無効となるので、一回の勝負で先攻後攻合わせて9回タップすることになる。

2. 先攻、後攻、いずれがタップしてもtapCoupntを1加算する。(赤黄色点線部分)

3. 関数noWinsNoLosses:tapCountが9(タップできるボタンがなくなった時)で、かつshowWinnerLabelのテキストが空白(これは、先攻、後攻ともに現在の対戦では勝っていないことを意味する)の場合は、showwinnerLabelに「No wins or losses」(勝ち負けなし)を表示し、関数makeButtonsDisabledを実行する。

4. 関数makeButtonsDisabled:全てのボタンを無効にし、「Play again」ボタンを表示する。

5. 関数decideWinnerに、関数noWinsNoLossesを最後に追加する。これにより、合計9回のタップの後でも先攻後攻いずれも勝たなかった場合に、この関数の条件が満たされ、「No wins or losses」が表示される。

                     *********************  途中省略  ***********************

6. 「Play again」ボタンをタップすれば変数等が初期化され、同時にtapCountも0に初期化される。

 

                                              ***********************************************************

前回までのブログ:

MIT App Inventor 2であのアプリを作ってみる (Tic-Tac-Toe 1)

 

 


MIT App Inventor 2であのアプリを作ってみる (Tic-Tac-Toe 1)

2024-08-28 18:59:02 | 日記

もう少しスマートに作りたかったが。。。何しろ動けばいいやということで、かなり無理矢理作った。またの機会に格好良く作ってみたい。

アプリ実行のビデオ:

スクリーンのデザイン:

Tablet sizeでキャプチャー。「Play again」ボタンは、勝敗が決まるまでは非表示。

                         

 

ブロック・コード:

1. マル、バツの画像ファイル名をリスト形式で変数imageToShowに格納。

                     circle1Trans.png                  cross1Trans.png  

                                            

2. 9つのボタンの初期化。有効にすると共にimageは「なし」に設定。

変数buttonListは以下の9つのボタンをリスト形式で格納

3. Buttonのgenericのイベントハンドラー(タップした時の動作を設定)を使用。

genericのイベントハンドラーは、対象となるcomponent全ての動作を一様に設定するもので、今回はButton。もちろん条件をつけて特定のButtonのみの動作を設定することもできる。

今回は、Buttonとして設定されているのは9つのみ。「Play again」ボタンがあるが、これはButtonではなくタップした時の動作を設定できる「clickable image」をボタンとして利用しているもの。

今回の基本的な動作は、ボタンがタップされると、変数tapIndexにより、初期設定の1の場合は「circle」を表示、2の場合は、「cross」を表示させる。先攻はcircleとあらかじめ決めているので、最初にボタンをタップすれば、そのボタンは、circleを表示することになる。次に相手がタップすれば、tapIndexは2と設定されているので、crossが表示される。

具体的にgenericのイベントハンドラーを見てみると。。。

先攻がいずれかのボタンをタップする=>初めてなので、tapIndexは1。同ボタンの画像はimageToShowのindex 1であるcircleとなる=>tapIndexを2に、タップされたボタンは無効に設定。=>後攻がいずれかのボタンをタップする=>tapIndexが2に設定されているので、imageToShowのindex 2であるcrossとなる=>tapIndexが1に設定されるとともに、タプされたボタンは無効に設定=>この繰り返しでタップするたびにcircle、crossが交互に表示されていく

また、変数positionListの当該indexの値が、circleの場合は5、crossの場合は10に設定されていく。

4. 関数decideWinnerは、以下の変数winningCombinationListの組み合わせを、circle(5)、またはcross(10)のいずれが達成するかを監視するのが役目。もし、circle(5)が達成したら、「Circle wins」を、cross(10)が達成したら、「Cross wins」を表示することになる。(変数winningCombinationList自体は使用していない。数字は上記positionListのリスト項目のindexの値)

*******************以下、勝つ場合の組み合わせの数だけ続くが、省略********************

変数winningCombinationListは、勝利する時の組み合わせをリストにしたもので、このリストを使えば簡単に勝敗を決定できるだろうと考えたが、目論み通りには行かなかった。結局、上記の通り、かなりめんどくさい方法で勝者を決めることになった。

5. 勝者が決まったら、以下の関数makeButtonsDisabledを実行し、全てのボタンを無効に設定し、「Play again」ボタンを表示。

6. 「Play again」ボタンをタップした時の動作を設定。各変数を初期値へ戻す。

positionListの各リスト項目に0を再設定(初期化)。

関数makeButtonsEnabledでButtonを初期化。各ボタンを有効にするとともに、ボタンの画像をブランクに設定。

 

やはり、もう少しスマートな方法がないのか検討する必要がありそうだ。

勝者なしの引き分けの場合を想定するのを忘れた。(訂正=>勝負がつかない場合

 


MIT App Inventor 2で遊ぶ (GlobalChat 4 (5) - 再々追加 -)

2024-08-24 14:14:39 | 日記

nicknameの登録、削除した場合、Firebase Realtime Databaseとのデータのやり取りがうまくいかない場合がよくあった。

nicknameの登録関係のブロックを以下のように全て取り出し、相互の関係などを一覧図にまとめてみた。図にまとめてブロック・コードの見直しを行ったのは初めて。自分で作ったとは言え、全体の構造がよくわかった。MIT App Inventor2 の場合、適当にブロックを組み合わせると簡単にアプリらしきものが出来上がる。が、この手軽さゆえに、ブロックが無秩序に作成され、いわゆる「スパゲッティコード」のようになってしまう。今後もコードの見直しを行う際は、まずはブロックを一覧図にまとめた上で行うのがいいかもしれない。

今回の具体的な対応としては、タイミングをとる(次の関数の実行を遅らせる等)Clockを追加したりした。その結果、だいたい期待通り動作するようになった。

(図の中のブロックは小さすぎて識別できないので「感じ」のみ。。。)

また、背景画像を挿入してみた。(Image from Pixabay and photographed by MASTUDIO)

実行中のアプリのビデオは以下の通り。

(前回より安定性が格段に増した。)

                                          **********************************************************************

前回までのブログ(CRUDの内Uを除くCRDを実装):

MIT App Inventor 2で遊ぶ (GlobalChat 4 -追加-)

MIT App Inventor 2で遊ぶ (GlobalChat 4)

MIT App Inventor 2で遊ぶ (GlobalChat 3)

MIT App Inventor 2で遊ぶ (GlobalChat 2)

MIT App Inventor 2で遊ぶ (GlobalChat 1)


MIT App Inventor 2で遊ぶ (Space Travel 1)

2024-08-21 08:14:21 | 日記

マリオ型の横方向ではなく、縦方向に背景を動かすものを作りたかったので。。。

宇宙船の左右への移動は、AccelerometerSensorを利用し、左右にスマホを傾けたらその方向へ移動。ビデオではその感じがわからないが。

アプリ実行のビデオ:

(ちょっと単調なビデオだが。。。)

スクリーン・デザイン:

                                     

ブロック・コード:

Tutorials Azaotl の YouTube 「Mario run Game for App Inventor | Scrolling background part 01」(10::00以降の部分)で教えてもらった通り、以下の関数setAllにてCanvasの高さをScreenの3倍のサイズに拡大して設定。(以下の赤黄色点線内)

ただし、同関数を普通に実行するだけではサイズを3倍に拡大して設定することはできず(何回も実験したが)、Tutorials Azaotlのアドバイス通りClock component を利用して関数を5回実行すれば設定ができた。(実験では3回でもOKだったが)

関数setAllの最初の部分(3倍に設定する部分)は上記の通り。他に背景(bgSprite1, bgSprite2)、宇宙船(spaceshipSprite)、ロケットより発射される弾丸(Ball1)、Startボタン(startSprite)のサイズ、配置位置を設定。

Startボタンをタップした時の動作を設定:背景を動かすmoveBGClock、隕石を動かすmeteorite1Clock、宇宙船を左右に動かすAccelerometerSensorをそれぞれ有効にする。

関数setAll、関数moveBGProcedureを分解すると(Tutorials Azaotlさんの説明を縦展開にしただけで、私が考えたわけではない)、以下のような配置、動きとなるので、bigSprite1とbigSprite2を入れ替えたほうがわかりやすいかもしれない。。。

Canvas Heightを Screen Height の 3倍に設定 => 背景(BGSprite1, BGSprite2)が下に移動 => BGSprite2 が赤丸3の位置まで移動したら、赤丸1の位置に移動 => BGSprite1 が同様に赤丸3の位置まで来ると赤丸1に移動

以上の繰り返しにより背景を上から下へ動かす。移動するスピードは、moveBGClockのIntervalである100m秒毎に10pixels(変数speedBG)。

 

meteoriteSprite1(隕石)を動かす関数moveMeteorite1Procedureの内容が小さくてみにくいが。。。

基本的には、BGSprite1, BGSprite2 と同じで、meteoriteSprite1のy座標(左上端のx, y座標の値が基準)が、Canvas Height - Screen1 Heightより大きくなると(上記図の赤丸3の位置)、x座標はランダムな値、y座標は Screen1 Heightの半分の位置に戻る。それまでは、30m秒毎に変数speedMeteorite1に設定された数値(10pixels)ずつ下に移動する。

スマホを左右に傾ける=>AccelerometerSensorより返されるxAccelの値を使って宇宙船を左右に動かす。

画面をタップした時の動作(Ball1の弾丸を発射する):

Ball1(z値は1.1に設定)の位置を宇宙船(z値は1.2に設定)の中央あたりに設定。宇宙船のz値の方が大きいので、Ball1はロケットの下に隠れる。=> Ball1を表示。

Ball1(弾丸)は、20pixelsずつ、上の方向に移動し、Screen1のHeightより50pixelsマイナスした位置(ちょうど、画面の上に隠れる位置)まで来たら=>shootingClockを無効、Ball1を非表示、Ball1のy座標値を見えている画面の下辺より100pixels上、Ball1のx座標値を画面の中央に設定。

Ball1(弾丸)がmeteoriteSprite1(隕石)に衝突すれば、Ball1およびmeteoriteSprite1の両方を非表示に。

meteoriteSprite1(隕石)が宇宙船に衝突すれば、宇宙船および隕石の両方が非表示に。

 

この手のアプリには、サウンドが必要だと痛感。

なお、BGSprite1とBGSprite2をそのまま上から下へ移動させたら、そのつなぎ目が白い線となって見えてしまうので、Canvasの背景色をBGSprite1/BGSprite2の背景色とするなどの対策を施した。これはマリオのアプリと同様。

<特に対策を行わず背景画像を動かした場合>

                                           *****************************************************

背景を動かす同種のアプリのブログ:

MIT App Inventorで遊ぶ (マリオ 4)

MIT App Inventorで遊ぶ (マリオ その3)

MIT App Inventorで遊ぶ (マリオ その2)

MIT App Inventorで遊ぶ (マリオ その1)