Scratchで点取ゲームを作ってみた

## これは何

Scractchで昔作った点取ゲームを発掘したので、振り返りがてら作り方を解説していきます

:::note
筆者はエンジニアではないので、設計などがスマートでないと思います:pray:
:::

完成品はこちらになります

https://scratch.mit.edu/projects/765061622/

(学生時代に使ってたアカウントにログインできなくなったので新しく作成したアカウントにログインできなくなったので、過去に作ったプロジェクトをリミックスして作成してます)

## ゲームの概要

ゲームは簡単な点取ゲームです。

- MAP内に宝箱が4つ配置されていて、宝箱にタッチするとポイントが溜まります。
- MAP内を彷徨いている敵キャラがいて、敵キャラにタッチすると初期位置に戻りライフが1減ります。
- ライフが0になるとゲームオーバーです。
- 宝箱を4つ開けると、ゲームクリアです。

作成したゲームのリンクはこちらです。

https://scratch.mit.edu/projects/228478035/

## ゲームを作る

### 何を作るか考える

Scratchでできることから、作りやすそうなゲームを考えます。

Scratchにはあらかじめ、「X歩動かす」「大きさをXずつ変える」などのコードが用意されていて、これらを組み合わせてプログラムを組んでいきます。

ざっくりと用意されているコードを整理してみました。

名前|できること
-|-
動き|動かす、回す、座標をかえるなど動きを制御する
見た目|吹き出しを出す、コスチュームや背景、大きさを変える、表示非表示するなどの見た目を制御する
音|音を鳴らしたり止めたり音量を変えるなど音を制御する
イベント|キーが押された時、背景がhogeになった時などイベント発火のタイミングを作ったり、メッセージを送るなどのイベントを起こす
制御|待つ、hogeまで繰り返す、ずっと、もしhogeならなど、条件に応じてプログラムを制御する
調べる|特定のオブジェクトや色に触った、マウスが押されたなどのイベントの発生や現在の年やユーザー名などを取得する
演算|四則演算やAND, OR, NOTなどの計算や制御をする
変数|変数を作成する
ブロック定義|ブロックを作成する

例えば「動き」でキャラクターの位置を動かし、「調べる」でキャラクターが橋に触れたかを取得し、「制御」でもしキャラクターが端に触れたらという発火条件を作り、「見た目」で吹き出しを出す のように組み合わせて簡単にプログラムを作ることができます。

![scratch.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/8ae2ff06-eb75-2f4e-5645-778944b187fc.gif)

また、Scratchには様々なキャラクターを歩いたり飛んだりさせることができる素材が用意されており、これらを活用して簡単にキャラクターを動かすことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/e82b4745-423d-f44e-c4f9-58df997e6bea.png)

ということで、今回はこれらを活用して「ゲームの概要」で紹介したような点取ゲームを作っていきます。

### 必要な素材を洗い出す

動かす自キャラクターと敵キャラクターはScratchで用意されているものを使えるで、背景のMAPと宝箱を用意します。

背景と[ドット絵世界](http://yms.main.jp/)さんから素材をお借りして作成しました。

![background.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/36a78d63-35e2-e534-77bc-6ab7d56c12b8.png)

宝箱も[ドット絵世界](http://yms.main.jp/)さんからお借りしています。

### 必要な挙動を洗い出す

- 自キャラクターを移動する
- お邪魔要素
    - 敵キャラクターが移動している
    - 敵キャラクターにぶつかると、LIFEが1減り、初期位置に戻る
    - MAPの「木」の部分の上は移動できない
    - MAPの「水」の部分に入るとLIFEが1減り、初期位置に戻る
    - LIFEが0になるとゲームオーバー
- 点取要素
    - 宝箱に触れると、SCOREが1増える
    - SCOREが4になるとゲームクリア

### ゲームを作る

素材の準備や作るものが決まったので、ゲームを作っていきます。

最初に使うスプライトや背景をプロジェクトに追加します。
スプライトとは、Scratchで使用するキャラクター画像のことです。

右下のプラスボタンから作成した画像を読み込んだり、Scratchに用意されているスクラッチを選択することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/da391695-d2cd-bf3d-75dd-436373c2f871.png)

### 自キャラクターを移動する

まずはキャラクターを用意して矢印キーで移動できるようにします。

矢印の各キーが押された時に、移動する距離を定義し移動する方向に合わせたコスチュームに変更して、x座標もしくはy座標を変えることで移動させます。

歩いているように見せるために、右足を上げている画像と左足を上げている画像を交互に出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/4ee2b663-c332-2e38-ad08-4125615b5d33.png)

