見出し画像

Among Us Scratch の解析3:最初の画面の3つのボタン

前回のタイトル "Among Us" スプライトにつづいて、ゲームを開始した最初の画面(intro モード)のスプライトについて調べたい。

Among Us 以外の intro モードのスプライト

最初の intro モードの画面には、次の3つのスプライトが見えている。

画像2

前回説明した Among Us スプライトの他に、くるくると回るクルーと、ゲーム開始用のボタンがある。

画像1

クルー:画面の後ろでくるくる回りながら浮遊しているキャラクタ。スプライト名は "Intro:FlyingPlayers"

開始ボタン(3つ):通常の通信プレイ "ONLINE"、プレイの説明 "HOW TO PLAY"、一人用の練習プレイ "FREEPLAY"、の3つのゲーム開始ボタン。スプライト名は "Buttons"。

くるくる回っている、クルー(Intro:FlyingPlayers スプライト)は、見た目は面白い動きをするが、意外にコードは大き目だ。

画像3

Intro:PlayingPlayers はアニメーションしかしておらず、なくてもゲームの進行には問題のないフレーバーな要素なので後回しにして、今回はゲームの開始ボタンである Buttons スプライトについて進めていく。

Buttons スプライトのコスチューム

Buttons のコスチュームは全部で6つある。6つで、intro 画面の3つのボタンを実装している。

このコスチュームはすべて 460 x 232 ドットの「ほぼ画面大のサイズ」になっている。

画像4

コスチュームは2つで一組になっている。たとえば、一番上の2つは ONLINE というボタンのコスチュームだ。名前は "Online" と "Online2"。

画像5

画像6

1番はマウスボタンが乗っていない状態、2番はマウスボタンが乗っている状態の絵になっていて、次の動画のように動作する。

画像7

絵が変わることで「ボクは触れそうでしょ?」とボタン自身が主張している。この変化を見たプレーヤーは、この矩形が「タッチできそう・押せそう」なものだと思うだろう。簡単だが大事なユーザーインターフェースデザインと思う。

その下の小さい、HOW TO PLAY と FREEPLAY も同じようにコスチューム2種類用意されている。

画像8

画像9

左側のコスチューム名は、"How2Play" と "How2Play2"、右側のコスチューム名は "costume2" と "costume3" だ。

実装の仕組みには直接重要なことではないが、なぜ FREEPLAY のコスチュームだけ "costume" とう体を表さないような名前な上に、ナンバリングも2 と 3 なのかは不明だ。きっときちんと名前を付けなかったのがそのままなのだろう。FREEPLAY かどうかも色がついている方かどうかもわかりづらく、とてもよくない命名だ。カードでないものでも名前はきちんとつけないと、見通しが悪くなってしまうという良い?例だろう。

スプライトはほぼ画面大で、X=0、Y=0 の場所におけば、おおむね画面の適切な位置にスプライトが表示される絵として描かれている。

Buttons スプライトのコード

次の写真は Buttons スプライトのコードは全体である。このコードは1つのスプライトだけでボタン3つ分の処理をしている。

画像10

Buttons スプライト:表示と非表示の処理

画像11

Buttons スプライトは、最初隠されているが、intro モードになったときに表示される。

この2つは画面モードに合わせて適切に表示されるようにするコードとして難しくもなく適切に見える。しかし、intro イベントを受け取るスクリプトにはもう一つあり、こちらは、次のように少し怪しい。

画像12

intro モードになったときに「表示する」のは最初のものと同じだが、さらに幽霊効果と座標の設定をしている。

Buttons スプライトの位置を変えたり、幽霊効果を使ったりしているなら、何度もプレイして intro モード画面に来るたびに再設定が必要だが、ほかのスクリプトを見ても位置や幽霊効果を変えるコードはないので、このスクリプトは役に立っているとは言い難い。

そのうち、位置や幽霊効果を使う予定かもしれないし、以前は使っていたが不要になって消えたのかもしれず、その残滓がこのスクリプトかもしれない。

ただ、同じような違う処理があちこちにあるのはよいことではない。何かの修正をしたときに「あれ?表示するコード消したのにまだ表示されてしまう、どういうことだ?」といった問題の原因にもなる。

