Power Appsで簡単なRPGを実現してみよう！- Part1

こんにちは！

出戻りガツオ🐟久しぶりの投稿です。
今回は、Power Appsのgalleryを使用した横スクロールゲームの操作の実現について
解説します！

動画はこんな感じ！

<iframe width="560" height="315" src="https://www.youtube.com/embed/7iP9BDtRbII" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 先にクレジットを表記
 - 著作権　Loose Leaf
	 - ●MACK●http://homepage3.nifty.com/looseleaf/

**参照**
 - ドット絵世界

http://yms.main.jp/page-m1/looseleaf1.html

今回の内容の素材のほとんどがこちらから出てきます。
ご利用の際は必ず参照してください。

# 1. 必要なモノ
準備するもの一覧です。
 - characterの画像
	 - 静止画 - 前向き
	 - 静止画 - 後ろ向き
	 - 静止画 - 右向き
	 - 静止画 - 左向き 
	 - GIF画像- 前向き
	 - GIF画像 - 後ろ向き
	 - GIF画像 - 右向き
	 - GIF画像 - 左向き
 - タイル
	 - 壁
	 - 草原など
	 - 透明の画像（なにも映っていないPNG）

行動を表現するうえでTimerコントロールを使って、動きを表現することもできます。
しかし、gif画像が断然ラクです。

iPhoneでも自動で作れますが、こちらのサイトでできますので、使って今回は実現しました。

https://www.bannerkoubou.com/anime/

**さあ、材料をそろえたら始めましょう！**

# 2. 構成

イメージとして二層構造にしています。
1. 下地となるMap
1. 動き回るキャラクター オブジェクト


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2de2aa0c-435d-8169-c890-ac75bef53c2c.png)

他に装飾するオブジェクトは、無理にgalleryに乗せる必要はありません。
galleryのテンプレートサイズに合わせて、自由に載せていくだけで違和感は出ないからです。

ドラッグで動かしていくとズレやすいですが、数値単位1でXとYを修正すると、上手く配置できます。

**大切なことは適切な場所に乗せていく感覚です。**

# MAP
まずは**水平ギャラリー**を用意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/d8d62094-63ca-510a-96e5-7ffa87c92d0a.png)

空の水平ギャラリーでもかまいません。

マスの作り方ですが、`TemplateSize`プロパティ（**テンプレートのサイズ**）を利用します。
これがマスの横幅に該当します。

そして縦幅は`WrapCount`プロパティ（**折り返しの数**）で、行に分割することができます。
縦幅は、ギャラリー全体の`Height`プロパティ（**縦幅**）を等分に分割して算出できます。

ですので、ギャラリーの全体の`Height`プロパティ（**縦幅**）を、**60 × 8 = 480**とすることで
ギャラリーの各レコードが正方形になります。

ちなみに、ギャラリーの全体の`Width`プロパティ（**横幅**）も、60 * 横のマス数に設定されないと
美しく整いません。ですので、**60 × 20 = 1200**とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/6e5920fb-d385-fc9a-e1d8-05723cc480e2.png)

### ・ 表形式で整理！
コントロールは水平ギャラリー、親となるフレームになります。

|プロパティ|Property|値|メモ
|---|---|---|---
|幅|Width|1200|60 * 横のマスの数（列数）
|高さ|Height|480|60 * 縦のマスの数（行数）
|折り返しの数|WrapCount|8|縦のマスの数
|テンプレートのサイズ|TemplateSize|60|マスの横幅

さて、この中でタイルの区分けをしていきたいと思います。
`Sequence`関数で要素を見てみましょう。

