この連載では、Scratchで本格ゲームの中身を調べる方法を解説しています。第3回では、全体のメッセージ呼び出しからちょっと離れて、各スプライトが、メッセージからどのように呼び出されているのか調べていきます。

題材には、恐竜ランニングゲームを使っています。

前回は、ゲーム画面の切り替わりとメッセージが対応していることを見てきました。

ゲーム画面の切り替わりとメッセージが対応している
  • TITLEメッセージ:タイトル画面を表示
  • STARTメッセージ:ゲームプレイの開始
  • CRASHメッセージ:恐竜の衝突 → スコア画面の表示
  • RESTARTメッセージ:ゲームプレイの再スタート

本格的なゲームの全体像を把握するには、細かなところは気にしないで、メッセージとスプライトの関係をざっくりと見ていくのが良いと思います。

でも、各スプライトの処理をどう呼び出しているのか、ある程度理解しておかないと、モヤモヤしますよね。そこで、メッセージを受け取ったスプライトが、どのように処理を進めているか、少し掘り下げてみましょう。

dinoスプライトがSTARTメッセージで何をするか

まずは、dinoというスプライトのコードを調べます。dinoは、走ったりジャンプしたりする恐竜をあらわすスプライトですね。

dinoのコードを見ると、「“START”を受け取ったとき」ブロックが3個あります。STARTメッセージは、ゲームプレイのスタートをあらわすメッセージでした。

Scratchでは、「メッセージを受け取ったとき」ブロックが複数個あると、そのすべてのブロックがメッセージを受け取って、同時並行して処理を進めていきます。

3個の「”START”を受け取ったとき」ブロック

左側の「”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メッセージは、恐竜が衝突したときに送信するメッセージです。

「”CRASH”を受け取ったとき」ブロック

dinoスプライトでは、「”CRASH”を受け取ったとき」ブロックの下のコードで次の処理を行っています。

まず衝突時の処理として、コスチュームと効果音を処理します。

スプライトの他のスクリプトを止める」 ブロックは、「***を止める」ブロックでリストを切り替えて使える機能です。

「このスプライトの他のスクリプトをとめる」なので、これまで同時並行で動いていた「走る」「ジャンプと地面チェック」「しゃがむ」を停止することになります。

「スプライトの他のスクリプトを止める」ブロック

そのあと、はね飛ばされた恐竜のアニメーションを処理します。このとき画面の下まで移動したら、表示を隠しています。

つまり、dinoスプライトがCRASHというメッセージを受け取ると、障害物と衝突したときのアニメーションを表示して、最後に自分自身を非表示にするんです。

dinoスプライトは、RESTARTメッセージで何をするか

さらにdinoのコードを見ると、「”RESTART”を受け取ったとき」ブロックが3個あります。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メッセージを送っています。

jumpメッセージを送信

duck_buttonスプライトも、jump_buttonスプライとよく似ています。

「”START”を受け取ったとき」ブロックと「”RESTART”を受け取ったとき」ブロックで、「duck_loop」ブロックを呼び出していますね。そして、duckボタンが押されたとき・離された時を検出して、duckメッセージとduck_offメッセージを送っています。

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」メッセージを送っています。これは、恐竜が衝突したときに、それまでのスコアとベストスコアを表示するメッセージです。

CRASHメッセージで、「update_bestscore」メッセージと「render_score2」メッセージを 送信

「score_engine」スプライトは、プレイ中のスコアを表示しています。

プレイ中にスコアを表示する score_engineスプライトのコード

「score_engine2」「bestscore_engine」スプライトは、衝突時に、スコアとベストスコアを表示しています。

あと、「star」スプライトが、「update_bestscore」メッセージを受け取っています。これは、ベストスコアが更新されたときに、星マークを表示するスプライトです。

starスプライトのコード

他のスプライトが送受信するメッセージ

これで、すべてのメッセージをどこで表示するか洗い出すことができました。メッセージの一覧表に書き加えとこんなふうになります。

ただし、RESTARTから送信するメッセージは省略しています。STARTと同じになるからです。

全体のメッセージの流れ

これで、DinoRunnerのメッセージを整理できました。スプライト同士がメッセージを通じてどのように連携しているか、分かりやすくなったと思います。

このあたりは、何度も考えながらやっていくことになると思います。メッセージ名を付箋紙で貼りなおしたり、メッセージの矢印を鉛筆で書いたり、試行錯誤して、ゲームの流れを自分なりにはっきりさせてください。

ただ、正解はないので、あくまで自分なりでいいと思います。

グローバル変数を洗い出す

最後に、グローバル変数を洗い出しておきましょう。リストがある場合は、それも調べます。

プロジェクトによっては、メッセージだけで全体を結び付けていない場合があります。たとえば変数で、共通の値や現在の状態を管理するといった具合です。

変数」は、値を保持する仕組みです。数値や文字列を記録できます。

Scratchの変数には、グローバル変数ローカル変数があります。グローバル変数は、すべてのスプライトとステージで共有できます。ローカル変数は、プライベート変数・スプライト変数とも呼ばれます。特定のスプライトだけが、値を読み書きできます。

そこで、プロジェクト全体のつながり具合を把握するため、グローバル変数を把握しておきます。

グローバル変数は、次のようにして調べます。

  1. 変数カテゴリを選択
  2. 変数名のチェックをオンにする

これで、変数名がプレビュー画面に表示されます。グローバル変数は、そのまま表示されます。ローカル変数は、スプライト名のあとに表示されます。

DinoRunnerは、次の4つのグローバル変数を使っています。

  • BestScore
  • Ground_level
  • Score
  • Scroll_X

私は、グローバル変数の名前の先頭を大文字にしています。こうすると、一目でグローバル変数だと判断できるからです。

それから、どのスプライト+ステージが、グローバル変数に値を代入しているか調べます。グローバル変数が、どこで値を変えているか分かっていると、思わぬ動きをしたときに、調べやすくなるからです。

DinoRunnerでは、次のスプライトでグローバル変数に値を代入しています。

  • BestScore :score_pannel
  • Scroll_X :ground1
  • Ground_level : dino
  • Score :score_pannel

これで、プロジェクトの全体像がだいたい把握できました。どこで処理を実行しているか、必要ならすぐに確認できると思います。

次回は、各スプライトで具体的にどんな処理をしているか、調べてみたいと思います。

第4回:個別の処理を見ていく >>