予定があっても、以前はそうだったにせよ、プログラムにおかしなゴミや不要なコードがまぎれないように、何か修正したときは影響するほかの部分もよく確認することは重要だと感じさせられるコードだ。

Buttons スプライト:ボタンを3つ表示する

Buttons スプライトのコスチュームは3つのボタン分あるのだが、スクラッチでは1つのスプライトで表示できるコスチュームは1つだけなので、Buttons スプライト1つでは、ボタンを3つ表示できない。

そこで Buttons スプライトは、自分自身とそっくり同じ複製=クローンを作る機能を使い、Buttons ボタンが HOW  TO PLAY と FREEPLAY 2つのボタンを作るよう仕掛けられている(ONLINE ボタンは Buttons スプライト自身)。

画像39

「クローン」というだけに、自分とまったく同じものしか作れないのだが、コードでクローン後に動作が変わるようにして、うまく下の2つのボタンを作り分けている。作り分けは、「クローンするところ」と「クローンされたあと」の2か所に分かれる。順にみていくことにする。

クローンするところ

ボタンのクローンを作るのは次のスクリプト。少し長めだが、クローン処理そのものは、次の写真で示す一番上の部分だけである。

画像14

この部分を拡大したのが次の写真。

画像15

「i」はスプライト用変数(Buttonsスプライトだけで使われる変数。第1回参照)だ。他のスプライトでは、同名の変数を作ることはできても、Buttons スプライトとは別の変数として扱われる。

「~のクローンを作る」は名の通り、指定したスプライトのクローンを作るコードだ。ここでは「自分自身」となっているので、Buttons スプライトは自分の複製を2つ作っていることがわかる。

クローンと変数 i の値は次のようになる。

■1つ目のクローンを作った時  i = 0 なので、1つ目のクローンの変数 i は0。

■2つ目のクローンを作った時  i = 1 なので、2つ目のクローンの変数 i は1。

■2つクローンを作り終わったら、元の Buttons スプライトの変数 i は 2 になる。

クローンを作った直後、クローンのコスチュームや変数の値は、元にしたスプライトと全く同じになる。

「スプライト用の変数」(第1回の変数の説明参照)は、クローンにとっても専用の変数だ。クローンが持つ「スプライト用の変数」は、元になった Buttons スプライトとは別物の変数で、クローンの間でも異なるものだ。Buttons スプライトと2つのクローンの変数 i は、名前が同じに見えるだけですべて違う値を持つ。変数i は3つあるのだ。

スクラッチは動作中のスプライトを選んで変数やスクリプトの動作状況を見ることができる。各ボタンをマウスポインタで選び、それぞれの変数 i を確認したのが次の動画だ。

画像18

(この動画を作るために、一時的に3つのボタンをクリックしたときの処理を抹殺している。普通にプレイするとボタンをクリックしたときに画面が変わってしまって変数の値は確認できない)。

Buttons スプライトとクローン2つで変数 i の値が異なるところまでできたなら、あとは変数 i を使って、ボタンごとに異なる処理を作ることができる。

スクラッチには「クローンされたスプライトだけ」の処理を書くことができる。クローンだけの処理が次のスクリプトである。

画像16

一番上に「クローンされたとき」というイベントがついてる。このイベントがついたスクリプトは、クローンで作られたときだけ動作する。逆に言えば、Buttons スプライト本体では動作しない。

このスクリプトも少し長いうえに、全体が「ずっと」ループとなっているが、最初のコスチューム変更は、写真に示した最初の部分だけである。次の写真はそこを拡大したものだ。

画像17

i = 0 なら1番目のクローン、i = 1 なら2番目のクローンだ。それぞれを、How2Play コスチューム、costume2 コスチュームにしてあげれば、違う表示のボタンになれる。

ここまでをまとめると、プログラムは次の図のようになる。

画像19

青い線は1つ目のクローン、赤い線は2つ目のクローンの動作である。

図の左側の、クローンを作るスクリプトは intro イベントが送られたときだけ実行されるので、クローンを作った後に動作することはない。つまり、クローンがクローンを作るようなことはない。

まとめると、左側のスクリプトは Buttons スプライト(ONLINEボタン)だけの処理右側のスクリプトはクローンの処理として分かれていて、右側はさらに、HOW TO PLAY ボタンと FREEPLAY ボタンの処理にわかれている。

