Power Apps でゲームを作る~アニメーション編~ #Power Platformリレー

こんにちは!Power Apps のキャンバスアプリの可能性を信じる男、サトハルです。

「Power Apps って何ができんの?」って聞かれたときには

「意外となんでもできるよ」って答えてることにしています。

今回はそんな Power Apps の可能性を探るべく、本来の用途(ローコードDX)からほど遠いグラフィカルなゲームアプリの作成に挑もうと思います。

千里の道も一歩からということで、先ずはベーシックな「ブロック崩し」を作ります。

本記事ではその中でも更にベースになる「アニメーション」部分にフォーカスして解説をしたいと思います。

必要なコンポーネントを用意する

今回のアニメーションを作るにあたって必要なものは以下のようになります。

それぞれを詳しく見ていきましょう。

1,Container

普段はコンポーネントをまとめる用途で用いる Container ですが、今回はボールが跳ね返る枠としての役割を担っています。

Container の中に入っているコンポーネントは Container の中だけの座標系になるのがとても都合が良いです。

このことについては後で詳しく解説します。

また、 BorderThickness プロパティを5にしておくことで枠線を表現する役割も果たしています。

2,Circle

Power Apps 標準の丸いアイコンです。

こいつのXとYプロパティに変数を指定することでボールの動きを表現しています。

ここで、先ほど Container の所で触れた座標系についての補足をしたいと思います。

わかりやすいように一旦 Circle のXとYを0にします。

すると、Screen ではなく Container の端っこに表示されていることがわかります。

これが Container の中だけの座標系ということです。

「ボールの座標が0以上であれば少なくとも左と上にはみ出ることがない」と言い換えるととってもハッピーなことがわかりますね。

また、Circle のx,y座標は Circle コンポーネントの円を囲う四角形の左上の角の座標であることもわかります。

3,Label

今回は単純にボールの座標を表示しているだけです。

4,Timer

アニメーションの要となるコンポーネントです。

画面上のどこにおいてもいいですが、Visible プロパティは false にしておきましょう。

ロジックを追加する

ボールが移動する仕組みは非常に単純です。

1,Timer コンポーネントが数えた周期毎にボールの速度変数を座標変数に足す

2,「壁に当たった」と判定したら速度変数の符号を反転させる

この二つをx方向とy方向のそれぞれに行えばOKです。

0,事前準備

速度変数と座標変数はページを表示する瞬間に初期化します。

Screen の OnVisible プロパティ上で UpdateContext 関数を使って変数を設定しましょう。

今回は以下のように設定しました。

UpdateContext({
    ball_vx:20,
    ball_vy:10,
    ball_posx:15,
    ball_posy:20
});

1, Timer コンポーネントが数えた周期毎にボールの速度変数を座標変数に足す

Timerコンポーネントが数える周期は Duration プロパティで設定できます。

単位はミリ秒になります。

とりあえず今回は30にしておきました。

続いて、Timer コンポーネントが指定したカウントを数え終えた瞬間に実行される関数は OnTimerEnd プロパティに書きます。

UpdateContext(
    {
        ball_posx: ball_posx + ball_vx,
        ball_posy: ball_posy + ball_vy
    }
);

ここでは本当に単純に足し算をしてるだけになります。

2, 「壁に当たった」と判定したら速度変数の符号を反転させる

OnTimerEnd プロパティの中に上記の内容に加えて、壁で反射する処理も追加します。

x軸に注目すると、まず左端に当たっているかどうかを判定します。

前述の通り、x座標が0未満であれば壁に当たっている(厳密にははみ出しているけど今回は簡単のためそれも良しとしています)と判定できます。

左端に当たっていない場合、続いて右端に当たっているかを判定します。

Circle のx座標は円の左端なので幅の分を考慮する必要があります。

また、上限は Container の幅を使って指定すればよいでしょう。

左右どちらかに関係なく、当たっている場合は速度を反転します。

この一連の流れをy軸と上下の端に対しても行えば壁で反転する仕組みの実装は完了です。

If(
    ball_posx < 0,
    UpdateContext({ball_vx: -ball_vx}),
    If(
        ball_posx + Circle1_1.Width >= Container1.Width,
        UpdateContext({ball_vx: -ball_vx})
    )
);
If(
    ball_posy < 0,
    UpdateContext({ball_vy: -ball_vy}),
    If(
        ball_posy + Circle1_1.Height >= Container1.Height,
        UpdateContext({ball_vy: -ball_vy})
    )
);

まとめ

簡単なロジックにしたがってアニメーションさせただけですが、それっぽい動きをしているのではないでしょうか。

Timer コンポーネントを非表示で追加する所は Power Apps 特有って感じで面白い所です。

今回はボールを跳ねさせましたが、文字列を流したり画像を動かしたりもできるので意外と使いどころがあるかもしれません。

本記事でPower Apps の可能性を感じて頂けていたら幸いです(?)

(おまけ) OnTimerEnd プロパティの全文

UpdateContext(
    {
        ball_posx: ball_posx + ball_vx,
        ball_posy: ball_posy + ball_vy
    }
);

If(
    ball_posx < 0,
    UpdateContext({ball_vx: -ball_vx}),
    If(
        ball_posx + Circle1_1.Width >= Container1.Width,
        UpdateContext({ball_vx: -ball_vx})
    )
);
If(
    ball_posy < 0,
    UpdateContext({ball_vy: -ball_vy}),
    If(
        ball_posy + Circle1_1.Height >= Container1.Height,
        UpdateContext({ball_vy: -ball_vy})
    )
);

参考

Power Apps のタイマー コントロール – Power Apps | Microsoft Docs