P5.エアホッケー.02「動くパックの登場?」
壁の所に来たら跳ね返るような感じに動くパックを登場させる。物理でやるならApply Impulse
や、Apply Force
だが今回は使わない。普通にオブジェクトを動かす場合はTranslate Object
とTime
ノードの合わせ技を使う。普通は、こっちの方を先に覚えるかな。
カメラとライト
パックが動いても、カメラとライトがちゃんと設定されていないと [▶ Play] しても見えないからな。イイ感じの所にセットしておこう。
〇 カメラ: テンキーの 0 でゲーム画面上どう見えるか確認しながら位置を決めればいい。まー、一番いいやり方は Lock Camera to View でやるやつかなー? それから、Clip End は 150m くらいに設定かな。これより短いと向こうの方が欠けるでしょ、多分。(ココ参照。) ちなみに俺はこの位置と回転にセットした。
Location | Rotation | |
---|---|---|
X | 0 | 64 |
Y | -88 | 0 |
Z | 36 | 0 |
〇 ライト: ライトはやっぱっり Sun にしてステージの下に置くよね、じゃまだし。(ココ参照) 回転は適当。
Location | Rotation | |
---|---|---|
X | 0 | 37.3 |
Y | 0 | 3.16 |
Z | -10 | 107 |
で、整理整頓は心がけておこう。
パックとマレット
パックを置くのと、ついでにマレットも置いておこう。一緒のコレクションに置くだけ、簡単。
❶ マレット(com): コンピュータが動かすマレット。シリンダーから出来てます。直径3m、高さ1.8m。色は適当にどうぞ。
Location | Scale | |
---|---|---|
X | 0 | 1.5 |
Y | 30 | 1.5 |
Z | 0.95 | 0.9 |
❷ マレット(player): プレーヤーが動かすマレット。大きさは com 用のと同じ。色は適当にどうぞ。
Location | Scale | |
---|---|---|
X | 0 | 1.5 |
Y | -30 | 1.5 |
Z | 0.95 | 0.9 |
❸ パック: とりあえず置いてみた。直径は2m、高さが90cm。
Location | Scale | |
---|---|---|
X | 0 | 1 |
Y | 0 | 1 |
Z | 0.5 | 0.45 |
パックもマレットも床から少し浮いてるのは、物理で動かそうとしていた時のなごり。別に床に埋まっててもどうでもいい。大事なのは直径(というか半径と言ってもいいけど)。パック2mとマレット3m。跳ね返る時にこの数値を使う。
アウトライナーだとこんな感じになるようにしてね。
(まだ扱ってないのは、"Stage" コレクションの "Tenjyo" と、"Kami" コレクションだな。)
パックにノードトゥリーを貼る
Trait(トレイト)の付け方は大丈夫だろ? パックに付ける内容は、まずはこう。ただ、今後どんどん変更していくから注意だ。
ちっちゃくって何が書いてあるか分からないので、部分的に拡大して解説する。(これがノードスクリプトの弱点だよな・・・)
❶ パックの初期値を設定: ここではパックの初速を決めている。
・On Init
: このスクリプトが貼ってあるオブジェクトが Active(アクティブ)な Scene(シーン)に出たとき最初に1回だけ呼び出される。と思う。アクティブなシーンとは何ぞや? って思うが、たぶんメインカメラが映してるシーンのこと。前、レンダリングの1回目とか書いた気がするけど、別にカメラに写ってなくてもここは呼ばれるからね、1回。出てきた時、最初に1回だけ呼ばれるものって覚えて置けばイイと思う。基本、ここではオブジェクトの初期値を設定する。
・Set Property
: オブジェクトにデータを保存するためのモノ。スクリプトじゃなくてオブジェクトにデータを入れ込むってのがおもしろいね。今回はパックが動く速度を設定したいので "myDir" という名前で下で設定したベクトル値(x: -20, y: 20, z: 0)を保存してもらっている。速度は秒速。だから、毎秒x方向に-20m、y方向に20m進むよってことね。プロパティには何でも入れることが出来るので便利なんだけど、逆に注意が必要とも言える。
・Vector
: ベクトルの値を入れるとき使う。(あー説明になってないな。) Armory は 3D Game Engine なので、ベクトルは3次元のしか無い。
❷ パックのメインループ: ここでパックを動かす。(写真クリックで拡大)
・On Update
: 毎フレーム呼び出されるモノ。ただ、なんだか Armory が 06 になってから、3パターンで呼べるようになったみたいだな。
- Update: 普通のやつ。
- Late Update: これは恐らくカメラ用。全部のオブジェクトが動き終えてから、カメラは最後に位置を決めたいでしょ。
- Pysics Pre-Update: これは物理用。物理の力で動かす奴はコレ使うはず。物理のタイミングと描画のタイミングが違う為だと思う。多分。
今回は、カメラでもないし、物理も使ってないので普通のでOKだ。
・Translate Object
: ベクトル値で入れた分(方向と距離)だけオブジェクトを動かす。
・Time
: 時間に関する2つのデータを取り出せる。
- Time: ゲームが始まってからの時間(秒)を取り出せる。Float型で出て来る模様。
- Delta: 前のフレームから何秒経ったかを取り出せる。Float型。
1の Time はイイとして、2の Delta は非常に大事。
ゲームの画面描写はパラパラ漫画なのはご存じだとは思うが、1枚の表示を何秒にするかで滑らかさが異なるよね。まー、1秒で何枚使うかって考えてもいいけど。例えば1秒で50枚使ったら、1枚の表示時間は、、、50分の1秒だから、、、0.02秒か? ま、これが Delta だ。パラパラ漫画の1枚の表示時間、それが Delta。
ゲームだとご存知のように、大体1秒60枚(60FPS / FPSはframes per second)で動かすのが多いだろ。すると、0.016666・・・秒ってなるな。この時間のこと。
で、なんで大事かって言うと、オブジェクトを動かしたい時の速度は秒速。つまり1秒で何メートル動かしたいかを設定したわけだ。だけど、On Update
には毎フレーム来ちゃうわけだろ、だから、パラパラ漫画で言えば1枚の表示時間(= Delta 秒)で動かすだけの距離を考えないとイケナイ。
くそ簡単に言えば、例えば「秒速150mで動くものの場合、Delta秒では何メートル進みますか?」を解きましょうって考えるわけだよ。算数だな。秒速150mは1秒で150mなんだから、「1秒で150m進むものは、Delta秒で何mすすみますか?」ってのと同じことじゃろ。
1(秒):150(m) = Delta(秒):X(m)
小学生の時やった比例式、"内項の積=外項の積"で一発や。
X = 150 × Delta
だから、Delta秒で動かす距離は "秒速 × Delta" で出るってことなんだよ。簡単だが、すごい大事なことなのだ。
・それをやってるのがVector Math
の部分。設定した秒速をGet Property
で取って来て、xとyにDeltaをいれたベクトルと掛け算してる。つまり"秒速 × Delta"をやってるってことね。(zには動かないから入れなくていいよ。) Vector Math
の "Multiply" は掛け算のとこ。
例えば、Aベクトル(x1, y1, z1)とBベクトル(x2, y2, z2)を "Multiply" するとベクトル(x1 * x2, y1 * y2, z1 * z2)が出て来るってことね。各項を掛けたものが各項に入る感じだ。
ここまでで、一応パックは毎フレーム、進むべき方向と距離を行くわけだ。
だけども壁があったら、跳ね返らないとイケナイだろ。その判断と処理をしてるヶ所が、右に4つならんだSend Event
だ。別に❸~❻を横にならべてもいいけどすげー長くなるからイヤだろ。だからまとまりを作ってその場所に飛ばしているわけだ。まー、見やすくなってよかったねってことだな。
・On Event
とSend Event
: On Event
でつくった場所(イベント)にSend Event
で処理を飛ばす。これはセットで覚えてね。イベント名を入れるところがあるだろ、ここに名前を付ければいいだけだ。作ったイベントはリストで出してくれるわけではないので、打ち間違いに注意な。
❸On Event
"LLLL": ここではパックが左の壁で跳ね返るように処理をしている。イベント名 "LLLL" で飛んでくるところ。
・Get Location
: オブジェクトの位置を取ってこれる。位置はベクトル型で入ってくる。今回欲しいのはxの値だけなので、、、
・Separate XYZ
: ベクトルの成分を分解して取り出せる。これを使ってxの値だけ持ってくる。なんでかって言うと、床の大きさが横30m×縦70mだろ。横だけ考えれば、±15mの所が壁だ。で、パックの半径が1mだから、それを引いて、パックの(中心)位置が-14mのところか、それよりもっと過ぎたら跳ね返る処理をすればいい。その判断をGate
でしてる。"Less Equal" っていうのは "<=" のこと。
跳ね返すにはどうすればいい? そう、次に自分の進む方向のx方向を反転させればいいだろ。だから、次の所で "myDir" のxに-1を掛ける処理をしてる。プラスのモノに-1を掛ければマイナスに、マイナスのモノに-1を掛ければプラスになる。つまり-1を掛けるとプラマイが反転するんだよ。簡単だろ?
❹On Event
"RRRR": 今度は右の壁のところまで来てるか調べて、跳ね返るように処理をしている。イベント名 "RRRR" で飛んでくるところ。
まー、❸とほとんど同じなんだけど、"-14" じゃなくて、"14"。"Less Equal" じゃなくて "Greater Equal"(">=")になってるだけ。右壁だからね。
❹On Event
"DDDD": 今度は下(自陣の壁)のチェック。
下の場合はxじゃなくてyのチェックが必要でしょ。だから、Separate XYZ
ではyを持ってくること。あと、床の縦は70m、半分が35、そこからパックの半径-1を引いて34。つまり±34でチェックする。下なら-34ね。
縦の場合、反転させるのはxじゃなくてyだから、 "myDir" のyに-1を掛けるぞ。注意。
❺On Event
"UUUU": 上(敵陣壁)。
- xを取って来るのかyをとってくるのか。
- "Less Equal" か "Greater Equal" か。
- 反転させるのは(-1を掛けるのは)xなのかyなのか。
そこんとこ注意!
テストプレイ
壁のなかで動くはず。ただし、ゴール処理はしてないので永久に動くのだ。(Gif画像はメンドクサイから無し。)
でも、あれだ、ゲーム開始でいきなりパックが動いてたらビックリするじゃん。だからスペースキーを押したら動くようにしてみようと思う。ではまた次回。
本日のポイント
On Update
には3パターン。- オブジェクトを動かすには
Translate Object
。ただし、Time
の Delta を掛け算する意味、理解すべし。 - べクトルの計算は
Vector Math
。ただのMath
とは違いマス。 On Event
とSend Event
のペアで綺麗に処理。
〇 次回、玉スポーン予定。