【GameMaker:Studio2】ミニゲームを作るチュートリアル (Part.3)

GameMaker:Studio2でミニゲームを作るチュートリアルの最終回となります。
前回→→[【GameMaker:Studio2】ミニゲームを作るチュートリアル (Part.2)](https://qiita.com/2dgames_jp/items/845ab51687de5345345a)

## 横の壁を作る
Resources > Objects を右クリックして、Create Object を選びます。
![055.png](https://qiita-image-store.s3.amazonaws.com/0/43772/631f29aa-f6e8-1f73-2b8f-adc1ba962c01.png)

Nameを "objWall2" に変更して、＋アイコンから新しくスプライトを作ります。
![056.png](https://qiita-image-store.s3.amazonaws.com/0/43772/c61db1a2-9c48-1bff-7420-48857e0f2e5f.png)

Nameを "sprWall2" に変更して、「Import」を選びます。
![057.png](https://qiita-image-store.s3.amazonaws.com/0/43772/97ea4153-0c2f-f81a-0ded-b79607e6ab08.png)

取り込む画像は "wall2.png" を選びます。
![058.png](https://qiita-image-store.s3.amazonaws.com/0/43772/4d7b9e59-4bed-b6ec-8385-5ec57946facb.png)

Resources > Objects > objWall2 をダブルクリックして、エディット画面を開きます
「Solid」にチェックを入れるのを忘れていたので、入れておきます。
![060.png](https://qiita-image-store.s3.amazonaws.com/0/43772/e92867fc-082e-80da-d3a1-a2ff5ab3ad76.png)

この横壁(objWall2)との衝突イベントを objTako に設定していきます。
Resources > Objects > objTako をダブルクリックして、エディット画面を開きます。
Events から、Add Eventをクリックして、Collision > objWall2 を選びます。
![061.png](https://qiita-image-store.s3.amazonaws.com/0/43772/ba736c7c-36d6-8af1-6709-88407b5fa22f.png)

Toolbox に "move" と入力、「Set Speed」アクションアイコンをドラッグ＆ドロップして、以下のように設定します。
* Type: Horizontal
* Speed: hspeed * -1
* Relative: チェックを入れない

![062.png](https://qiita-image-store.s3.amazonaws.com/0/43772/5148cf4d-df97-cb6f-e3c5-f9534a41333d.png)

これは、水平方向(Horizontal)の速度を反転する設定となります。

では、衝突イベントが設定できたので、横壁(objWall2)をRoomに配置していきます。
Resources > Rooms > room0 をダブルクリックします。

Resources から objWall2 をドラッグ＆ドロップして、Alt＋マウスドラッグで横壁を配置します。
![game.png](https://qiita-image-store.s3.amazonaws.com/0/43772/383936a5-fdd2-c72d-417a-33ba9c2abfed.png)

間違えてはみ出した場合は、選択してDeleteキーで削除したり、Ctrl+Zでやり直したりします。

実行すると、横の壁で跳ね返りするようになります。

## たこ焼きを破壊できるようにする
マウスクリックすると、たこ焼きを消滅できるようにします。
Resources > Objects > objTako をダブルクリックしてエディターを開き、
Add Event > Mouse > Left Down を選びます。
![065.png](https://qiita-image-store.s3.amazonaws.com/0/43772/6d73d4a3-57b4-b9ae-0a65-2575869bb506.png)

これは、マウスを左クリックしたときに発生するイベントとなります。
Left Downイベントで、Toolboxに "instance" と入力して、ごみ箱のようなアイコン「Destroy Instance」を中央にドラッグ＆ドロップします。
![066.png](https://qiita-image-store.s3.amazonaws.com/0/43772/69fb43d0-1634-41af-5d13-e36b7164d583.png)

これはオブジェクトを破棄するアクションとなります。
![067.png](https://qiita-image-store.s3.amazonaws.com/0/43772/493731ec-ed43-e6c4-f669-0048fdba1dec.png)

続けて、Toolboxに "effect" と入力して、「Do Effect」アクションをドラッグ＆ドロップします。
![068.png](https://qiita-image-store.s3.amazonaws.com/0/43772/bf83077d-464c-21f8-8cee-b5b311f77b4b.png)

これはたこ焼きを破壊したときのエフェクトとなります。
設定値は以下のようにします。
* Type: Explosion
* Where: Below Objects
* Size: Medium
* X: 0
* Y: 0
* Colour: $FFFFFFFF

では実行して、たこ焼きをクリックしてみてください。
クリックするとたこ焼きが消えるようになったのですが、エフェクトは表示されません。
正確には、表示はされているものの、おかしな位置に表示されています。
よく見るとわかるのですが、たこ焼きをクリックするとゲーム画面の左上に何かもやのようなものが表示されています。
![070.png](https://qiita-image-store.s3.amazonaws.com/0/43772/d8a63e53-716d-5ce0-d03f-84dbc4cba871.png)

なぜこのようなことが起きるのかを確認するために、先ほど設定したエフェクトを確認します。
Resources > Objects > objTako > Events > Left Down のイベントの Do Eventアクションの設定を見直します。
設定値を X:0, Y:0 としていますが、これはゲーム画面の座標(0, 0)に表示するという意味です。
なお、ゲーム内では左上を座標(0, 0)として扱います。
![900.png](https://qiita-image-store.s3.amazonaws.com/0/43772/65a9286d-d26d-ce0a-d334-d9f9d245a6d4.png)

そのため、画面の左上にエフェクトが出ていました。
ちなみに画面の解像度の情報はRoomエディタの左下に表示されています。
![071.png](https://qiita-image-store.s3.amazonaws.com/0/43772/e7a85651-dfe8-fb09-b80d-e7bcbe28c8df.png)

エフェクトを表示する座標はゲーム画面を基準にするのではなく、たこ焼きの座標を基準に表示したいですよね。
たこ焼きを基準にした座標を使う場合は、「Do Effect」の「Relative」の項目にチェックを入れます。
![072.png](https://qiita-image-store.s3.amazonaws.com/0/43772/ffe2bf11-b73f-be0e-8e7b-c7339f2785fa.png)

Relativeにチェックを入れたら、実行してみましょう。
たこ焼きをクリックするとエフェクトを表示して消滅するようになりましたが、どこか座標がずれているようです。
![073.png](https://qiita-image-store.s3.amazonaws.com/0/43772/335ea2c7-9313-d29e-c976-a5bc97e81399.png)

これは原点の扱い方が、たこ焼きとエフェクトで異なるためとなります。
Resources > Sprites > sprTako をダブルクリックします。

エディターの中央あたりに注目すると、「Origin 0 x 0 Top Left」とあります。画像の左上にも何かのマークがあります。
![074.png](https://qiita-image-store.s3.amazonaws.com/0/43772/e5addc96-c66a-ba1b-f0ca-42c35a112b3e.png)

これはスプライトの中心を左上基準にしているためとなります。
そのため、エフェクトの発生が左上から行われてしまっていることになります。

これを解消するには、以下の2つのどちらかを選ぶ必要があります。
1. たこ焼きスプライトの基準座標を中央にする
2. エフェクトの発生位置をスプライト中心に移動させる

どちらもメリット・デメリットがあります。
例えば 1 の方法で解消するには、Top Left の指定を、Middle Centre に変更します。
![075.png](https://qiita-image-store.s3.amazonaws.com/0/43772/86d26e13-f60e-6d8c-1ee9-64d65c0910c8.png)

この設定にすると、スプライトの原点が中央になります。
![076.png](https://qiita-image-store.s3.amazonaws.com/0/43772/922a317d-9373-48c2-d264-53b0b9b2f031.png)

実行すると、たこ焼きの中心からエフェクトが発生するようになります。
(完全に余談ですが、ColorがColourだったり、CenterがCentreだったりするのは、GameMaker:Studio2の開発元のYoYo Gamesがアメリカの会社ではなく、イギリスのスコットランドの会社で、イギリス英語が使われているためです)

スプライトの中心を原点にしたときのデメリットですが、一番大きいのはRoomエディタ上での配置の扱いです。
例えば、左上基準であれば、グリッドに沿った位置に配置することができます。
![077.png](https://qiita-image-store.s3.amazonaws.com/0/43772/a14934f3-72a9-794e-8be8-4112db34e717.png)

これを中心を原点にしてしまうと、以下のようにグリッド上に配置されてしまうことになります。
![078.png](https://qiita-image-store.s3.amazonaws.com/0/43772/5981d16c-32bf-35cc-4e17-aa6054b624e9.png)

2のエフェクトの発生位置をスプライト中心に移動させる方法です。
sprTakoの設定を「Top Left」に戻して、objTakoの「Do Effect」の設定を以下のようにします。

* Type: Explosion
* Where: Below Objects
* Size: Medium
* X: 32 (Relativeにチェックを入れる)
* Y: 32 (Relativeにチェックを入れる)
* Colour: $FFFFFFFF

![079.png](https://qiita-image-store.s3.amazonaws.com/0/43772/d6b66ea7-2c6e-8056-1d67-0508113228e4.png)

たこ焼きのスプライトの中心が(32, 32)なのでそこに移動させていることになります。

デメリットは、中心を原点として扱っているオブジェクトに座標を渡すときに、毎回この変換が必要になることですね…。

長くなってしまいましたが、今回はどちらの方法でも問題ないので、好きな方法を選んで問題ありません。

## ゲームクリア判定の実装
最後にゲームクリア判定を入れます。
たこ焼きがすべてなくなったら、ゲームクリアとします。
Resources > Objects を右クリックして、Create Objectを選びます。

Nameには "objGame" と指定します。
ゲームの制御を行うだけなので、スプライトの指定はしません。
![080.png](https://qiita-image-store.s3.amazonaws.com/0/43772/a0aaf62d-02de-b6c8-278c-1e9ca6975471.png)


続いて、objGameのEventsから、Add Event > Step > Step を選びます。
![081.png](https://qiita-image-store.s3.amazonaws.com/0/43772/3723b0e3-cce6-7de7-c9c6-218649476a1f.png)

Stepイベントとはゲームの更新が行われるたびに呼び出されるイベントとなります。

Toolboxに "instance" と入力して、「If Instance Exists」アクションをドラッグ＆ドロップします。
![082.png](https://qiita-image-store.s3.amazonaws.com/0/43772/a81d63a9-93ff-aae2-d545-7bd86ccbc221.png)

「If Instance Exists」アクションは、「指定のオブジェクトが存在する場合」の処理を定義するものです。
「If Instance Exists」の設定は以下のようにします。
* Object: objTako
* Not: チェックを入れる

"Not"にチェックを入れることで、「指定のオブジェクトが存在しなくなった時」という条件の処理を定義することができます。
上記の設定内容は、「objTako」が存在しなくなった、という条件になります。
この「条件(クリア条件)」が成立した場合、ゲームを終了するアクションをつなげます。

Toolboxに "game" と入力して、「Exit Game」アイコンを選びます。
![083.png](https://qiita-image-store.s3.amazonaws.com/0/43772/dde95660-be95-5411-8952-52d9b9b1d9fa.png)

このアイコンを、「If Instance Exists」の右側の "Empty" の部分をめがけてドラッグ＆ドロップします。
![084.png](https://qiita-image-store.s3.amazonaws.com/0/43772/0c16b201-2c6e-8a31-2d85-ce24ce0d049c.png)

すると、「If Instance Exists」の下の部分から伸びた線が「Exit Game」につながります。
![085.png](https://qiita-image-store.s3.amazonaws.com/0/43772/f6028afd-aca9-0c15-becd-71906b9aacd3.png)

もしこれが右側から線が伸びてつながる場合は、条件が成立しなかったときでも実行されてしまうので、このような状態にならないように注意してください。
![086.png](https://qiita-image-store.s3.amazonaws.com/0/43772/dbef737f-af64-90d8-6a1d-e120b4e32ed9.png)

作成した objGame を Room に配置します。
Resources > Rooms > room0 をダブルクリックして、objGame を任意の場所に配置します。
![087.png](https://qiita-image-store.s3.amazonaws.com/0/43772/ec797f40-2ed4-c80a-7f08-155c13490e0a.png)

配置したオブジェクトが「？」アイコンになりますが、これはスプライトが指定されていないだけですので、問題ありません。

実行すると、たこ焼きがすべて消えた瞬間にゲームが終わります。

これだけだと突然すぎるので、何かメッセージを出します。
Resources > Objects > objGame をダブルクリックします。
Stepイベントを開き、Toolboxに "code" と入力して、
![088.png](https://qiita-image-store.s3.amazonaws.com/0/43772/30e57d62-c02a-8e36-1e72-e8e83fe8fe11.png)

「Execute Code」アクションを「Exit Game」の上あたりにドラッグ＆ドロップします。
![089.png](https://qiita-image-store.s3.amazonaws.com/0/43772/6890f2ef-0822-58fa-0762-b4eecd525ebe.png)

「Execute Code」アクションはGMLと呼ばれる独自スクリプトを実行するアクションとなります。
「Execute Code」には以下の文字を入力します。

> show_message("GAME CLEAR!");

![090.png](https://qiita-image-store.s3.amazonaws.com/0/43772/2710785b-c0cc-d606-c1c4-07bee448ab5e.png)

これは、ダイアログを表示して、"GAME CLEAR!" というメッセージを表示する命令となります。
実行してたこ焼きをすべてクリックすると、ゲームクリアメッセージが表示されます。
![091.png](https://qiita-image-store.s3.amazonaws.com/0/43772/f8e2c576-2a6e-4073-e704-48259d5a5060.png)

これにてミニゲーム作成のチュートリアルは終了となります。