コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

【JPPGB #8】ボールを射法投射してみよう


スポンサードリンク

はじめに

JPPGB #8のLT枠でお話したPower Appsでの射法投射の実装方法についてまとめています。

jppgb.connpass.com

こちらを参考に皆さんも是非Power Appsでのゲーム開発に挑戦してみてください!

射法投射

一覧

利用するコントロールと変数の一覧をまとめています。
上手く動かない場合など、作成漏れがないか。や各コントロールや変数の役割を確認したい際に確認してみてください。

利用するコントロール一覧

今回利用するコントロールはこちらです。

コントロール 役割
VelocityLbl 初速度を表示するラベル
VelocitySlider 初速度を設定するスライダー
AngleLbl 発射角を表示するラベル
AngleSlider 発射角を設定するスライダー
Circle 設定値に従って投げられるボール
ShotBtn ボールを投げるボタン
isGrandTgl ボールが地面に到達したら処理を止めるためのトグル
LoopTgl ボールの座標を計算するためのトグル
isLoopTgl デバッグ用の処理を緊急停止するためのトグル
IniBtn 初期化ボタン

利用する変数一覧

今回利用する変数はこちらです。

変数名 役割
acc 重力加速度
地球上では  9.81{m/s}^2 が重力加速度となるので、
初期値には9.81を設定しています
angle ボールを射法投射する角度
Degreeで表しています
time 射法投射を開始した時間経過
iniVelocity ボールを射法投射するときの初速度
circleX ボールのX座標の値
circleY ボールのY座標の値
loopFlg ボールを射法投射処理するためのフラグ

ボールを用意する

まずは射法投射するためのボールを用意しましょう。

図形より円(Circle)を追加します。
コントロール名は "Circle" とします。

ボールの初期位置は左下に設定したいです。

なので、初期化用ボタン("IniBtn")を追加して、ボタンが選択されたときに変数が初期化されるようにします。

IniBtn.OnSelect

UpdateContext({circleX: 0, circleY: App.Height - Circle.Height});

ボールの座標にはこれらを適用したいので、それぞれ設定しましょう。

Circle.X

circleX

Circle.Y

circleY

私のブログをちょくちょく見てくれている方は、何度も聞いていることかもしれませんがこのように初期化用ボタンを用意しておくと、開発時に大変便利なのでおすすめです。

この初期化処理は画面表示時に実行したいので以下のような式も追加しておくといいかもです。

Screen1.OnVisible

Select(IniBtn)

射法投射に必要なパラメータと計算方法

射法投射を計算するためには以下のパラメータが必要になってきます。

  1. 初速度 (initial velocity,  v_0):
    ボールが放たれた瞬間の速度です。
  2. 射角 (launch angle,  θ):
    ボールの放物線の最高点からの角度です。
  3. 重力加速度 (acceleration due to gravity,  g):
    通常、地球では約  9.81{m/s}^2 です。

これらのパラメータを用いて、ボールの水平方向の位置 ( x) および垂直方向の位置 ( y) 、時間 ( t) とすると、以下のように表すことができます。

  • 水平方向の位置 ( x)
     x = v_0 \times \cos \theta \times t
  • 垂直方向の位置 ( y)
     y = v_0 \times\sin \theta \times t - \frac{1}{2} g t^{2}

式を見てもらえばわかりますが、今回は空気抵抗などは考慮していないです。

射法投射に必要なパラメータを用意する

先ほど説明したパラメータを用意します。

まずは初期値として用意する必要があるので以下のように初期化ボタンの設定に以下式を追記します。

IniBtn.OnSelect

// 初期値
UpdateContext(
    {
        time: 0,
        iniVelocity: 100,
        angle: 45,
        acc: 9.81
    }
);

timeが時間( t)
iniVelocityが初速度( v_0)
angleが射角( θ)
accが重力加速度( g)
ですね。

初速度( v_0)と射角( θ)は都度変更できるようにしたいです。
よって、それぞれの値を表示するためのラベルと値を変更するためのスライダーを用意します。

初速度用

VelocityLbl.Text

$"初速度: {iniVelocity}"

VelocitySlider.OnChange

UpdateContext({iniVelocity: Self.Value})

射角用

AngleLbl.Text

$"角度: {angle}"

AngleSlider.OnChange

UpdateContext({angle: Self.Value})