Buttons スプライト:ボタンを消す処理

ここまでボタンを表示することだけをしてきたが、intro モードが終わればボタンを消さなければならない。

画像20

この4つのスクリプトはすべて intro 画面以外への画面の切り替えイベント(how to play や online)を受け取った時のスクリプトで、イベントが異なること以外全く同じ次のことをしている。

■スプライト(クローン)を「隠す」=消す。

■動作しているスクリプト以外のすべてのスプライト(クローン)のスクリプトを停止する。

■自分がクローンなら削除する。存在しなくなる。

「隠す」と「スプライトの他のスクリプトを止める」は、タイトルロゴの Among Us スプライトでも使用している、画面モードが切り替わるときに非表示+処理停止のセットだ。

スプライト(クローン)を非表示にし、自分すべてを停止したあとにするのが「このクローンを削除する」だ。このコードは、自分がクローンだったときだけ、自分自身をプロジェクトから削除して、存在自体を消してしまう。

まとめると、この4つのスクリプトにより intro モード以外へ画面が変わると、次の状態に「戻る」ことになる。

■もとの Buttons スプライトだけが残る。クローンは消える。

■Buttons スプライトは隠される(非表示)。

■Buttons スプライトのスクリプトもすべて停止した状態

また intro モードに戻って intro イベントがきたときは、これまでの説明と同じ処理が繰り返されて、ボタンが3つ現れる。

Buttons スプライト:online 画面になるときの処理

online 画面になるときだけ、上の4つの場合とは違う形のスクリプトが動作していた。

画像39

Among Us スプライトの、online モードになったら表示をやめるコードと同じく、なぜかイベントを受けてから modus 変数の変化を待っている。もしかしたら、online モードになるときだけ、online イベントにしてから modus 変数が設定されるようなことがあるのかもしれない。

(ちなみに、この記事の後の方で説明するように、Buttons スプライト自身が online モードへの変更をするコードを持っているが、そこでは modus 変数の設定と online イベントを送るのは同時である)。

Buttons スプライト:ボタンの動き

3つのボタンは、それぞれ次のように役割分担されて動作していることまではわかった。

■ONLINEボタン:Buttons スプライト。i = 2

■HOW TO PLAY ボタン:1番目のクローン。i = 0

■FREEPLAY ボタン:2番目のクローン。i = 1

この3つの処理は先ほどの、Buttons スプライトだけで動く intro イベントのスクリプトと、クローンだけで動く「クローンされたとき」イベントのスクリプトに分かれて動作する。

画像21

どちらも少し長いが、どちらもほぼ同じ、次の「ずっと」ループする構造となっている。

画像22

この無限ループは次のことを繰り返す。

①通常のコスチューム表示 ⇒ マウスポインタがボタンの中に入ったら②へ。

②緑のハイライト表示 ⇒ マウスボタンが押されたら③へ。

③音を鳴らす ⇒ マウスボタンがボタンの中のまま離されたら④へ。

④ボタンをクリックした処理。

どの番号の状態でも条件が成立しないようなら、「ずっと」ループの中の条件分岐「もし」が成立せず、①の最初状態に戻るようになっている。

例えば③の後、マウスポインタがボタンの外に出た場合、③の次の「~まで待つ」コードが待つのを止めて次のコードの「もし」へ進むが、条件が成立しないので、一番外側の「ずっと」の一番最初まで処理は戻される。

画像23

この「ずっと」ループのコードは、ほぼプレーヤーの操作によるボタンの動きだけで、ボタンを押したときにゲームモードを変える処理は、④の「ボタンをクリックしたときの処理」だけである。ボタンを押したら次の画面へ進むだけの実装にこれだけの分量が必要なところを見ても、よくできたユーザーインターフェースの実装は分量も多く作るのが大変なことがわかる良い例だと思う。

(よくできていなくていいなら、マウスが押された「もし」だけで機能的には十分だ)

以下、①~④まで、Buttons スプライト本体の ONLINE ボタンの動作(最初の図の左側)を調べていく。クローン(HOW TO PLAY ボタンと FREEPLAY ボタン)もほぼ同じだが、違うところはそれぞれ比較しながら説明する。

Buttons スプライト:ONLINE ボタンの ①通常のコスチューム表示

