アマゾンバナーリンク

初心者弾幕講座その1 2D移動基本編

2020年5月3日

みなさんこんにちは!ジェイです。
今回から数回にわけて弾幕の講座をします。
前にも何回か説明をしましたが、今回はもっと一番基本的な事から説明していきます。

2次元座標での位置

まずキャラや弾幕を描画するには座標データが必要になります。 DXライブラリはDirectXのライブラリなので二次元の座標では左上がX=0,Y=0になります そして、今回のゲームの解像度は640×480なので右下が640,480です。 スコアボードの座標は左上X=32,Y=16 右下X=384,Y=448です。

キャラや弾幕の移動させる方向を決める

上記の説明を元にすると、X座標を+すると右に移動し、-にすると左に移動します。 Yの座標は、+すると下に移動し、-すると上に移動します。

さて、これを念頭にコードを書いてみると以下の様になります。

真上に飛ばしたい場合

X += 0.0;
Y += -1.0;

真下に飛ばしたい場合

X += 0.0;
Y += 1.0;

右に飛ばしたい場合

X += 1.0;
Y += 0.0;

左に飛ばしたい場合

X += -1.0;
Y += 0.0;

上下左右に移動させい場合はこれで済みます。しかし、斜めに同じ移動量1.0だけ移動させたい場合はどうしたらよいでしょうか?

X、Y座標に加算する移動量を求める

結論からいうと、まず角度を求めて三角関数でXとYの移動量を求められます。
その前にMath.SinとMath.Cosに渡す単位はラジアンなので角度から単位を変換させる必要があります。
変換させる式は以下のようになります。

角度→ラジアン

θ=θ×PI/180

ラジアン→角度

θ=θ×180/PI

0~PI2で1週を表すのがラジアン、0~360で表すのが弧度法です。 1周のイメージをわかりやすく図で表すと以下のようになります。

例えば、右下45度に移動させるには以下の様なコードを書きます。
X += Math.Cos(45.0*PI/180);
Y += Math.Sin(45.0*PI/180);
これで右下45度に向かって1ピクセル(斜辺)だけ進ませることができます。

下90度に進めたい場合は、
X += Math.Cos(90.0*PI/180.0);
Y += Math.Sin(90.0*PI/180.0);
になります。

目的の方向に進めるには

角度を指定してその方向に進める方法はわかりました。
次に、今いる位置からターゲットへの方向を求める方法を解説します。

これには2つ方法があって1つはatan2関数を使って角度を求めて三角関数を使う方法と、もう1つは三平方の定理で斜辺(移動量)を求める方法です。1つずつ解説します。

角度を求めて三角関数を使う方法

Math.Atan2は引数に(目標のY座標-自分のY座標, 目標のX座標-目標のX座標)でラジアンで自分のいる座標から相手の座標までのラジアンを返してくれます。コードにすると以下の様になります。

// TX,TYターゲット(目的)のX座標とY座標
// MX,MY自分のX座標とY座標
double angle = Math.Atan2(TY-MY, TX-MX);
X += Math.Cos(angle);
Y += Math.Sin(angle);

三平方の定理で斜辺(移動量)を求める方法

// TX,TYターゲット(目的)のX座標とY座標
 // MX,MY自分のX座標とY座標 
 double c = Math.Sqrt((TX-MX)(TX-MX)+(TY-MY)(TY-MY)); // 目標までの距離を求める
 double Speed = 3.0; // 1フレームで動く移動量
 double vx, vy;
 if(c != 0.0)
 {
     vx = (tx-mx)/c*Speed;    
     vy = (ty-my)/c*Speed;
 }else{
     vx=0;
     VY=Speed;
 }
  1. 目標までの距離(c)を求める
  2. 目標までのX座標から今いる座標のX座標を引いてX座標の移動量を求める
  3. 目標までのX座標から今いる座標のY座標を引いてY座標の移動量を求める
  4. 2と3で求めて値をcで割ると斜辺が1になるので、その値にSpeed(移動量)をかける
  5. 距離(c)が0の場合下に向けてSpeedの分だけ移動させる

この2つの方法で目標までの加算すべきX座標とY座標をそれぞれ求める事ができます。

狙い撃ち弾を打ちたい時には最初のフレームだけ、目的の方向を求めて座標を加算し、誘導弾を作りたい場合は毎ループ、目的の方向を求めて座標を加算すれば実装できます。

次回からは、これを基本にして、様々な種類の弾幕を作っていきます。