RPGツクールと数学のブログ

RPGツクールと数学についてのブログです。

ゲーム作りに使える高校数学(後編)

前回記事の続きです

高校数学がゲーム作りに使える場面を紹介していきます。今回の内容は全体的にちょっと難しいです……確率はよく使うので、そこがメインということで^^;

平面図形・ベクトル

2D・3D関わらず、ゲーム画面をベクトルで考えると楽になる場面が多くあります。当たり判定の計算を行う際には図形同士の重なりの様子を確認する式を作る必要があるので、平面図形やベクトルは御用達です。

丸同士の当たり判定は次のようにして考えることができます。

f:id:fermiumbay13:20180106155243p:plain

半径がそれぞれr_{1},r_{2}の円同士が衝突したかどうかを判定する場合は、二つの円が重なっているかどうかを調べる式を考えればよいです。中心間の距離がr_{1}+r_{2}になればちょうど二つの円がくっついた状態になりますので、それ未満になったときに衝突、とすれば円同士の当たり判定ができます。中心座標がそれぞれベクトル\vec{c_{1}},\vec{c_{2}}で表されているとき、次式を満たせば衝突、と考えられるわけです。

\displaystyle \left| \vec{c_{1}} - \vec{c_{2}} \right| \lt r_{1}+r_{2}

 ベクトルの表記がわかりづらければ、中心座標がそれぞれ(x_{1},y_{1}), (x_{2},y_{2})のように座標表記にして、次式でも求められます。実装する場合はこちらの式をそのまま入れたほうが楽ですね。

\displaystyle \sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}} \lt r_{1}+r_{2}

あるいは、ルートの計算は案外重たいので、両辺2乗した式を使うのもよいです。

\displaystyle {(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}} \lt (r_{1}+r_{2})^{2}

ベクトルを知っていると、このような当たり判定計算が楽になる機会が多くあります。

例えば次のような場合を考えてみます。

f:id:fermiumbay13:20180106160252p:plain

長方形の2D画面に線分Op_{1}があり、その画面上に点\vec{p_{2}}があって、この点\vec{p_{2}}が線分を境界として右側にあるかどうかを判定したい、という謎のシチュエーションを考えます。この場合は、2次元ベクトルの外積を使うとあっさり求められます。

外積は高校数学に出てきませんが、2次元平面における外積はいたってシンプルです。

\vec{p_{1}}=(x_{1},y_{1}), \vec{p_{2}}=(x_{2},y_{2})に対して、
\vec{p_{1}}\times\vec{p_{2}}=x_{1}y_{2}-x_{2}y_{1}

内積はドットの記号で表しますが、外積は掛け算記号を使って表します。そして、外積には次の性質があります。

\vec{p_{1}}\times\vec{p_{2}}\gt0のとき、\vec{p_{1}}から反時計回りの位置に\vec{p_{2}}がある
\vec{p_{1}}\times\vec{p_{2}}\lt0のとき、\vec{p_{1}}から時計回りの位置に\vec{p_{2}}がある

どっち周りに回転させた位置にあるかが、外積の答えの符号を調べることで分かるのです。上の図の場合は\vec{p_{1}}から時計回りの位置に\vec{p_{2}}があるので、\vec{p_{1}}\times\vec{p_{2}}\lt0かどうか調べればよいことになります。
(ゲーム画面は上下が逆なのでそこだけ注意です)

式と曲線

媒介変数表示は、キャラクターを自由自在に動かすために便利な記法です。円運動をさせようと思ったら、次のような値を指定すればOKです。

\displaystyle \begin{cases}x=\cos \pi t\\y=\sin \pi t\end{cases}

x,y座標値の変化を、変数tの上昇によって表します。

f:id:fermiumbay13:20180107032024g:plain

円じゃなくて楕円上の移動にしたい場合は、引き延ばしたい方向の変数に何か係数を掛け算してやればいいだけになります。横に2倍伸ばすならこうなります。

\displaystyle \begin{cases}x=2\cos \pi t\\y=\sin \pi t\end{cases}

f:id:fermiumbay13:20180107032159g:plain

各座標の値を一つの変数tを使って表現できるので、複雑な動きを作る場合に便利です。

複素平面

虚数などいつ使うのか、というのはたびたび持ち出される話題ですが、ゲームでは主に図形の回転などに用いられます。ただ、複素数を使わずにベクトルや行列を使っても同様にして表現できるので、2Dゲームであればそんなに使われないかもしれません。*1

複素平面において-1倍するというのは反時計回りに180^{\circ}回転するのと同じ意味なので、回転を掛け算で表現出来るのが便利な所です。上述の円運動も、複素平面上の運動として考えると次式で簡潔に表現できます。

z=e^{\pi t i}

t=0のときz=1(座標(1,0))、\displaystyle t=\frac{1}{2}のときz=i(座標(0,1))、t=1のときz=-1(座標(-1,0))、となって、確かに回転していることが分かります。

虚数を使えば動作をシンプルに記述出来る場合があるのが利点でしょうね。複素数型の変数を使うことのできる環境であれば導入を考えてみてもよいかもしれませんが、著者自身があんまり使っていないので、これぐらいにさせてください;_;

行列

行列は掛け算をすることによって、ベクトルを変換する力を持っています。よく使われて便利なのは一次変換の式ですね。

\begin{bmatrix} x'\\y' \end{bmatrix}=\begin{bmatrix} a\quad b \\ c\quad d \end{bmatrix}\begin{bmatrix} x\\y \end{bmatrix}

座標(x,y)に、定数a,b,c,dからなる行列を掛けて、新しい座標(x',y')に変換する方法です。その一例が下に挙げる回転行列です。