ONLINE ボタンの方の通常コスチューム表示処理は次のコードになっている。

画像24

このスクリプトは Buttons スプライトだけしか動作せず、クローンでは動作しない。ONLINE ボタンの Buttons スプライト本体は先の説明のようにクローン処理後は i = 2 にするので、「もし i = 2」は必ず成立して無意味だ。

だが、クローンで動作する同じ①のコードの部分は、次のように変数 i の値によって、コスチュームを HOW TO PLAY か FREEPLAY のどちらかになるよう処理している。

画像25

「大きさを70%にする」は、ためしで3つのボタンすべてを 100% にしたところ次のようになった。

画像26

位置を合わせれば全部表示されるが、それでも少しボタンが大きい。後ろでくるくると動いているクルー達が少し見えづらくもある。

どんな絵でも修正や描き直しは簡単ではないが、全体の大きさ調整なら「大きさを~%にする」コード1つで足りるので、絵を変えずにこのコードで大きさを調整したのだろう。

「明るさの効果」は、名前では少しわかりづらいがスプライトを白く光らせる効果を出す。効果0(なし)から効果100(明るさ最大)まで、10づつ変化させると次のようなアニメーションになる。

画像27

ただ、ボタンについては効果を0に設定しているだけなので、結局とくに何もしていない。他に明るさの効果の処理をするところが無いようなので、このコードはきっと昔のゴミかもしれない。

①通常のコスチューム表示の処理で、一番テクニカルなのは最後にある次の2つのコードだ。

画像28

このコードはそのまま読めば、スプライトの表示の順序を「一番手前より2つ後ろ」にしている。これだけではなんのことがさっぱりだが、実はAmong Us Scrach v2.1 (WIP)通して使用されている、画面が切り替わるときに、画面全体がふわっと暗転したり暗転がはけたりするときの効果(トランジション)に関係がある。

画像29

この効果は、Buttons とは違う、別のスプライトによるものだ。

先ほどの「最前面へ移動する」と「2層奥に下げる」コードは、Buttons が、この効果よりも前に来ないようにして、画面の切り替わり時にふわっと表示(もしくは非表示)されるようにするためにある。

このトランジションの効果のスプライトについては、また別の回に解説するつもりだが、第一回で謎のままにしていた trans1 と trans2 イベントはこのトランジション効果を発動するおまじないである。

Buttons スプライト:ONLINE ボタンの ②緑のハイライト表示

②緑のハイライトにする処理は、①に比べればごく簡単だ。

画像30

ONLINE ボタンについてはこの1コードだけである。

HOW TO PLAY ボタンと FREEPLAY ボタンの②のコードには、「表示する」が追加されている。

画像31

最初に「表示する」としているのに、さらにここで必要な理由は実は不明だ。きっと世の中そんなものなのだろう、と思っていることにする。

(実は、この「表示する」の有無によって挙動が少し違うようなのだが、それがどういう意味を持つのかよくわかっていない)。

Buttons スプライト:ONLINE ボタンの ③音を鳴らす

マウスボタンがボタンの絵の上で押されたら、③音を鳴らす。

画像32

「SELECTの音を鳴らす」がそれで「チキッ」という音がなる。

問題なのは、その上の「明るさ」の効果設定だ。0でも100でもなく「空欄」。こういった場合スクラッチでは0として扱われるらしい。しかし、個人的には、PHPじゃないんだからそんな雑なものエラーや入力不能にしてほしいと思ったりする。

明るさは Buttons スプライトには操作する箇所がないので、この明るさの設定コードも役に立っているようには見えない。以前はボタンに触ったら白く光るような演出もあったのかもしれない。

Buttons スプライト:ONLINE ボタンの ④ボタンをクリックした処理。

ボタン画像の上でマウスボタンを押してから離すと、④ボタンをクリックした処理が動作する。

画像33

ボタンは触っただけではだめで、ユーザーが「これでいい」と思ってボタンを離すまで「ボタンを押した」とは見なさない。

マウス等のデバイスでは一般的と思われる仕組みで、うっかりボタンを触ってしまっただけでは何もせず誤動作につながらないようにしている。何度も繰り返す操作には細かな親切が重要だと感じさせられる。