### 敵キャラクターが移動している

今度は敵キャラクターを動かしていきます。
敵キャラクターは同じ場所をループで移動しているようにしたいので、右端まで右に向かって歩く、左端まで左に向かって歩くを繰り返させて移動させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/ac3f9893-7712-cda8-3dd7-34faa0ce2d2a.png)

### 敵キャラクターにぶつかると、LIFEが1減り、初期位置に戻る

的キャラクターにぶつかった時の挙動は、メインキャラクターに定義していきます。

「もし~~に触れたら」というブロックで触れたかどうかの判定ができるので、そのブロックを利用します。
LIFEを変数で定義し、敵キャラクターに触れた時に、-1ずつ値を変えます。
ぶつかったことがわかるように音を出し、ぶつかった後はスタート地点に戻します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/d21e4e9e-793a-0638-6ae6-beea6f6fd5d8.png)

### MAPの「木」の部分の上は移動できない

次に移動できない部分で矢印キーで移動できないようにします。

これはスマートなやり方が思いつかなかったのでかなり力技で作っています...
木の位置を計算して、木にぶつかりそうになったら位置を戻すという挙動を作っています。

MAPを全てスプライトで作成して並べて「~~に触れた」ブロックを使えるようにしても良かったのですが、Scratch上で位置調整をするのが面倒で背景画像にしてしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/f4c6f744-1df4-2f24-3d9c-3b947ce98a20.png)

### MAPの「水」の部分に入るとLIFEが1減り、初期位置に戻る

水に触れた判定は、色に触れたらで作っています。そのまま判定を使うと頭が水に触れても落ちた判定になってしまうので、自キャラクターに青い靴を履かせて落ちた判定に使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/283ca6a9-be17-6b94-b857-ef73ee0d4e9f.png)

### LIFEが0になるとゲームオーバー

そして、LIFEが0になったら音を鳴らして背景を変えてゲームオーバーにします。
また、LIFE=0になった時は自キャラクターや敵キャラクターなどの不要なスプライトを隠すようにしてます。

ゲームオーバーにする|不要なスプライトを隠す
-|-
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/9d9275db-3805-0c19-8c32-7e8b3d931634.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/0246a484-7c25-3506-9540-756a2f2ce331.png)

### 宝箱に触れるとSCOREが1増える

単純に「もし宝箱に触れたら1増やす」にすると、触れている間無限に点数が増えてしまうので、変数を作って「その宝箱にすでに触れたかどうか」を判定します。

最初は0にしておいて、isTreasureNOpen=0かつ宝箱に触れたら、SCOREを1増やし「isTreasureNOpen」を1にします。

キャラクターのコード|宝箱のコード
-|-
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/975b3afe-9f30-5c88-e859-28c1414d06f8.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/8379d4de-fbf1-934b-146f-706c1a6f63d6.png)

また、宝箱側でもキャラクターと触れたかを判定し、キャラクターに触れたらコスチュームを宝箱が開いているものに変更します。

### SCOREが4になるとゲームクリア

SCOREが4になったらゲームオーバーの時と同じように背景を変え、キャラクターなどの不要なスプライトを非表示にします。

ゲームクリアにする|不要なスプライトを隠す
-|-
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/3eb04eae-b038-0b60-7100-53f78080ddaf.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/aecd76b6-d195-3814-4e88-93a01e79f16e.png)

ついでに風船を飛ばしてみます。

クローンを作る機能があるので、風船を1つとふわふわと飛んでいくブロックを定義し、クローンを作ってたくさんのふわふわ飛んでいく風船を作ります。

コスチュームを複数用意しておいて、どのコスチュームにするかに乱数を作ると、色々な種類の風船をランダムに飛ばすことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/79e78901-404a-eabe-a6d2-a338e75bb741.png)

### 最後に

このままだと、スタートボタンを押した時にキャラクターの位置や非表示などが受け継がれてしまうので、諸々の設定を初期値に戻すようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/f6118015-d28c-c996-90c6-d49c1bb7850f.png)