AOYAMA KOJI's PROGRAMMING BLOG

メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】初中級者向けプログラミング解説

2020/08/16
メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】

 メガホンDEポンのお話もおそらくこれでラストとなりました。 前回円と円の当たり判定と、当たった位置を求める方法を紹介しましたが、 その後に跳ね返す処理を今回ご紹介します。


接戦に対して入射角と反射角が等しくなるように跳ね返す


メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】 fig.2
 跳ね返す処理がイメージとしてどういったものか、をにしました。
 左から緑のボールが迫り、右に黄色いメガホンがある状態です。 この図ではボールがメガホンの上っ面に当たり上方向に跳ね返っていますね。
 この処理は、ボールの円とメガホンの円が接触している状態で考えます。 それらの円の共通の接線に対して、 入射角反射角が等しくなるように反射後の速度を求めればOKです。 つまりこの接線の角度によって跳ね返る方向が決まります。

方程式は立てられるけれどちょっと大変


 ここで紹介した方法で、円と円の当たった位置は求められています。 それがわかればその2つの円の接線の式も立てられます。 ボールの速度も、角度を含めてわかっています。
 それらわかっている情報や条件を数学的に組み合わせて方程式を立てれば、反射後の速度を求めることができます。 できますが、、、、正直なところ少々面倒です。

空間を回転させて考えやすくする


メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】  そこで、ちょっとした工夫をします。 図のように空間を回転させてしまうのです。
 具体的には、反射する壁的なものがちょうど垂直あるいは水平になるように、空間全体を数学的に回転させます。

垂直な壁に対する反射はX成分を反転


メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】 fig.3  接線がちょうど垂直になるように回転させてしまえれば、 この接線をに見立てて、その壁で反射することを考えることになります。
 そうなると反射はとても簡単です。 一般的な2Dゲームもそうだと思いますが、このゲームでは速度を、 横軸のX成分と縦軸のY成分を用いたベクトル形式で表現しています。 そのため垂直の壁に対しては、横方向すなわちX成分だけ反転させることで反射した状態にできます。 反転というのはプラスとマイナスを逆にすることです。 それが次の図です。
メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】 fig.4
 数学的には、跳ね返り前の速度ベクトルが\((V_x,V_y)\)であれば、跳ね返り後の速度ベクトルは\((-V_x,V_y)\)になります。

逆回転で元に戻すのを忘れずに


 このように空間を回転して処理をしたら、最後に逆回転して元の座標系に戻す必要がありますが、それで完成です。

同一方向へ進んでいる場合は反射をさせない


 ここで少々注意すべき事項があります。
 例えばボールが左に動いている状態で、プレイヤーが右から左に追いかけ、同一方向に進んでいる状態でボールを叩いた場合、 ボールは左への速度をより加速させるでしょう。 しかし今まで説明した式で反射させると、左に動いていたボールは右に動くことになります。 これは明らかにな動きですね。
 つまり接触した際にその位置や速度の関係で反射させないべきと判断すべき場合もあります。 こういったことも空間を回転させて考えると、とてもわかりやすくなります。
 今回の例は、回転後ボールが右、メガホンが左に位置しています。 そのため、回転後のボールの速度のX成分がに向かっているなら跳ね返す。 に向かっているなら跳ね返さないということになります。

プレイヤーの速度を加算


 プレイヤーがボールを追いかけてメガホンがぶつかった場合に、跳ね返らない処理になるだけでは少々不自然です。
 そういったことを考慮してメガホンDEポンでは、 ボールを反射させるタイミングでプレイヤーの速度もえています。 プレイヤーの速度の一部をボールに加える形で、より激しくぶつかったらボールはより速く進むようにしています。 それでできるだけ直感に近いというか、自然になるようにしています。
 なお加算するのはプレイヤーの速度のうち、ぶつかった接線に対して直行する成分のみです。 つまりこれも空間を回転させて壁を垂直にした状態にしておけば、プレイヤー速度のX成分だけ考慮すれば良いことになります。
 ボールの跳ね返りの考察のために空間を回転させたときに、こちらも一緒に処理してから、 まとめて逆回転で元に戻すと計算回数らせます。

空間を回転させる数学


 ここまで空間を回転させられる前提で話を進めてきました。 空間の回転は実際にできます。角度\(\theta\)だけ回転させるのは以下の公式です。
\( \begin{pmatrix} x' \\ y' \end{pmatrix} = \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} \)

 この公式は、行列と呼ばれるものを用いて各座標\((x,y)\)を\((x',y')\)に変換するものです。 \((x',y')\)が回転後の座標になります。

行列の計算方法


 行列の計算方法も記載しておきますと、この式を行列を使用せずに記載すると以下になります。
\(x' = x \cos\theta - y \sin\theta \\ y' = x \sin\theta + y \cos\theta \)

 詳細な説明は省略しますので、ご存知無い方で、興味がある方は、色々と調べてみていただけると!

実際には角度は不要


 位置関係から角度を調べて…というのがきれいですが、 角度を求めには三角関数を先に計算することになります。 そのため実際の計算では角度\(\theta\)まではめずに、 \(\sin\theta\)と\(\cos\theta\)を求めたらそれをそのまま使用します。

行列が高校のカリキュラムから落ちた件


メガホンに当たったボールを跳ね返す【絵が動くゲームを作ってみよう】 fig.5  私は高校の授業行列を習いましたが、 2012年以降に行列は高校のカリキュラムの範囲になったそうですね。 つまり今回説明している内容は大学数学ということになります。 少々残念に思うところはあるのですが、実は結構納得しています。
 高校で習った行列は、その要素が2行2列のものだけでした。 今回登場した行列はまさにその2行2列ですけれど、行列は行も列も3以上のものを普通に扱います。
 行列は効果的に使えばとても便利で、 例えばゲームプログラミングでは3D空間の処理に使用します。 ただしその要素数は4行4列です。 それで空間各種物体回転および移動させます。
 これに限らず行列には他の使い方もありますが基本的に2行2列では不足で、 なんというか中途半端なのです。 そのため要素が多いものを含めてまとめて大学で勉強するというのは、 少なくとも実践的な意味で私は納得できます。
 カリキュラムを決めている人は色々と考慮しているのでしょうね。 大変なお仕事だなと思います。
 ちなみに2行2列の行列でできる代表格は平面を回転させることです。 まあ今回の例ではかにその回転で十分役に立ちますけれど。

ゲーム業界ではマトリックス


 ちなみにゲーム業界では行列のことをマトリックスあるいはマトリクスと呼ぶことが多いので、念のため記載しておきます。 英語のmatrixですね。 ただ映画マトリックスを英語で聞くとmatrixは「メイトリックス」的な発音になるみたいですので、 英語の発音は別に覚える必要がありそうですけれどね。

まとめ


 今回は、壁的なものに対して反射する処理を、空間を回転させることでえやすくする方法を紹介しました。
 空間を回転してしまえば簡単になるということで、ある意味ではズルですね。 回転に数学を使用していますので知らないと回転そのものが難しいということはあるでしょうけれど。 回転できることや方法を知っていればグッと簡単になります。
 難しい数式を解けばいというわけでもありませんし、 簡単になるならその方が良いと思います。 今回の例に限らずですね。

補足

・メガホンDEポンはキャラクターがふっとばされる処理は入っていないため、跳ね返す処理はメガホンは固定してボールだけ跳ね返せばOKです。
・ベクトルと反射まわりについて、数学と書きましたが正確には物理学に属する話かもしれません。
・数式表現にMathJaxを使用しております。助かります!


カテゴリー:絵が動くゲームを作ってみよう,当たり判定
[PR]