このボタンの処理は画面モードを online に切り替える処理で、オンラインプレイ中から抜ける処理に似たコードになっている。

画面モードを切り替えるとき Among Us Scrach v2.1 (WIP) は、「modus 変数をモード名に設定してから、同名のイベントを送る」というプログラミングルール(第一回参照)により、modus変数で画面モードを確認したり、モードの切り替わりをイベントで受けたりできるが、もう一つ、先ほどの「ふわっと画面が切り替わる効果」は、trans1, trans2 イベントを送るという別のプログラミングルールが存在する。

実装の詳細はトランジション効果の説明の機会に解説したいが、画面モードを切り替えるときに「ふわっと」切り替えたいだけなら、次のようにする。

画像34

「画面モードを変える」のところは、modus 変数の設定とイベント送信にする。

trans1 イベントは、ふわっと「暗転」する処理を誰かにお願いするイベントだ(誰か=トランジションをするスプライト)。trans1 イベントで発動した処理が全部終わるまで待つと画面は真っ黒になる。

逆に trans2 はふわっと「暗転がはける=真っ黒がなくなる」のを誰かにお願いするイベントだ。trans2 を送ると暗転が消えはじめ、同時に画面モードも変えるので、暗転が消えたときは別の画面モードになっている、という仕掛けだ。

HOW TO PLAY ボタンと FREEPLAY ボタンも、モードの切り替えとふわっと切り替えるプログラミングルールについては同じだが、曽於の他の処理内容は少し違う。

画像35

HOW TO PLAY ボタンの処理で気になるのは、modus 変数は "tutorial" を設定するのに、イベント名は "how to play" であるところだ。違う理由はここではわからない。

また、どちらのボタンも "reset" というブロック呼び出し(ピンク色)をしている。スクラッチのブロックは、よくあるプログラミング言語のサブルーチンや関数と呼ばれるものに相当する、名前と引数のあるスクリプトを指す。

次の写真は、この "reset" ブロックの定義である。

画像36

何か大事な変数の初期化をしているのはわかるのだが、用途はここではまったくわからない。また「タイマーをリセット」や「goto を送る」など謎の処理もある。

「タイマーをリセット」はスクラッチに初めから用意されている、かなり正確な時間を計測するのに使うストップウォッチのような変数だ。

タイマー変数を表示した状態にして Among Us Scrach v2.1 (WIP) を起動すると、HOW TO PLAY や FREEPLAY ボタンをで画面が変わった時にタイマーが0になっているのがわかる。

画像37

しかし、残念なことに、ここではタイマーが0になることがわかっただけで何の役に立つのかはさっぱりわからない。ONLINE ではタイマーを0にしないし、そもそも reset ブロック自体呼ばれていない。まだまだアプリケーション全体像が明らかになる日は先のようである。

Buttons スプライト:またもや set_volume イベントを処理するコード

Buttons スプライトには、Among Us スプライトにもあった、set_volume イベントを受けるコードがある。

画像38

全く同じイベントを受けたら必ず動作するという Among Us スプライト同様、背景が set_volume イベントを送り続ける限り、たとえボタンがなくともあらゆる画面で動き続ける。

次の動画は、Buttons スプライトのこのコードが freeplay 画面になってボタンがなくなっているのに動作している(ずっと黄色枠がついている)ことを確認したものだ。

画像40

Among Us スプライトの set_volume イベントを受けるスクリプトも同様にずっと動いているので、少なくとも全く同じ音量処理をするスクリプトが常時2つ以上存在しているのだ。期待通り動いてはいるが限りなくバグに近いのではないだろうか?

まとめ:クローンの使い方と新しいプログラミングルール

今回、最初の intro 画面下部の3つのボタンを処理する Buttons スプライトについて詳細に調査した。

1つのスプライトがクローンにより3つに分かれて別々のボタンを実装しているところは、スクラッチらしい(もしくは、Javascript 等のプロトタイプ型のプログラミング言語らしい)テクニックだ。きっとゲーム中はもっと様々なクローンテクニックが使われているだろう。

ふわっと切り替わる効果(トランジション)については、今回実装の詳細は見送ったが、利用方法については明らかにできたと思う。

次の記事

Among Us Scratch の解析4:モード切替で使う効果


この記事が気に入ったらサポートをしてみませんか?