\begin{bmatrix} x'\\y' \end{bmatrix}=\begin{bmatrix} \cos \theta \quad -\sin \theta \\ \sin \theta \qquad \cos \theta \end{bmatrix}\begin{bmatrix} x\\y \end{bmatrix}

原点(0,0)を中心に、角度\thetaだけ反時計回りに回転させる式です。実際には原点を中心とした回転では使いづらいので、一次変換を拡張した次の式を使うのが便利です。

\begin{bmatrix} x'\\y' \end{bmatrix}=\begin{bmatrix} \cos \theta \quad -\sin \theta \\ \sin \theta \qquad \cos \theta \end{bmatrix}\begin{bmatrix} x-x_0\\y-y_0 \end{bmatrix}+\begin{bmatrix} x_0\\y_0 \end{bmatrix}

座標(x_0,y_0)を中心とした回転です。

例えば下図は、点(250,50)から中心(100, 75)の円に沿って反時計回りに60^\circ回転する様子です。

f:id:fermiumbay13:20180114135641j:plain

回転した後の座標はさっきの式を用いて次式で得られます。

\begin{bmatrix} x'\\y' \end{bmatrix}=\begin{bmatrix} \cos 60^\circ \quad -\sin 60^\circ \\ \sin 60^\circ \qquad \cos 60^\circ \end{bmatrix}\begin{bmatrix} 250-100\\50-75 \end{bmatrix}+\begin{bmatrix} 100\\75 \end{bmatrix} \fallingdotseq \begin{bmatrix} 196.65\\192.40 \end{bmatrix}

点の座標を変換するだけではなくて、媒介変数表示された曲線式を点の座標として当てはめてやれば、曲線全体を回転させるなんてこともできます。複雑な軌道を考える際には便利なツールです。

確率

ゲームに確率は欠かせません。これだけは覚えておきましょう。

和の法則

AとB、少なくともどっちかが起こる確率:
(Aが起こる確率)+(Bが起こる確率)-(A, Bが同時に起こる確率)

積の法則

AとBが同時に起こる確率:
(Aが起こる確率)×(Bが起こる確率)

特に、A, Bが同時に起こらないことであれば、和の法則はもっとシンプルに各確率の足し算で済みます。

例として、敵を倒したとき、その敵がレアアイテムをドロップする確率について考えます。

アイテムドロップ確率:20%
ドロップしたアイテムがレアである確率:25%

この場合は、アイテムドロップが起こってかつレアである、ということで、同時に起こる確率を求めれば良いため、積の法則が使えます。20%=0.2、25%=0.25にそれぞれ直しましょう。

0.2 \times 0.25 = 0.05

0.05=5%なので、全体としてレアアイテムをドロップする確率は5%となります。20体倒せば1体は落とすという計算になりますね。

ゲームを作る場合はこれらの確率そのものを設定することになりますから、実際にそれが起こる確率を計算し、現実的にありうるのか吟味する必要があるでしょう。

例えばこんなミニゲームがあったとします:

f:id:fermiumbay13:20180114145847p:plain

宝箱が10個あって、そのうち5個にあたりが入っています。はずれを何回引いてもいいので、すべてのあたりをなるべく早く見つけろというものです。最速のパターンは、スタート付近にある5個すべてにあたりが入っている場合ですよね。そうなる確率はどれぐらいなんだろう?というのが気になります。*2

これも高校数学の確率を使えば求めることが出来ます。10個のうち最初の5個があたりになる確率ということで、10個のうちから5個を取り出す組み合わせのうちの1通りに他ないですね。すべての組み合わせは次式で求まります:

\displaystyle _{10}C_5=\frac{10 \times 9 \times 8 \times 7 \times 6}{5 \times 4 \times 3 \times 2 \times 1}=252

この中の1通りということで、求める確率は\displaystyle \frac{1}{252}(約0.4%)となります。直観的にはもうちょっと出るんじゃないか?と思うのですが、案外無いもんなのですね。

確率分布

ふつう確率といえば、1~100のうちのどれかが出る確率、というようにすべての事象が同一の確率で出るものと暗黙のうちに扱います。こういうのを同様に確からしといいます。

ところが、別にそういうものに限る必要はないわけで、例えば50が一番出やすくて、1とか100みたいな端の方の数はあんまり出ない確率があったっていいわけです。このような、確率の分布のことを確率分布といいます。冒頭の等確率で出る分布のことは一様分布といいます。

RPGで敵とランダムエンカウントするまでの歩数の確率を一様分布にすると、敵とエンカウントした直後に1, 2歩歩くだけでまた敵が出る、みたいなことが起こりうるのでちょっとなぁ、と思うことがあり、下記のようにこの確率分布を正規分布に置き換えてみたというのがあります:

エンカウント確率分布 - RPGツクールと数学のブログ

f:id:fermiumbay13:20180114151041p:plain

正規分布は計算が面倒ですが、扱うと便利な確率分布の代表です。シンプルに構築する方法として、こんな方法もあります:

(1) 一様分布で1~100の乱数を作る
(2) (1)を10回繰り返し、出た値すべてを足す
(3) それを10で割る

使っているのは一様分布の乱数ですが、こうするだけで正規分布っぽくなります。すなわち、中心の50が最もよく出やすく、1とか100は滅多に出ないようになります。実用的にはこうやって扱うのがいいかもしれません。

 

高校数学がゲームに使える場面を色々と列挙してみました。結構使うと便利なものが多いので、ぜひぜひ色んなことに使っていただきたいです。数学なんて何の役に立つんだ、とさじを投げている方を見かけたら、ぜひともゲーム作りを提案してみてくださいね^^

*1:3Dゲームでは3次元物体の回転として、複素数の強化版である四元数がよく用いられます。ここでは割愛です。

*2:実際にむかし作ってたゲームで、当時気になっていました。