この連載では、Scratchで本格ゲームの中身を調べる方法を解説しています。第3回では、全体のメッセージ呼び出しからちょっと離れて、各スプライトが、メッセージからどのように呼び出されているのか調べていきます。
- 第1回:スプライトを洗い出す
- 第2回:スプライトとメッセージの関係
- 第3回:恐竜のコードをどう呼び出すか
- 第4回:個別の処理を見ていく
題材には、恐竜ランニングゲームを使っています。
前回は、ゲーム画面の切り替わりとメッセージが対応していることを見てきました。
- TITLEメッセージ:タイトル画面を表示
- STARTメッセージ:ゲームプレイの開始
- CRASHメッセージ:恐竜の衝突 → スコア画面の表示
- RESTARTメッセージ:ゲームプレイの再スタート
本格的なゲームの全体像を把握するには、細かなところは気にしないで、メッセージとスプライトの関係をざっくりと見ていくのが良いと思います。
でも、各スプライトの処理をどう呼び出しているのか、ある程度理解しておかないと、モヤモヤしますよね。そこで、メッセージを受け取ったスプライトが、どのように処理を進めているか、少し掘り下げてみましょう。
dinoスプライトがSTARTメッセージで何をするか
まずは、dinoというスプライトのコードを調べます。dinoは、走ったりジャンプしたりする恐竜をあらわすスプライトですね。
dinoのコードを見ると、「“START”を受け取ったとき」ブロックが3個あります。STARTメッセージは、ゲームプレイのスタートをあらわすメッセージでした。
Scratchでは、「メッセージを受け取ったとき」ブロックが複数個あると、そのすべてのブロックがメッセージを受け取って、同時並行して処理を進めていきます。
左側の「”START”を受け取ったとき」ブロックは、変数に値を設定したあと、「go_1」という定義ブロックを呼び出しています。「go_1」は、コスチュームのサイズや位置を設定したあと、「ずっと」ブロックで、「Running」ブロックを呼び出していますね。「Running」ブロックが、恐竜の走るアニメーションになっています。
中央の「”START”を受け取ったとき」ブロックは、「go_2」という定義ブロックを呼び出しています。「go_2」は、「ずっと」ブロックのなかで、「Jump」ブロックと「Check_ground」ブロックを呼び出しています。これは、ジャンプ処理と地面チェックをやっています。
右側の「”START”を受け取ったとき」ブロックは、「ずっと」ブロックで、すぐに「Down」ブロックを呼び出しています。これは、下矢印が押された時に、恐竜のしゃがむアニメーションを呼び出しています。
つまり、dinoスプライトは、STARTメッセージを受け取ると、ゲームプレイをスタートさせて、次の3つの処理を同時並行で行っているのです。
- 恐竜の走らせる:「go_1」>「Running」
- 恐竜のジャンプと地面チェック:「go_2」>「Jump」と「Check_ground」
- 恐竜のしゃがませる:「Down」
CRASHを受け取ったら、他のスクリプトを止める
続いて、dinoスプライトが、CRASHメッセージにどう対応するか見ていきましょう。
dinoのコードを見ると、「”CRASH”を受け取ったとき」ブロックがあります。CRASHメッセージは、恐竜が衝突したときに送信するメッセージです。
dinoスプライトでは、「”CRASH”を受け取ったとき」ブロックの下のコードで次の処理を行っています。
まず衝突時の処理として、コスチュームと効果音を処理します。
「スプライトの他のスクリプトを止める」 ブロックは、「***を止める」ブロックでリストを切り替えて使える機能です。
「このスプライトの他のスクリプトをとめる」なので、これまで同時並行で動いていた「走る」「ジャンプと地面チェック」「しゃがむ」を停止することになります。
そのあと、はね飛ばされた恐竜のアニメーションを処理します。このとき画面の下まで移動したら、表示を隠しています。
つまり、dinoスプライトがCRASHというメッセージを受け取ると、障害物と衝突したときのアニメーションを表示して、最後に自分自身を非表示にするんです。
dinoスプライトは、RESTARTメッセージで何をするか
さらにdinoのコードを見ると、「”RESTART”を受け取ったとき」ブロックが3個あります。RESTARTメッセージは、ゲームプレイを再スタートさせたときのメッセージです。
よく見ると、「”RESTART”を受け取ったとき」ブロックの処理は、「”START”を受け取ったとき」ブロックのコードとほとんど同じになっています。違うのは、Ground_level変数の値を設定しているところだけです。
つまり、dinoスプライトでは、STARTメッセージとRESTARTメッセージで、ほとんど同じ処理を呼び出しているんです。
ブロック定義を使うことで、共通の処理を「go_1」「go_2」「down」というまとめていますね。同じ処理をバラバラに持っていると、コードの修正が大変になりますが、これなら初回実行時(START)も再スタート(RESTART)も、一ヶ所で修正できますね。
また、「go_1」「go_2」「Down」というように、ブロック名で、そのコードの塊がどんな処理をするのか、すぐに把握できるようになっています。
サボテンのコード
障害物になるサボテン(cactus)と翼竜(birds)についても、メッセージを受け取ったとき、どのように処理を進めているか、ちょっと調べてみましょう。
サボテン(cactus)も、二つの「”START”を受け取ったとき」ブロックがありますね。そこから、「go」ブロックと「check_CRASH」ブロックを呼び出しています。
そして、「”RESTART”を受け取ったとき」ブロックも二つあります。こちらも、同じように「go」ブロックと「check_CRASH」ブロックを呼び出しています。
つまり、ゲームプレイがスタートしたとき、この処理でサボテンの動きを制御しているんです。
ここで、「check_CRASH」の定義ブロックを見てみましょう。恐竜のdinoスプライトに触れた時、「CRASH」メッセージを送るとなっていますね。これで、サボテンと恐竜がぶつかると、衝突時の処理を呼び出しているわけですね。
cactusスプライトでは、「CRASH」メッセージを受け取ったとき、「スプライトの他のスクリプトを止める」となっているので、ゲームプレイの処理である「go」ブロックと「check_CRASH」ブロックを停止します。
翼竜のコード
翼竜であるbirdsスプライトの処理も、cactusとよく似ています。「”START”を受け取ったとき」ブロックと「”RESTART”を受け取ったとき」ブロックのところは、ほとんど同じです。
「go」の定義ブロックを見ると、すこしコードを追加して、moveブロックを呼び出しています。これは、翼竜の飛行アニメーションを表示するコードです。
衝突処理は、ほとんど同じですね。ただ、「CRASH」メッセージを受け取ったときのコードが少し異なっています。翼竜は、画面の左端まで飛んでいってから、他のスクリプトを止めます。このおかげで、恐竜と衝突してもすぐに停止したり消えたりせず、 画面の左端まで飛んで いきます。
ボタンに対応するメッセージ
残りのメッセージは、どうなっているのでしょうか。
jump_buttonスプライトとduck_buttonスプライトは、それぞれゲームプレイ画面のjumpボタンとduckボタンに対応しています。
jump_buttonスプライトは、「”START”を受け取ったとき」ブロックと「”RESTART”を受け取ったとき」ブロックで、「jump_loop」ブロックを呼び出していますね。そして、jumpボタンが押されたとき・上向き矢印キーが押された時を検出して、jumpメッセージを送っています。
duck_buttonスプライトも、jump_buttonスプライとよく似ています。
「”START”を受け取ったとき」ブロックと「”RESTART”を受け取ったとき」ブロックで、「duck_loop」ブロックを呼び出していますね。そして、duckボタンが押されたとき・離された時を検出して、duckメッセージとduck_offメッセージを送っています。
つまり、jump_buttonスプライトとduck_buttonスプライトは、ゲームプレイ画面のjumpボタンとduckボタンが押されたとき、メッセージを送信しているんです。
スコアに対応するメッセージ
スコアに対応したメッセージは、score_panelスプライトが送っています。score_panelスプライトは、恐竜が衝突したときに、スコアのラベルを表示するスプライトです。ゲームプレイ中は、スコアをカウントしています。
STARTメッセージで、「init_score」メッセージと「init_score2」メッセージを送っています。initは、「initialize」(イニシャライズ:初期化する)の略なので、「init_score」メッセージはスコアを初期化するメッセージになります。
そして、「loop_score」ブロックの下のコードで、「render_score」メッセージを送っています。これは、プレイ画面でスコアを更新するメッセージです。
CRASHメッセージで、「update_bestscore」メッセージと「render_score2」メッセージを送っています。これは、恐竜が衝突したときに、それまでのスコアとベストスコアを表示するメッセージです。
「score_engine」スプライトは、プレイ中のスコアを表示しています。
「score_engine2」「bestscore_engine」スプライトは、衝突時に、スコアとベストスコアを表示しています。
あと、「star」スプライトが、「update_bestscore」メッセージを受け取っています。これは、ベストスコアが更新されたときに、星マークを表示するスプライトです。
他のスプライトが送受信するメッセージ
これで、すべてのメッセージをどこで表示するか洗い出すことができました。メッセージの一覧表に書き加えとこんなふうになります。
ただし、RESTARTから送信するメッセージは省略しています。STARTと同じになるからです。
これで、DinoRunnerのメッセージを整理できました。スプライト同士がメッセージを通じてどのように連携しているか、分かりやすくなったと思います。
このあたりは、何度も考えながらやっていくことになると思います。メッセージ名を付箋紙で貼りなおしたり、メッセージの矢印を鉛筆で書いたり、試行錯誤して、ゲームの流れを自分なりにはっきりさせてください。
ただ、正解はないので、あくまで自分なりでいいと思います。
グローバル変数を洗い出す
最後に、グローバル変数を洗い出しておきましょう。リストがある場合は、それも調べます。
プロジェクトによっては、メッセージだけで全体を結び付けていない場合があります。たとえば変数で、共通の値や現在の状態を管理するといった具合です。
「変数」は、値を保持する仕組みです。数値や文字列を記録できます。
Scratchの変数には、グローバル変数とローカル変数があります。グローバル変数は、すべてのスプライトとステージで共有できます。ローカル変数は、プライベート変数・スプライト変数とも呼ばれます。特定のスプライトだけが、値を読み書きできます。
そこで、プロジェクト全体のつながり具合を把握するため、グローバル変数を把握しておきます。
グローバル変数は、次のようにして調べます。
- 変数カテゴリを選択
- 変数名のチェックをオンにする
これで、変数名がプレビュー画面に表示されます。グローバル変数は、そのまま表示されます。ローカル変数は、スプライト名のあとに表示されます。
DinoRunnerは、次の4つのグローバル変数を使っています。
- BestScore
- Ground_level
- Score
- Scroll_X
私は、グローバル変数の名前の先頭を大文字にしています。こうすると、一目でグローバル変数だと判断できるからです。
それから、どのスプライト+ステージが、グローバル変数に値を代入しているか調べます。グローバル変数が、どこで値を変えているか分かっていると、思わぬ動きをしたときに、調べやすくなるからです。
DinoRunnerでは、次のスプライトでグローバル変数に値を代入しています。
- BestScore :score_pannel
- Scroll_X :ground1
- Ground_level : dino
- Score :score_pannel
これで、プロジェクトの全体像がだいたい把握できました。どこで処理を実行しているか、必要ならすぐに確認できると思います。
次回は、各スプライトで具体的にどんな処理をしているか、調べてみたいと思います。
2件のコメント
2件のピンバック