Power Apps コレクション 動的に連番コレクションを作成する
コレクションをPower Appsのみ で動的に作成したい場合に使える例をひとつ。
今回挙げるのはループ処理でコレクションを追加していく方法です。
コールバック的に使えるSliderを用意する
Power Apps はループ処理系に弱いです。for eachとかfor文とかも使えません。
何度も同じ処理をさせたい場合、タイマーコントロールまたはスライダーコントロールを使用すると実現させることができます。
今回はスライダーを使用してみます。
スライダーを設置しSlider.Valueに適当な変数を指定します。
Slider.Value
SliderValue
※変数は事前にOnVisibleなどで初期化しておく必要があります。
Slider.OnChangeで変数の値を変更する
Slider.OnChange
UpdateContext({SliderValue:SliderValue+1})
このようにすると、無限にOnChangeの処理が実行されるようになります。
Slider.OnChangeでコレクションに追加する
処理がループで実行されるようになったので、ここでコレクションに追加していきます。
Slider.OnChange
Collect(colItems,{Index:SliderValue});
UpdateContext({SliderValue:SliderValue+1});
指定した回数で処理をやめる
このままでは無限に実行されてしまうので、条件分岐で変数を変更しない分岐を作ります。
Slider.OnChange
Collect(colItems,{Index:SliderValue});
If(
SliderValue < 10,
UpdateContext({SliderValue:SliderValue+1})
)
上記の例では固定値の10を用いていますが、スライダーやドロップダウンで選択した値を参照させ、ユーザが選択した任意の数字を渡すことも可能です。
処理を発火する
処理を発火するには、Sliderコントロールのリセットを行います。
Screen.OnVisible
Reset(Slider)
これでコレクションを動的に作成することができます。
スライダーのループ処理については下記のリンクを参考にさせていただきました!
参考URL
【#PowerApps】PowerAppsでタイマーコントロールを使わずにタイマーコントロールよりも高速なループを実行する方法
Power Apps DisplayMode.ViewのFormのDataCardに罫線をいれる
DisplayMode.EditのFormだとDataCardに罫線を出せますが、DisplayMode.ViewのFormでは出すことはできません。
プロパティも揃ってて設定もできるのに。一見できそうで歯がゆい・・・。
なので、一回諦めましょう。
どうしてもやりたい場合は四角アイコンとか使って人力でやるしかないです。
四角アイコンで罫線を再現する
各DataCardに四角アイコンを設置することで罫線的なものを再現できます。
ちまちまいれていきましょう。
注意点
DataCardのロックを解除しないと挿入できないことと、四角アイコンは再背面に設定することに気をつけて設置してください。
感想
出せないのはまだわかるので、項目を非表示にするとかなんかして欲しいですね。
場合によりますが別の案としてDisplayMode.Editで作ってしまうのもありかもです。
PowerApps Gallery.Selectedが取得できないときは・・・
どうも環境によりGallery.Selectedが正常に動かない場合があるみたいです。
ページの読み込みが完了していない状態でギャラリーを選択した場合や、iOSでの不具合報告もあるようで。
安全に取り扱うには、Selectedを使うのをやめてThisItemを変数に格納するようにしたほうがいいかもしれません。
同じスクリーンで使用する場合
Gallery.OnSelect
UpdateContext({SelectedItem:ThisItem})
遷移先のスクリーンで使用する場合
Gallery.OnSelect
Navigate(Screen2,ScreenTransition.None,{SelectedItem:ThisItem});
上記どちらかの方法で代用が可能です。
※複数画面で使用する場合はグローバル変数に入れてください。
Gallery.Selectedの値が怪しかったら試してみてください。
Power Apps で横スクロールアクションゲームを作る 記事まとめ
Power Apps で横スクロールアクションゲームを作る の記事一覧です。
上から順にやってみよう!
Power Appsで横スクロールアクションゲームを作る ジャンプ編
https://zezeze.hateblo.jp/entry/2019/12/25/053353
Power Apps で横スクロールアクションゲームを作る 横スク編
https://zezeze.hateblo.jp/entry/2020/02/15/090558
Power Apps で横スクロールアクションゲームを作る ステージ構成編
https://zezeze.hateblo.jp/entry/2020/02/15/092135
Power Apps で横スクロールアクションゲームを作る コイン取得編
https://zezeze.hateblo.jp/entry/2020/02/15/092429
Power Apps で横スクロールアクションゲームを作る Collection化編
https://zezeze.hateblo.jp/entry/2020/02/15/092520
全部できたら、カスタマイズしてみるのも勉強になりますよ!
コイン取得のSEをつけたり、BGMをつけたり、タイトル画面を着けたりゲームオーバーを作ったりしてみたり。スコアもつけてみたり。いろいろ試してみてください!
Power Apps で横スクロールアクションゲームを作る Collection化編
1年以上前に作ったゲームアプリですが、今更ながら作り方の解説記事を書いてみます。
↓昨年9月に行われた海外コミュニティ主催のPowerAppsゲーム作成コンペで優勝したアプリ
https://twitter.com/bothernpa/status/1045855585797722112
こんな感じの横スクロールアクションゲームを去年作成しました。
いくつかのセンテンスに分けて、作り方の解説記事を書いていきます。
前回まででとりあえず横スクロール的なものを作成することができました。
ただ、今の所固定のステージをループしているだけです。
もう少し手を加えてコレクションからステージをロードするようにしましょう。
ちょっと難易度が上がるのでがんばってください。
基本的な考え方は以前と同様なので、細かいところは説明しません。
自身で読み取ってみてください。そういうこともいい勉強になると思います。
手順
・ステージ読み込みコレクションMapsを初期化
・ステージ設定コレクションStageControlsを初期化
・LoadingIDを初期化
・CellLengthを初期化
・StageImage.Y を変更
・Coin.Visible を変更
・コイン当たり判定改修
・GroundYの取得処理を改修
・ステージロード処理を追加
前提条件
以前までのステップをすべて完了している事が前提です。
ステージ読み込みコレクションMapsを初期化
ステージのMAP設定をコレクションに入れておきます。
LookUpで使うIDと、セルの高さを表すCellHeightを設定します。
※もっとたくさん作成しないとすぐステージが終わってしまうので、ID:100くらい入れといたほうがいいです。エクセル使うと量産が楽。
Screen.OnVisible
ClearCollect(Maps,
{ID:1,CellHeight:1},
{ID:2,CellHeight:1},
{ID:3,CellHeight:2},
{ID:4,CellHeight:2},
{ID:5,CellHeight:1},
{ID:6,CellHeight:1},
{ID:7,CellHeight:2},
{ID:8,CellHeight:1},
{ID:9,CellHeight:2},
{ID:10,CellHeight:1},
{ID:11,CellHeight:1},
{ID:12,CellHeight:2},
{ID:13,CellHeight:1},
{ID:14,CellHeight:2},
{ID:15,CellHeight:3},
{ID:16,CellHeight:4},
{ID:17,CellHeight:3},
{ID:18,CellHeight:1},
{ID:19,CellHeight:1},
{ID:20,CellHeight:2});
ステージ設定コレクションStageControlsを初期化
Stage1 - 9の設定値をコレクションに入れておきます。
LookUpで使うIDと、StageImageコントロール、ステージの高さを表すStageY、CoinImageコントロール、コインの表示設定値CoinVisibleを設定します。
Screen.OnVisible
ClearCollect(StageControls,
{ID:1,StageImage:StageImage1_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 1,CellHeight)),CoinImage:CoinImage1_1,CoinVisible:true},
{ID:2,StageImage:StageImage2_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 2,CellHeight)),CoinImage:CoinImage1_2,CoinVisible:true},
{ID:3,StageImage:StageImage3_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 3,CellHeight)),CoinImage:CoinImage1_3,CoinVisible:true},
{ID:4,StageImage:StageImage4_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 4,CellHeight)),CoinImage:CoinImage1_4,CoinVisible:true},
{ID:5,StageImage:StageImage5_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 5,CellHeight)),CoinImage:CoinImage1_5,CoinVisible:true},
{ID:6,StageImage:StageImage6_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 6,CellHeight)),CoinImage:CoinImage1_6,CoinVisible:true},
{ID:7,StageImage:StageImage7_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 7,CellHeight)),CoinImage:CoinImage1_7,CoinVisible:true},
{ID:8,StageImage:StageImage8_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 8,CellHeight)),CoinImage:CoinImage1_8,CoinVisible:true},
{ID:9,StageImage:StageImage9_2,StageY:App.Height - (CellLength * LookUp(Maps,ID = 9,CellHeight)),CoinImage:CoinImage1_9,CoinVisible:true}
);
LoadingIDを初期化
ステージロード的な処理をするための、LoadingIDを初期化します。
LoadingIDをキーにMapsからLookUp()したりします。
最初の設定値は9にしておきます。
Screen.OnVisible
UpdateContext({LoadingID:9});
CellLengthを初期化
視認性向上と負荷軽減目的でセル1つ分の大きさを変数に入れておきます。
Screen.OnVisible
UpdateContext({CellLength:StageImage1_2.Width/2});
StageImage.Y を変更
StageImage.Yの設定をコレクションに対応した形に変更します。
StageImage1- 9 でIDが異なるので注意しましょう。
例:
StageImage.Y
LookUp(StageControls,ID = 1,StageY)
Coin.Visible を変更
CoinImage.Visibleの設定をコレクションに対応した形に変更します。
StageImage1- 9 でIDが異なるので注意しましょう。
例:
CoinImage.Visible
LookUp(StageControls,ID = 1,CoinVisible)
コイン当たり判定変更
コインの当たり判定をコレクションに対応したものに変更します。
Timer.OnStart
Patch(StageControls,
LookUp(
StageControls,
// 横方向の判定。
CoinImage.X <= PlayerCenterX && CoinImage.X + CoinImage.Width >= PlayerCenterX
&&
// 縦方向の判定。
CoinImage.Y <= PlayerImage_3.Y + PlayerImage_3.Width && CoinImage.Y + CoinImage.Width >= PlayerImage_3.Y
),
// Coinを非表示にする
{CoinVisible:false}
);
GroundYの取得処理を改修
GroundYの更新処理をコレクションに対応したものに変更します。
処理が1行で済むため、関数化するメリットは少なくなります。処理も軽くなります。
Timer.OnStart
UpdateContext({GroundY:LookUp(StageControls,StageImage.X < PlayerCenterX && StageImage.X + StageImage.Width > PlayerCenterX,StageImage.Y)});
ステージロード処理を追加
描画更新タイマーにステージロード的な処理を追加します。
今までの処理の一番下に追加します。
Timer.OnStart
// ステージロード仕様のための実装
If(
// 右に移動したステージがあるなら
!IsBlank(LookUp(StageControls,StageImage.X >= App.Width - 9)),
// LoadingIDを更新
UpdateContext({LoadingID:LoadingID + 1});
// LoadingCellHeightを更新
UpdateContext({LoadingCellHeight:LookUp(Maps,ID = LoadingID,CellHeight)});
// 読み込んだステージの高さに設定。コインの表示値も初期化。
Patch(StageControls,LookUp(StageControls,StageImage.X >= App.Width - 9),{StageY:App.Height - (CellLength * LoadingCellHeight),CoinVisible:true});
);
まとめ
以上で一通り完成になります。
ちゃんと分かる記事になっているか不安もあるのですが、後ほど完成形のアプリをアップする予定です。記事がわかりにくい方は完成形を見ながらやってみましょう。
余力のある方は処理の高速化に挑戦してみるのもいいと思います。
LookUp()で相対位置を指定しているところはLast(FirstN())にしたほうが早そうな気がしてます。
全然余裕という方は、一部説明していない機能もあります。是非ご自身で挑戦してみてください。
もちろんカスタマイズ、拡張していってもいいです。
面白いものができたらぜひ Twitter で #PowerApps #JPAUG 等のタグでツイートしてください!僕が喜びます。
この記事でPower Apps でいろいろやることの楽しさを伝えられていたら嬉しく思います。