投げる!変化球

どうも、もにょさんです。今年度のアドベントカレンダーはお初。23日分の記事のつもりですが投稿が24日になってしまいましたね悲しい。

ゲーム創作研究部のアドベントカレンダーなのにゲーム創作を研究してない!との声を部の内部からよく聞くので、それっぽいことでも書いておきましょう。

今年度の高専祭では狐っ娘がわちゃわちゃする某方Projectっぽい弾幕STGを展示したのでそれに纏わるアレコレを少々。そんな専門的なことはやりません。数学徒とか物理学徒にマサカリ投げられちゃうヤバイヤバイ。

投げる!

さてさて弾幕STGなんで自機も敵も弾を撃たないとお話にならないねぇというわけです。変化球を投げる前には直球を知らなくてはいけません。だったらどうやって弾を動かしたらいいんでしょ。
今回は無能で怠惰で役立たずな白狐の深草すすきさんにお越しいただいて、色々と見てみましょう。

とりあえず飛ぶ弾

彼女の居る位置、すなわち弾の発射される位置をここでは仮に点(0,0)としておきます*1f:id:anctgcc:20141223230646p:plain
まず画面に弾を表示してあげるには、その弾がどこにあるかが分からないといけません。
弾には「位置」の情報を持たせてあげます。2Dゲームなんで難いこと考えずにX座標とY座標があればいいですね。2次元ベクトルで表して、まだ弾は動いていないので点(0,0)に居ます。

次はその座標を動かします。図中の矢印のような、「速度」の情報が要りますね。
1フレーム(60fpsなら1/60秒)あたりに動かしたいX軸方向の距離が2ドット、Y軸方向の距離が3ドットだったら、速度ベクトルは(2,3)です。あとは弾の座標に対して、この速度を毎フレーム足していけばいい話です。
移動をさせていくと(0,0)に居た弾は、1フレーム目は(2,3)、2フレーム目は(4,6)と徐々に動いて、1秒後である60フレーム目には(120,180)に居るはずです。

撃ちたい方向に撃ちたい速度で

でも「X軸方向とY軸方向の速さ」とか言われても分かりづらくはありませんか?
人がボールを投げる時に投げたい方向を向くように、「角度*2」と「速さ*3」で弾を撃たせるほうがいいんじゃなくて?f:id:anctgcc:20141223230643p:plain
というわけで「角度」と「速さ」でもって弾を撃たせます。
三角関数のsinとcosを使えば、角度と速さからX軸方向とY軸方向の速さにすることができます。人が弾の動きを設定するような箇所では角度と速さを入力させ、実際に弾を動かす時に速度ベクトルに変換して、弾を動かせばいいわけです。

速くなる弾

発射されてから徐々に速くなっていく、もしくは発射時は速くても徐々に遅くなる弾です。 f:id:anctgcc:20141223230640p:plain
どれだけずつ速くなっていくか、もしくは遅くなっていくかの加速度*4というものを設定します。
毎フレーム、今の速さに加速度の値を足していく処理をさせれば速さの変化する弾の出来上がりです。発射時の速さを1、加速度を0.1とすると、1秒後には速さが7になりますね。
さてここで問題になるのが、このままでは際限なく速くなっていくということです。ゲームは楽しむものであるので弾速の速い弾を撃ちまくればいいというものではありません*5。速さに上限下限を設けておきましょう。発射から速くなるor遅くなって一定の速さになります。

曲がる弾

いくら速度変化があっても、これでは真っ直ぐにしか進みません。弾が曲がることによって見た目のバリエーションも増えるほか、難易度も上げることが出来ます。出た!初心者キラーだ! f:id:anctgcc:20141223230635p:plain
どれだけずつ角度が変化するかの角速度*6というものを設定します。毎フレーム、今の角度に角速度の値を足していく処理をさせれば角度の変化する弾の出来上がりです。
加速度とは違ってどれだけ角度が増えても360°ぐるっと回るだけなのですが、その変化量に気をつけなくてはなりません。例えば角速度を1°毎フレームとした場合、360°回るのに6秒しかかからないので弾速が遅い場合、ずっと画面内を回り続けるなんて状況になります。画面内に弾が溜まり過ぎる(大爆笑)と処理が重くなるので、そうなる時は角速度を小さくする、速さを上げる、もしくは加速度をつけて徐々に速さを上げましょう。

画面端で跳ね返る弾

出た!初心者キラーその2だ!
f:id:anctgcc:20141223230631p:plain
上下の壁に当たった場合(弾の位置が画面上端よりも上に行ったor下端より下に行った)や、左右の壁に当たった場合(弾の位置が画面左端よりも左に行ったor右端より右に行った)に、ちょうど反射するような軌道を描かせます。
上下壁なら速度のY成分を、左右壁ならX成分を逆符号にしてやれば跳ね返りますね。角度でいえば上下壁なら角度を逆符号に、左右壁なら逆符号に180°足したら跳ね返ります。
自機は画面下側をうろちょろしていることが多く、下を除いた3つの壁でのみ跳ね返るようにしている場合もあります。また、そのままでは跳ね返り続けて画面外へ出て行かず、処理が重くなるばかりか難易度が跳ね上がってしまうので、反射する回数に制限を設けてあげると良いでしょう。

おわり

他にも「自機方向に向かって撃たれる弾」「重力加速度のかかる弾」「指定した速さと角速度で極座標系における動径と偏角が変化する弾」「反射した後に自機方向に向かうよう反射する弾」なんていうのもゲーム内には登場しますが記事が長くなるのでこのへんにしておきます。ここでは弾幕STGでしたが別なジャンルのゲームにも流用できるでしょう多分。
実際このゲーム、高専祭で展示しててまともにクリアしてる人を見たことがないので難易度むずかしいでノーコンクリアくらいしたらご一報ください*7。部公式サイトでゲームは配布中です♥

*1:実際の座標(0,0)は画面左上端です。ちゃんと敵の座標を基準にして弾を発射させてあげましょう。

*2:弧度法の話をしだすとまた記事が長くややこしくなるので避けます。ここでは度[degree]です。

*3:大きさと向きを持つ「速度」と、大きさのみの「速さ」を分けています。[dot/frame]

*4:便宜上こう呼んでいますがスカラー量です。[dot/frame2]

*5:例外有り

*6:便宜上こう呼んでいますがスカラー量です。角周波数の方が正しい?[degree/frame]

*7:制作者はしてません