射法投射によるボールの座標を計算する

射法投射によるボールの座標を計算するためには、時間経過ごとに座標を再計算するような繰り返し処理(ループ処理)が必要になってきます。

Power Appsでループ処理というとタイマーコントロールを用いたものやスライダーコントロールを用いたものがありますが、今回は折角ですので私がこの前紹介したトグルコントールを用いたループ処理、トグループを利用したいと思います。

トグループの詳しいやり方についてはこちらの記事をご参照ください。

koruneko.hatenablog.com

トグルによるループ処理を行うので、トグルコントロールを追加します。
こちらの名前は "LoopTgl" としてください。

またループ処理の設定がミスったとき用にループ処理を緊急停止できるようのトグル、"isLoopTgl"も追加しておいてください。

ループ処理を開始するかを判定するためのフラグが欲しいので、変数で用意してあげます。
また、ループ用のトグルコントロールは初期化時にリセットしておいてあげましょう。

初期化ボタンの設定に以下式を追記します。

Reset(isLoopTgl);

// ループフラグ
UpdateContext({loopFlg: false})

ループ処理が行われる仕組みを設定します。

ループ用トグル("LoopTgl")に以下を設定します。

LoopTgl.Default

loopFlg && isLoopTgl.Value

LoopTgl.OnChange

UpdateContext({loopFlg: !loopFlg})

トグルのチェック状態を切り替えることによりループ処理を実現する感じですね。

ループ処理緊急停止用のトグルの状態が変わったときにはループ処理用のトグルの状態をリセットする用にします。

isLoopTgl.OnChange

Reset(LoopTgl)

これでループの仕組みが完了したのでボールの座標を計算する処理を設定していきます。

ループ用トグルがチェックされたとき(OnCheck)にボールの座標を計算するようにします。

LoopTgl.OnCheck

UpdateContext(
    {
        circleX: iniVelocity * Cos(Radians(angle)) * time,
        circleY: (App.Height - Circle.Height) - (iniVelocity * Sin(Radians(angle)) * time - 0.5 * acc * Power(time, 2))
    }
)

Power Appsの三角関数はDegreeではなくRadianで扱われるのでRadians関数でDegreeからRadianに変換を行っています。

learn.microsoft.com

また、Power AppsではY座標の値が小さくなるほど画面上部にいき、値が大きくなるほど画面下部になりますので、ボールの初期値から射法投射で計算された値を減算するようにしています。

ループ用トグルがチェックが外れたとき(OnUnCheck)に射法投射後の時間を経過されるようにします。

UpdateContext({time: time + 0.2});

時間は0.2ずつ加算されるようにしています。

ここで加算される数値が大きいほどボールは早く動きます。
ご自身でいい感じに設定してください。

また、このままでは射法投射後ずっとボールの座標が計算され続けてしまいます。
今回はとりあえずボールが半分画面下部に埋まったところでループ処理を止めるようしたいと思います。

ボールが画面下部に埋まったことを判断する仕組みとしてトグルコントロールを用意します。
名前は"isGrandTgl"とます。

こちらのDefaultに以下式を設定します。

isGrandTgl.Default

circleY <= App.Height - Circle.Height / 2

これにより、ボールが画面下部に半分埋まっているときはトグルのチェックが外れ(false)、それ以外の場合はトグルがチェック(true)になるようになります。

これをループ処理のトグルに組み込みます。(式を上書きしてください。)

LoopTgl.Default

loopFlg && isLoopTgl.Value && isGrandTgl.Value

ボールを射法投射する

最後にボタンが押されたら射法投射されるようにします。

"ShotBtn"という名前のボタンを追加して、以下のように設定します。

ShotBtn.OnSelect

UpdateContext({loopFlg: true});
Reset(LoopTgl)

これでボール("Circle")が射法投射されるようになりました!

おわりに

Power Appsでもゲーム(動くもの)を作成しようとすると、数学や物理の知識がちょっとだけ必要になってくる場面があります。

学生時代を思い出してみて、Power Appsで利用可能なコントロールや式を用いて皆さんもPower Appsでのゲーム開発に是非挑戦してみましょう!

そしてゲーム開発に挑戦してみた暁には是非JPPGBでの登壇をお願いします!
初心者の方も大歓迎です!!

JPPGB登壇に興味のある方は@koruneko32767までお願いしますー


スポンサードリンク