ホームへ戻る

 3.7章 特定の角度で弾を飛ばす

 STGなどで弾を特定の角度に飛ばすには、sin,cosの知識が不可欠です。

sin,cosの解説は別の章で行っています

高1で習う三角比ですが、忘れてしまった人は復習しておきましょう。



直角三角形の図の角度30゜の時、「辺の比は 1:2:√3 になる」なんて習ったと思います。
でもシューティングではこんな事覚えてもしょうがありません。
弾は31゜で飛んでいくかもしれませんから、30゜や60゜だけ計算できてもしょうがないのです。



このように、特定の角度θの時、xやyがいくらになるのか計算出来なくてはなりません。
ここで、sin、cosってなんだったでしょうか。

「斜辺÷対辺がsin」と習ったと思います。つまり sinθ=y/r です。
これは



アルファベットの筆記体の書き順で覚えた人も多いかもしれません。

sinθ = y/r
cosθ = x/r

です。これは何のために必要なのでしょう?それは


図1. 弾の飛ぶ方向と座標

今、左下を初期座標として、右上に向かって飛んでいる弾があったとしましょう。
この弾はある角度θで飛んでいるわけですが、
弾がθの方向に、rほど進んだ時、どこの座標に表示したらよいか?という場合に必要です。

sinθ = y/r

であるならば、

y = sinθ × r

であり、同様に

x = cosθ × r

です。つまり、図1の弾は x=cosθ×r, y=sinθ×r ずつ進むことがわかります。

弾は1フレームにrの距離ずつ進むわけですが、よく考えたらこのrはスピードと同義です。
例えば1フレームに1ピクセルずつ進む弾より、10ピクセルずつ進む弾の方が速いですね。

よって、θ,rを固定すると、x,yをひたすら上で述べた量

x += cosθ × r;
y += sinθ × r;

加算することで、座標が更新出来ます。

これをプログラムで確認してみましょう。

サンプルプログラムは、θを変数angle, rをspeed と表しています。
また、Zキーを押すと、座標を中央に戻し、角度や速さをランダムにセットします。Zキーをおしてみて下さい。
生成した乱数の結果は左上に表示されます。


#include <math.h>
#include "DxLib.h"

#define PI 3.1415926f

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定

        int Handle[3];     // 画像格納用ハンドル
        LoadDivGraph( "画像/弾01.png", 3, 3, 1, 14, 16, Handle ); // 3つに画像を分割してロード

        float x=320,y=240,angle=0,speed=1;

        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

                x += cos( angle ) * speed;      // x座標を更新
                y += sin( angle ) * speed;      // y座標を更新

                if( CheckHitKey( KEY_INPUT_Z ) == 1 ){//zが押されていたら変数の中身を変更
                        x = 320;        //初期座標にセット
                        y = 240;
                        angle = GetRand(10000)/10000.f * (PI*2);        //0~PI*2の乱数を生成
                        speed = 0.5f + GetRand(10000)/10000.f * 2;      //0.5~2.5の乱数を生成
                }

                DrawRotaGraph( x, y, 1.0, angle+PI/2, Handle[0], TRUE );//弾を描画
                DrawFormatString( 0,0,GetColor(255,255,255), "angle=%.2f, speed=%.2f\n", angle, speed );

        }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
}

実行結果



弾は3つの画像を分割ロードしています。LoadDivGraph関数の仕様が分からない人はこちらで確認して下さい。
ちなみに、この画像を DrawRotaGraph関数 で描画する際、角度を +PI/2 していますが、
これは、画像のデフォルトの向きが -PI/2 を向いているからです。


弾01.png

↑の弾を使っていますが、プログラム上の角度0は右であり、時計回りが正の方向です。そう考えるとこの画像は -PI/2 の向きを向いています。
ですから、表示する時に +PI/2 しているのです。(画像素材を最初から右向きにしておけば、+PI/2 する必要はなくなります)

x += cos( angle ) * speed;

の計算式は、上で述べた

x += cosθ × r

の計算をソースコードに落としたものです。
このように計算することで、角度angle、速さspeedで弾を飛ばすことが出来ました。

STGではこのようにして、弾の座標を更新します。

→分からないことがあれば掲示板で質問して下さい


- Remical Soft -