スクラッチプログラミングに挑戦している皆さん、どうも!スクラッチコーチです。
ゴンザレスからゲームクリエイターへの挑戦状
エンティティが
描画されて、
敵が
見えるようになった。でも
敵がいない
道を
探して
遠回りすれば
問題ないよね!ってアレ!?
壁の向こう側にいるはずの敵が見えちゃってる!?これじゃあ
速攻で
見つかっちゃうじゃんか……ダメダメ!なんとかしないと、しかし
壁の
向こうにいる
敵をどうすれば
壁の
向こうに
描画できるのだろうか……あぁなんだか
頭がこんがらがりそう(T_T)
今回の目標「奥行きを実装して奥から順番に描画する」
いまは
外見上は3Dだけど
、実際は目の錯覚でそう見えるだけで、XとYの2次元空間に過ぎない。だから
壁の
向こうにナノがいるはずでも、それが
反映されないで
何でもかんでも
前に
来ちゃう……これじゃあ
壁に
隠れながら
進んだり、トーストをくわえた
少女が
角を
曲がったらイケメンとぶつかるイベントも
起こせないよね!(え?いらない?)ということで
今回はXとYにくわえてZに
相当する
3つ目の次元、奥行きを実装していこうと
思う。↓これが
目標の
状態。
ok-scratch
\u003cp\u003e今回の最後には真の3Dが僕らを待っているぞ。\u003c/p\u003e
マップを見えるようにしておく
このあとの
処理でいったん
見えるようにしといたほうが
便利なので
修正しておくね。
ok-scratch
\u003cp\u003eもしすでにマップが見えるようになっているなら、そのままでOKだよ~\u003c/p\u003e
幽霊をゼロにセットしよう。
ok-scratch
u003cpu003eあと、スプライト「エンティティ」の緑の旗が押されたときに、ドラッグできるようにするブロックを置いておくとデバッグしやすい(スクショ取り忘れた)u003c/pu003e
CHECK! 壁の裏側に敵を配置したらどうなるかテストする
冒頭の
漫画はいったいどういうことなのか、
最初に
現状を
確認しておこう。↓こんな
感じで、エンティティを
壁の
中に
移動してみたら
分かるよ。
なんと
壁の
前側に
描画されてしまった!
本来このナノは
壁の
向こう
側に
存在しているのだから、
見えてはいけないよね。しかし
現段階では「
壁の
向こう」みたいな
概念は
存在していないんだ。すべてが
手前に
描画されてしまう
世界になっている。ここからは
奥行きを
実装して、
何が手前で、何が奥にあるのか、という
情報を
世界に
与えていくよ。
それには
リストを使った描画の管理が
必要になる。さぁ、いよいよ
手強い
部分に
差し
掛かってきたぞ。
ok-scratch
u003cpu003eけっこうな難所だけど、一緒に乗り越えていこう!u003c/pu003e
リストで描画を管理する
さっそくリストを
使った
描画の
仕組みを
作っていこう。
新しいリスト「描画X」を作る
スクショだと
末尾にリストって
書いてあるけど、リストなのはブロックの
色で
分かるから
余計だなと
思い「
描画X」という
名前に
変えました。
新しいリスト「描画距離」
こちらも
末尾のリストという
文字は
消しました。
初期化しておくよ。
スプライト「レイキャスター」を開く
ペン関連のブロックを移動する
このブロックをドラッグアンドドロップで、スプライト「ペン」に
移動しよう。
移動したらスプライト「レイキャスター」からは
緑のペンブロックは
消してしまってOKだ。こんな
感じになるはず↓
描画に必要な情報をリストに入れる準備をする
次は
定義「_シングル・レイ」を
見つけて。
↓この
線のとこで
切り
離してみて。
「レベルカラーに
触れたら」っていう
条件ブロックを
横にどけて、↓こんな
状態にしておいて。
定義「_描画する」を作る
再描画せずに
実行するにチェック
入れてね。
引数が3つもあるんだ。
定義「_シングル・レイ」の
最後で
実行しよう。↓このスクショを
見て
引数に
次の3つを
入れておいて。
- タイプ:空白
- X:変数「x座標」
- 距離:変数「距離」
条件ブロックを作って囲もう
いま
置いた
定義ブロックを「もし~でなければ」ブロックで
囲もう。そしてタイプのところにペンの
色を
入れておいて。
定義「_
描画する」の
中で、
各引数を
各リストに
格納するぞ。
u003cpu003e奥行きを実装するために必要な情報をリストに格納できた!u003c/pu003e
残りのペン関連ブロックを、スプライト「ペン」に移動する
さっき
切り
離しておいたペン
関連ブロックを、ドラッグアンドドロップでスプライト「ペン」に
移動しよう。
移動後は
消しちゃってOKだ。
CHECK! リストにデータが格納されるかテストする
実行すると↓こんな
感じになるぞ。
ペンで描画する
スプライト「ペン」を
開こう。
さっき
準備したリストの
中身を
使って、
実際にペンを
入れていくぞ。
定義「_描画する」を作る
さっきスプライト「レイキャスター」でも
同名の
定義を
作ったけど、
今度はスプライト「ペン」でも
作るよ。
引数はいらないよ。
↓この
一連のブロックを
追加しよう。
「
描画Xの
長さ」
回繰り
返すループを
置こう。
変数「行#」を作る
行#《ナンバー》を
作るよ。
ループの
直前で、1で
初期化しておこう。
ループの
中で
変数「
行#」を1ずつ
加算するよ。
定義「_行を描画する」を作る
ok-scratch
u003cpu003e行を描画する、ってあんまり聞かない日本語だよね。実際使われてないと思うw ちょっと図解しておこうと思うので↓これを見ておいてね。u003c/pu003e
ここまで
作ったロジックだと、ペンって
上から
下に1
行ずつ
描いていくよね。
定義「_
行を
描画する」の
行は、この1
行のことなんだ。おっけぃ。
実行する
ループの
中で
実行しよう。
実行する
場所はさっき
置いた
変数「行#」の前に置いてね。
変数「タイプ」を作る
色々作るものが
多いけど、
今度は「タイプ」っていう
変数を
作るよ。
定義「_
行を
描画する」の
中でいろいろな
値をいれていくよ。
タイプ
値は、リスト「
描画タイプ」の「
行#」
番目にしよう。
X座標
これをまるっと
複製する。
複製後に
各値を
調整して、X
座標についても
同じようなブロックを
作る。
距離
距離も
作るよ。
複製しよう。
同じように
各値を
調整しておこう。
移動しておいたブロックをくっつける
さっきスプライト「レイキャスター」から
移動しておいたペン
関連ブロックをガチャン!っとくっつけよう。
とりまこれでOK!
メッセージ「ペイントする」を受け取ったとき
テストの
前にここで
定義「_
描画する」を
置いておこう。
CHECK! 壊れてないかテストする
色々変えたから、
壊れてないかテストしておこう。
だいたいOKだね。でもナノが
画面の
端にいるのが
不自然な
瞬間があるね。ずっと
端っこから
監視しているみたいだ……これは
直さないと、
敵に
見つかっちゃいそうだね。さっき
置いた
定義「_
描画する」の
場所を
変更しよう。↓こんなかんじ。
↓ここに
置けばナノが
画面から
消えるはず。ちょっとしたタイミングの
問題なんだ。
あと、
壁のカラーが
無くなってたね。
定義「_
行を
描画する」で、
変数「タイプ」をペンの
色に
設定しよう。
CHECK! ナノが画面外に消えるかテストする
これでナノが
画面外にスムーズに
消えるかな。
うん、
大丈夫そうだね!ナチュラルな
動きになった。
奥から順番に描画していく
奥行きを
実装するメインの
処理に
取り
掛かるよ。3Dで
奥行きを
実装するというのはどういうことかと
言うと、
奥にあるモノから
順番に
描画していくということなんだ。
基本的には
後から
描画されたものほど、
前に
表示されるという
法則がある。だから
奥から
順番に
描画すれば、
前のモノほど
前に、
後ろのモノほど
後ろに
表示されるんだ。つまり↓コレが
実現できるってこと!
やってみよう!
スプライト「プレイヤー」を開く
定義「_レイキャスターを
初期化する」でダミー
値をリスト「
描画距離」に
追加しよう。
残りの2リストについても
追加するブロックを
置いておこう。
変数「★描画インデックス」を作る
インデックスとして
使う
変数を
用意するぞ。
2で
初期化する。
スプライト「レイキャスター」を開く
定義「_
描画する」に「◯まで
繰り
返す」ブロックを
置いて、
元々あったリストに
関するブロックはいったん
外しておこう。
◯まで
繰り
返す、の
条件に
使う
演算を
用意しよう。↓このブロックを
準備して。
この
引き
算は「
★描画インデックス - 1」を
作っておいて。(スクショ
取り
忘れたm(_ _)m)これを「◯ >
距離」っていう
比較演算の
左側にセットしてみよう。
最終的には↓こんな
感じになるはずだ。
適切な位置にインデックスをセットする
使うブロックはカンタンだけど
処理は
複雑なところ。とりあえず
実装していこうか。ループの
中で★
描画インデックスを
マイナス1ずつ変えていこう。
このループの
直下で、もう1つ「◯まで
繰り
返す」ブロックを
置こう。
ここの
条件にも
比較演算子を
入れる。ただし
さっきとは逆向きの比較をするぞ。「◯
< 距離」を
置こう。
左側にはシンプルに、リスト「
描画距離」の「★
描画インデックス」
番目、を
入れよう。↓この
画像をみて
上下の
条件式が
違うことを
再確認しておこう。
この
中で
変数「★
描画インデックス」を
プラス1ずつ変えよう。
上のループとは
何もかも
逆だね。
この2つのループを
通して
変数「★
描画インデックス」は
適切な
位置にセットされる。ところで
適切な位置とはなんだろうか?
適切な位置の演算を解説
読んでもよくわからん、という
人は
飛ばしてもOK。
現時点で
理解は
必須ではないけど、
一応解説しておく。まず2つのループを
作ったよね。1つ
目はインデックスをマイナス1していくループ。2つ
目はインデックスをプラス1していくループ。この1つ
目のループでは
何をしていたのかを
見ていこう。サンプルとして↓こんな
感じのリストがあったとしよう。
矢印は
距離の
長さを
表しているよ。
↓★
描画インデックスの1つ
上と、
引数の1つである「
距離」を
比較するんだよね。
↓
引数「
距離」より、リストの
中身が
長かったらループを
止めるんだよね。
ここまでが1つ
目のループ。これで
終わりでもいいんだけど、さらに2つ
目のループを
作ったね。↓2つ
目では
引数「
距離」より、リストの
中身が
短かったらループを
止めるんだよね。
こうすることで、
確実に
描画距離リストが「
奥のモノがリストの上」に
来るようになる。
これこそが
今まで
使っていた
「適切な位置」の正体なんだ。
ok-scratch
u003cpu003eなんだか複雑なことをしているなぁと思うかもだけど、実はこういうリストの並べ替え処理っていうのはシステム開発でもゲーム制作でも高頻度で発生する超一般的なコーディングなんだ。専門的には「ソート」とか呼ばれてる。数学の公式みたいにパターン化されているものはアルゴリズムなんて呼ばれたりする。u003c/pu003e
適切な位置を各リストに反映する
このインデックスを
使って、
例の3つのリストに
値をセットしよう。
これで
奥行きを
反映した
描画の
準備は
整った!
CHECK! 奥から描画されるかテストする
このテストはいつもとは
違う
手順で
行う。
描画は
一瞬で
行われるから、
目で
確認するには
工夫が
必要なんだ。まずスプライト「ペン」を
開いてほしい。
いったんプロジェクトを
止めるために
停止ボタンを
押そう。
その
後、
定義「_
描画する」をクリックしよう。
そうすれば……
こんな
感じでテストできると
思う!
奥からペンで
描かれている
様子がバッチリわかるね!あーでもちょっと
待って。↓
肝心のナノがまだ
壁の
前に
描画されてしまうみたい。
それもそのはず。
奥行きが
実装されたのは
壁だけであって、まだエンティティ(スタンプ)は
何も
変わってないもんね。
スタンプも奥行きを反映する
エンティティも
今作ったリストで
管理されるように
直していこうか!
スプライト「レイキャスター」を開く
定義「_
描画する」をドラッグアンドドロップして、スプライト「エンティティ」にコピーしよう。
両方のスプライトに定義「_描画する」が存在するようにしたいから、消さないでね。スプライト「エンティティ」を開く
定義「_
画面を
回転させる」で、いまコピーした
定義「_
描画する」を
実行しよう。
引数「タイプ」
タイプにはコスチューム
番号を
入れる。とりあえず1にしておこうか。
引数「X」
「
相対距離X * (★DV /
相対距離Y)」という
演算を
作ろう。↓この
矢印を
参考に
作ってみて。
引数「距離」
ここには
変数「
相対距離X」を
入れよう。↓
最終的にはこんな
感じ。
そして、この
定義ブロックを
条件ブロックで
囲んでみて。
条件式で、
相対距離Yがゼロよりも
大きいかどうかを
調べる。
u003cpu003e自分の前にいるエンティティに奥行きを適応する準備ができた。u003c/pu003e
スプライト「ペン」を開く
メッセージ「ペイントする」を
受け
取ったときの
処理をごっそり
外すよ。
横にどけておいて。
ok-scratch
u003cpu003e↑後で使うよu003c/pu003e
そして
最初に「
隠す」ブロックを
置こう。
定義「_行を描画する」を改修する
ちょっと
複雑な
改修作業をするよ。いまって↓こんな
感じだよね。
これを「ペンの
明るさ」で
切り
離してから、
変数「
高さ」のブロックを、
変数「
距離」の
下に
持ってきて。↓こんなかんじにする。
ok-scratch
u003cpu003e↑ちょっと複雑な作業だからスクショを見て再度確認してね。u003c/pu003e
変数「
高さ」ブロックの
直下に
条件ブロックを
挟もう。
条件式でタイプが10
未満かどうか
調べる。
ok-scratch
u003cpu003eいきなり10っていう数字が出てきたね。これはこのゲームで使えるエンティティ(敵やアイテムなど)の上限だよ。もちろん10じゃなくて50でも100でもOK。とりあえず10個にしておく、ってかんじ。定数(変数)を作って管理してもOK。u003c/pu003e
定義「_エンティティをスタンプする」を作る
さっき『メッセージ「ペイントする」を
受け
取ったとき』から
外しておいたブロック
群をここにくっつけよう。
ok-scratch
u003cpu003e↑ブロック群の最後に「ドラッグできるようにする」があるけど、これはなくてもOK!u003c/pu003e
↓こんなかんじになるよ。
これを
加工していく。まず
距離と
高さの
処理は
消しちゃって。
さらに
最後の「ドラッグできるようにする」がある
場合は
消しちゃおう。
そしてこの
定義を、さっき
追加した
条件ブロックの
中で
実行する。
ココ
以降は
壁を
描画する
処理になるから、エンティティをスタンプする
場合は
処理をここで
止めちゃおう!
なんか
加工しまくったら
結局くっつけたブロックのほとんどを
外して、いったん↓ここまでシンプルにしてもらったほうが
分かりやすいかも……。
あらためてX
座標とY
座標をセットしていこう。YはゼロでOK。
そしてペンのスタンプブロックを
実行する。
CHECK! ナノが壁に隠れるようになったかテストする
やっほーーーい!ナノが
壁の
向こう
側に
描画されたぁ!!
長かったね……w
まとめ
今回は
奥行きを
実装するのがメインだったね。しかしこれで3D
空間が
真の
意味で3Dになったよ。XとYと
奥行き、この3つの
次元がそろって
始めて3D(3
次元)だからね。ふぅー!これでスクラッチキャット
氏も
壁に
隠れながらスターを
探せるに
違いない。っと、あれ?なんかスクラッチキャットが
迷子になってない!?なんてこった!
次回もチェックしてみてくれ。
グリフパッチさんの動画
このチュートリアルは
世界No.1スクラッチャーとして
名高いグリフパッチさんの
動画を
参考にしているよ。ただし
手順を
一部変えているところもあるんだ。