100日チャレンジ『100日で50弾!』第10回、リフレクトショットです。直線に沿って進む弾が見えない壁で跳ね返ります。動画をどうぞ。

原理自体は単純で、弾の位置をUpdate()内で点検し、指定した範囲から外に出ようとしたとき進行方向を変えればよいのです。例えばx方向、右側の限界の位置に到達したら、弾の進行方向のベクトルをdirとして、dir.x = -dir.x とやればよいわけです。ただ、ぼんやりコードを書いていると反転が短い時間に何度も続けて起こったりしてうまくいきません。そこで、1回符号を反転させたらその後0.1秒間は反転させないようにしました。もっといい方法があると思いますが、とりあえずこれで。コーナーで続けて壁に当たるときなど、このやり方だとヘンなことが起こるでしょう。
今回は反射させる壁はyz平面かzx平面に平行な平面に限りました(画面に向かって左右あるいは上下に進み過ぎたときに跳ね返る)。一般には任意の場所で、任意の平面を考えてその平面で跳ね返るようにします。そのときには弾の進む方向を表すベクトルから、反射後のベクトルを求めなければなりません。次の関数を使えます。
//----------------------------------
//入射ベクトルvが法線ベクトルnの平面にぶつかり、
//反射したときのベクトルを得る。
//n: 平面の法線ベクトル(単位ベクトル)
Vector3 getReflectVec(Vector3 v, Vector3 n) {
return v - 2 * Vector3.Dot(v, n) * n;
}
//----------------------------------
証明は高校の数学レベルです。ここで平面の法線ベクトルとは、平面と直交するベクトルです。長さの決まりはありませんが、上のコードでは単位ベクトル(長さが1)であることを要求しています。またVector3.Dot()はベクトルの内積です。
授業で内積の話をします。2本のベクトルの内積とは、ベクトルの長さの積にcosθ(θは2本のベクトルのなす角)をさらにかけたもの、と高校では定義します。初めてこれをみると大抵「内積っていったい何?」ということになります。何度も質問されました。大学で勉強する線形代数では、ベクトル空間に内積を定義すると、ベクトルの長さ、なす角が求められるようになります。そういうベクトル空間を内積空間というのでした。あるいは、物理学的には物体に力Fをかけ、rだけ変位(位置が変わること)したときF・rは仕事を表します。……といった話をしてあげるとよいでしょう。「定義なんだから憶えればいいんだよ。あとで役に立つから」ではつまらないです。応用面では例えばベクトルの、別のベクトルへの正射影を求めるのに利用して、今回みたいに反射後のベクトルを求めるなどに使えます。
ついでなのでもう少し。プログラミング情報誌で、「プログラミングに数学は不要」と堂々と書いている記事を見たことがあります。「え……?」と思いましたが……。そりゃ、数学とは関係なく開発できるアプリケーションだってたくさんあるでしょう。「これをタップしたらこういう画像が表示される」とかばかりならそれでよい。でも今回みたいな場合、どうするの? いろんな関数を書いて、その中でこの値を求めるために別の関数をコールして、配列のこういう条件を満たす要素をこうして、……ってこれ、要するに数学みたいなもんだよなぁ……。逆らう気はないですが。
では今回はここまで!