スクラッチに挑戦している皆さん、どうも!スクラッチコーチです。
- ① まず2Dマップを動き回れるようにしよう!
- ② さっそく3D化しちゃおうぜ!
- ③ 壁にスキマがあって敵から丸見え!?やっば
- ④ 陰影をつけて立体感マシマシにしよう
- ⑤ トゲトゲやユガミを補正してハイクオリティ3Dの一歩を踏み出そう(爆速オンライン3Dゲームの作り方 #05)
- ⑥ 壁の衝突判定の基本を作ろう
- ⑦ 壁に触れてると進めない!?移動を改善しよう
- ⑧ ついに敵が現れた!距離感の計算ってどうやる?
- ⑨ 奥行きを実装して壁の後ろに隠れられるようにする
- ⑩ エンティティに陰影をつける
- ⑪ 敵がプレイヤーに向かって迫ってくるように実装する
- ⑫ スターを実装しよう!
- ⑬ 爆速3D爆誕 (いまここ)
- ⑭ 壁に画像(テクスチャ)を貼り付けてリッチな3D空間を演出する
- ⑮ テクスチャの壁を洗練させて本格3D完成!
- ⑯ シメだ!モバイル & オンライン化をするぞ
- ⑰ 【おまけ】敵がプレイヤーを見つけたら追いかけるロジック
- ⑱ 【特別編】マウスに合わせて視線を上下させる方法
- ⑲ 【特別編】マウスでターンするスピードを調整する
- ⑳ 【特別編】敵をジャンプで乗り越える
ゴンザレスからの挑戦状
エンティティやアイテムなども実装して、解像度の値も小さくしてきれいに描画されるようにしてたら、急にスクラッチキャットの身体が動きにくくなった!
どうやら高負荷な描画に耐えきれずに、まともに動けなくなってしまったようだ……これはなんとかせねば!
今回の目標「3Dを爆速化する」
このチュートリアルシリーズのタイトルでもある「爆速3D」を今回で実現する。え?今までも十分に軽い?ノンノン、今までは過去になる。それが今回。ここがスクラッチ3Dの歴史における1つの転換点になる、そう確信しているぜ。
実現するのは次の通り。
- FPSを算出する
- プレイヤーと敵の移動をペンの描画と切り離して高速化する
- レイキャスティングのムダを省き、ペンの描画の負荷を下げる
うぃ、行くぜ!
爆速3D化の第一歩を踏み出す
ここからがこのチュートリアルが世界No.1スクラッチャー(グリフパッチさん)によって作られたものである超高品質な部分だ。まじ刮目して見てくれ。
スプライト「プレイヤー」を開く
まずはデバッグ表示されている★解像度を右クリックして、スライダーの指定範囲を変更しよう。
1から16まで選べるようにする。
小さいほうがキレイな描画になるよ。使ってるパソコンのスペックによっては1にするとモッサリしてとてもプレイできたもんじゃなくなるかも……不安な人は2か3くらいにしておいてもいいかも。
変数「ティック30」を作る
ちょっと変わった名前だけど、これからパフォーマンスを改善していくうえで重要になる変数だから、ニュアンスを変えてしまわないように変数の名前は動画のとおりにしておくね。
変数「★デルタ」を作る
変数「★FPS」を作る
★デルタとティック30を初期化しておこう。
定義「_FPS」を作る
ちょっと変な名前だけど、引数に「直前のティック30」をもたせよう。
ずっとループの最初で実行しよう。引数には変数「ティック30」をはめよう。
この定義を作っていく。
まず最初に変数「ティック30」に「タイマー x 30」を割り当てよう。
次に変数「★デルタ」に「ティック30 - 直前のティック30」を割り当てる。
CHECK! ★デルタの値が正常に動作するかテストする
これで解像度の値が大きくなる(粗くなる)と★デルタが減る。
逆に解像度の値を小さくする(きれいになる)とデルタが増える。
この状態になっていることを、この段階で確認しておいてくれ。
★FPSを算出する
次の演算ブロックを使うよ。
↓こんな演算を作ってくれ。四捨五入って使いそうで意外と使わないよね。
これを★デルタの下でセットする。
トラブル発生!壁が透ける
さて、この段階でいったん解像度を1にしてみたところ、妙な減少が起きてしまった。
↓このように壁が半透明になってしまったんだ。
ペンの太さが細くなりすぎて起きたのが原因だよ。
これは直さないとね。
定義「_レイキャストする」を切り離す
↓この部分で切り離して。
条件ブロックを挟もう。条件式には「★解像度 < 4」という演算をはめる。
解像度が1, 2, 3とか小さい値なら、X座標を四捨五入するようにする。こうすることでペンが細くても適切な場所に描画されるようになる。
CHECK!
ちょっと見づらいけど、★解像度が1になってるのに右側の壁が透けてないことが見て取れるよね!
おっけい!
プレイヤーの動きを爆速化する
さぁ面白い部分が始まるぞ。
なぜキレイな解像度の中でもプレイヤーが爆速で動くのか
解像度の値を小さくしてきれいな描画をすると、プレイヤーの動きがカクカクしてしまう。
この理由は、ペンの処理が忙しいから。
たとえば★解像度が8なら、スクラッチの処理としては(あくまで例えばの数字として)10回ペンを描く中でプレイヤーを動かすだけだから余裕なんだ。でも★解像度が1だと100回ペンを描く中でプレイヤーを動かす必要があって、めちゃめちゃ忙しくなる。
リアルな動きでたとえるなら、机に座りながら数学の問題を解くのはできるよね。
でも坂道をダッシュしながら数学の問題を解けって言われたら頭が回らなくなるのと同じような感じ。
スクラッチも忙しい中ではカンタンな処理でもできなくなってしまうというわけだ。
このため★解像度の値が小さいと、プレイヤーの動きがカクカクしてしまう。
じゃあどうすればいいだろうか。
スクラッチの性能を変えることはできないから、もちろんコーディングで解決する必要がある。
答えを抽象的に言うとこうだ。
ペンの描画が10倍忙しくなったなら、プレイヤーの動きは10倍ザツにすればいい、ってこと。
坂道ダッシュしながらでも1x1とか1x2っていう超カンタンな掛け算なら問題なく解けるよね。それと同じで、ペンの処理が忙しいなら、その分だけプレイヤーの動きの処理は大雑把なものにしてあげればいいんだ。
このときに役に立つのがさっき作った★デルタになる。
やってみよう。
★デルタを使う
定義「_プレイヤーティック」内の処理に★デルタを使っていくぞ。
←
まず左向き矢印キーが押されたときの値を「3 x ★デルタ」にしよう。
↓こんなかんじ。
←
↑
↓
a
d
おっけい!
スプライト「エンティティ」を開く
エンティティにも★デルタをつかっていく。
クローンされたときの移動にさっきと同じような感じで★デルタを使おう。
CHECK! 動きが爆速になったかテストする
どおおおおおやぁぁぁぁ( ・´ー・`)
★解像度を小さくしてもスーッと敵を華麗にスルーしていく様子が見て取れるんじゃないかな!?
すっげー!まじすっげー!
解像度に関係なくプレイヤーの動きが爆速になった!
天才スクラッチャー(グリフパッチさん)のすごいところは、これで満足しないところなんだよ……もうこれだけでも感動的なんだけど、こっからもっと驚くコーディングをしていく。
世界、変わりますよ?覚悟は良いですか?
レイキャスターの精度を上げる
いまってさ、レイキャスターでヒットボックスっていうコスチュームを使って扇状のビームを出してるよね、見えないけど。覚えてるかな?
このヒットボックスっていうコスチュームのサイズは4 x 4だよね。違う人もいるかもだけどまぁ大丈夫。
4 x 4って小さいように見えるけど、レイキャスターはこのコスチュームを使って「壁にぶつかったかどうか」という当たり判定を1度に何回も、いや何百回とか途方もない回数繰り返してるんだよね。
分かりやすく数値化すると、4 x 4のサイズのどこかが壁に触れてないかっていうチェックを1度のチェックにつき合計16回行ってるっていうイメージ。(あくまでイメージだから回数は正確じゃないよ)
だったら、このヒットボックスのサイズをめちゃめちゃ小さくしてあげれば、1度に実行する当たり判定の負荷が下がるんじゃね?っていう発想。
それを今からスクラッチの裏技を使って実現していく……わお。
スプライト「レイキャスター」を開く
コスチュームを描くよ。
最初にビットマップ化しておくと楽だよ。
塗りつぶしツール選ぼう。
色は何でもいいから、枠内を塗りつぶすよ。これだけ。
名前はBIGにしておこうか。
コーディングに戻って、緑の旗が押されたときにコスチュームをBIGにしてから大きさを1%にしてみて。
CHECK! レイキャスターの精度が上がったかテストする
実はこれだけでめっちゃ改善されてる……。
なんじゃこりゃぁ!!
ロジックはさっき説明した通り、レイキャスターのビームを4 x 4というサイズからもっともっと小さくして1度の当たり判定の負荷を下げているんだけど、いったいBIGっていうコスチュームはなんで必要だったんだろうか。
じつはスクラッチでは小さいコスチュームを大きさブロックを使ってめっちゃ小さくする、という挙動は実行されないようになっているんだ。え!?って感じだよね。小さすぎるコスチュームを作れないような仕様になってる。
そこで以下のような作戦でスクラッチをダマしたんだ。
- いったん大きなコスチュームを使って大きさ1%という状態を作る。これは大きなコスチュームをめちゃ小さくしてるからスクラッチもOKを出してくれる
- 大きさが1%の状態でコスチュームを着替える(4 x 4)
- 4 x 4の1%の大きさのスプライト爆誕
わおわおわお!
1度の当たり判定の負荷も超下がって、描画がさっきよりもヌルヌルになってるっていうわけ。天才だなマジで!
レイキャスターの負荷を下げることで精度が増した。
レイキャスティングを……しない
天才は止まらない。天才だから止まらないのか、止まらないから天才なのか。とにかくさらにパフォーマンスを上げていく。
いまのレイキャスティングには無駄がある。どこだと思う?
↑これのとおり、カベの近くだけ当たり判定が必要で、それ以外の空白の空間では別に当たり判定する必要ないよね。
いやーでも、当たり判定しないとそこが空白かどうかわからないじゃん、って思うよね……。
そこで、空白かどうか、分かるようにしておく工夫をほどこす。どうするか、コスチュームを使う。
取り掛かる前にいったん敵とかスターを消しておこうか。
スプライト「エンティティ」を開く
スポーンさせる数をゼロにしておこう。
スプライト「アイテム」を開く
アイテムもスポーンをゼロにしておく。
スプライト「レベルの近接範囲」を作る
さっき言ってたコスチュームを使った工夫をしていくよ。
スプライト「レベル」を複製して。
名前を、ちょっと変わってるけど、レベルの近接範囲っていう名前にしておこう。
コスチュームを修正するよ。
選択ツールを選んで。
全選択しよう。
この状態で、枠線を20にする。
↓こんなかんじになるよね。
この黒い枠線の部分にレイキャスターのビームが触れたら当たり判定をするようにしていく。
逆に言うと、それ以外の場所では当たり判定は行われなくするってこと。
マップ表示を切り替えるところだけ消す
このスプライトは人間にはいっさい見える必要ないから、このブロックは消そう。
スプライト「レイキャスター」を開く
よし、じゃあさっき言ってたコーディングをしていくぜ。
定義「_ハイスピード・レイ」を作る
なんかカッコいいw
定義「_シングル・レイ」から一部移植するよ。
「レベルに触れた」まで繰り返すループを_ハイスピード・レイに移動しよう。
↓こんなかんじにしてね。
_ハイスピード・レイにはずっとループを置く。
この中で条件ブロックを置いて「レベルの近接範囲に触れてないなら」という条件を作る。
レベルの近接範囲に触れてないということは、さっき作った太い線に当たってないから、カベからは遠いよね。だから10歩動かしてしまおう。何も障害物がないから大股でビューンと動く感じ。
ちなみにこの10という数字は、さっき枠線を20にしたことと密接に関係している。あまり大きな歩数動くと、線に触れる前にカベに当たってしまったり、カベを通り越してしまったり不具合が起きる。
この条件ブロック内に新しくループを作る。
今度は「レベルの近接範囲に触れるまで繰り返す」というループだよ。この中でも10歩動かそう。これで太い枠線かカベか、どっちかに当たるわけだ。
当たったらちょっと下がる。どのくらい下がるか。枠線の太さが20だったよね。実は枠線の太さは1につき0.5歩分に相当する。だから太さ20は10歩分に相当するんだ。そこで半分よりも少し多めのマイナス6歩下がっておく。確実にカベの当たり判定が行われるためだ。
マイナス6歩下がって、そろそろカベがあるということが分かっている状態なので、ここからは従来通り慎重にレイキャスティングを進めていく。
8回繰り返すループを置こう。
その中で1歩ずつ動かすよ。
そしてレベルに触れたらこのスクリプトを止めよう。
これでカベに近づくまでは大股でガシガシ進み、カベに近づいたらゆっくり慎重に進むという柔軟なビームができあがった!
CHECK! パフォーマンスがあがったかテストする
さぁて、どうなったかな?
どぇぇぇぇ!なんなんすか?!このスムーズな描画!動き!神ってる!わーーーーー!
解像度1なのにヌルヌルだぜ……。
まとめ
いやぁ今回は神回。マジでパフォーマンス爆上げ。ちなみにパフォーマンスを上げることを専門的にはパフォーマンスチューニング(パフォチュー)とかって呼ぶ。今回は神パフォチュー。
こんなことができるようになったぞ。
- デルタを算出しFPSの管理ができるようになった
- デルタ値に合わせてプレイヤーと敵の移動を最適化した
- レイキャスティングのムダを省き負荷を下げ精度までもが高まった
なにこれ……超高額のスクラッチ講座にでも参加したような気分。いや、国内でこれだけの技術を教えてくれるスクラッチ講座なんて存在しないから、もはやスクラッチ留学したようなお得な気分だぜ……。ふぅー最高。
まぁこれでスクラッチキャットもスムーズにスターを集めてサッサと脱出できるように……ってあれ?なになに?まだなにか問題があるの?次回もチェックしてみてくれ!
グリフパッチさんの動画
このチュートリアルは世界No.1スクラッチャーとして名高いグリフパッチさんの動画を参考にしているよ。ただし手順を一部変えているところもあるんだ。
- ① まず2Dマップを動き回れるようにしよう!
- ② さっそく3D化しちゃおうぜ!
- ③ 壁にスキマがあって敵から丸見え!?やっば
- ④ 陰影をつけて立体感マシマシにしよう
- ⑤ トゲトゲやユガミを補正してハイクオリティ3Dの一歩を踏み出そう(爆速オンライン3Dゲームの作り方 #05)
- ⑥ 壁の衝突判定の基本を作ろう
- ⑦ 壁に触れてると進めない!?移動を改善しよう
- ⑧ ついに敵が現れた!距離感の計算ってどうやる?
- ⑨ 奥行きを実装して壁の後ろに隠れられるようにする
- ⑩ エンティティに陰影をつける
- ⑪ 敵がプレイヤーに向かって迫ってくるように実装する
- ⑫ スターを実装しよう!
- ⑬ 爆速3D爆誕 (いまここ)
- ⑭ 壁に画像(テクスチャ)を貼り付けてリッチな3D空間を演出する
- ⑮ テクスチャの壁を洗練させて本格3D完成!
- ⑯ シメだ!モバイル & オンライン化をするぞ
- ⑰ 【おまけ】敵がプレイヤーを見つけたら追いかけるロジック
- ⑱ 【特別編】マウスに合わせて視線を上下させる方法
- ⑲ 【特別編】マウスでターンするスピードを調整する
- ⑳ 【特別編】敵をジャンプで乗り越える