```plaintext:ギャラリーのItemsプロパティ
Sequence(160)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/5ba227a0-9a6c-4a93-047e-0ac2a3d920ea.png)

### タイルの区分け

移動させたくないエリアは下記の通りとします。※赤で塗りつぶされたマスです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4c317ce4-4c57-f956-b86d-d86f661de88a.png)

雑ですが、`UpdateContext`で、赤で塗りつぶされたマスの番号を設定します。

```plaintext:移動できないエリア
UpdateContext(
    {disableArea:
        [
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 16, 17, 19, 21, 23, 24, 25, 27, 29, 32, 33,
            40, 41, 48, 49, 56, 57, 60, 64, 65, 73, 74, 81, 89, 92, 93, 97, 104,
            105, 112, 113, 120, 121, 126, 127, 128, 129, 132, 135, 136, 137, 140, 143, 144, 145,
            148, 152, 153, 154, 155, 156, 157, 158, 159, 160
        ]
    }
);
```

これによるメリットは、ギャラリーのデータソース`Items`の中でも、インデックス番号を`in`句で判定することにより、タイルの基本的な区分けが出来るからです。

- 移動可能なエリアに草原のタイル
- できないところに壁のタイル

となるようにしましょう。

**1 まずは全マスに草原のタイルを`Image`として最背面に配置する。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2ff1cc1b-3e48-d87c-60e9-57c23b8caf97.png)

Imageコントロールを追加しています。縦横のサイズは`TempleteSize`から書くのも良し、
直書きでも問題ないです。

注意点としては`Image`プロパティで画像の位置を**拡大して表示**にしておくとピタっとはまります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/39c4ebec-8709-82a4-56bd-7888b512f522.png)

**2 次に必要なところに、壁か無色透明の`Image`を乗せる**
他のやり方もありそうですが、移動不可能なエリアを`disableArea`として宣言しています。

- 移動不可能なエリアに、壁のタイル
- それ以外に無色透明のタイル

こちらを乗せます。

無色透明な画像って意味がわからん表現ですよね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/346a6a07-a3d9-7ec7-fea7-d75bbdbc49c3.png)
PowerPointで、四角形の図形を書いて、塗りつぶしなし、枠線なしで`png`で図として保存すれば、それができます。

なんにも映らない透明な図の出来上がりです。
フォトで見ても何も映りません・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/d3a2f97a-e2dd-a4c9-cc26-0a3a7cc24025.png)

これで、草原タイルの上に乗せるイメージ（もといタイル）を変数でコントロールします。
- `disableArea`にインデックスが入っていたら壁のタイル
- そうでなければ何も映らないタイル
とします。

こちらで下地ができあがります。
関数は以下の通りとなります。

```
// 移動できない範囲
UpdateContext(
    {disableArea:
        [
            1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24, 25, 32, 33,
            40, 41, 48, 49, 56, 57, 64, 65, 73, 81, 89, 97, 104,
            105, 112, 113, 120, 121, 128, 129, 136, 137, 144, 145,
            152, 153, 154, 155, 156, 157, 158, 159, 160
        ]
    }
);

// Collect関数でデータソースを追加方式で積み上げていく
ForAll(Sequence(160),
    If(ThisRecord.Value in disableArea,
        Collect(maps,{index: ThisRecord.Value,obj: wall}) ,
        Collect(maps,{index: ThisRecord.Value,obj: _null})
               
    )
);
```

ゲーム画面の`OnVisible`に`ClearCollect`関数を上記にまず書くことがStep1です。
各レコードの`visible`プロパティの制御でもできそうですが、なんとなく今回はこうしました。


# メインキャラクターの移動
移動を表すために、Mapと同様の水平ギャラリーを用意します。
データソース`Items`はこちらです。
```
// ###########################
// All Null
// ###########################
ForAll(
    Sequence(160),
    Collect(moves,
    {index: ThisRecord.Value,obj: _null})
);
// ###########################
// Init
// ###########################
UpdateContext(
    {
        _index:68,
        _me:front
    }
);
// こちらで初期の位置を制御
Patch(moves,First(Filter(moves,index=_index)),{obj:_me});

```
データソースが異なるだけで、
- X
- Y
- Height
- Width

これらのプロパティ値は、Mapと全て同様です。
`Patch`関数で主人公キャラクターの初期の位置と画像を表しています。

**Map**の上にこのようなギャラリーを乗せるイメージになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/bed8148d-cda5-e026-ae38-8018a42f062d.png)

重なるとこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/5bc572bc-da49-b746-981d-50bd8caa480e.png)

それらしいですね。
さて、これに動きをつけたりするなど、ゲームらしい要素を追加していきたいところですが、
結構長くなってきたので、一旦ここまでとします。

**動きの部分については次のステップで解説したいと思います。**

**それでは皆様、良いPower Apps Lifeを！**