シューティングゲームの館

今日 昨日


8. ショットをうつ。

今回はそれぞれのファイルの変更点が多いので、一つ一つみていきましょう。

まず、グローバル宣言のヘッダに、定義と、画像ハンドル変数と弾の構造体を追加します。

弾のかずは、縦いっぱいで15個、それが11列飛ぶものとします。

(写真では縦方向に10行しか発射されていませんが、余裕を持って1列あたり15個用意します。)


一度に11列ショットをうつので

#define PLAYER_MAX_SHOT1 11

1列には最大で15個の弾を使用するので

#define PLAYER_MAX_SHOT2 15

このように定義します。

いきなり全部作るのは大変なので、今の節では、中心の一列だけ、



作ってみます。

弾の画像のハンドルを格納する変数を用意します。

弾の画像は2種類あるので配列で宣言します。

int img_player_shot[2];

次に弾の情報を格納する構造体を宣言します。

構造体には座標であるx,yの他に、弾が今発射されている状態か(1)発射されていない状態か(0)を格納するflagを用意します。

この構造をもった変数を2次元配列で、弾の数だけ用意します。

typedef struct{
    double x,y;
    int flag;
} SHOT_t;

11列、各15個ですから

SHOT_t PlayerShot[PLAYER_MAX_SHOT1][PLAYER_MAX_SHOT2];

こうなります。


/* GlobalVariable.h*/
/* 素材 ver1.00以上必要*/

/* 定義 */
#define PLAYER_MAX_SHOT1 11 
#define PLAYER_MAX_SHOT2 15

/* グローバル宣言 */
int counter=0;
int color_white;
char Key[256];

//画像ファイルハンドル
int img_background[2];
int img_player[4];

//弾の画像
int img_player_shot[2];

//構造体
typedef struct{
        double x,y;
        int status,counter;
} BODY_player_t;

BODY_player_t Player;

typedef struct{
        double x,y;
        int flag;
} SHOT_t;

SHOT_t PlayerShot[PLAYER_MAX_SHOT1][PLAYER_MAX_SHOT2];

グローバル宣言にともない、extern宣言情報を格納するExternGV.hも変更します。


/* ExternGV.h */
/* 素材 ver1.00以上必要*/

/* 定義 */
#define PLAYER_MAX_SHOT1 11 
#define PLAYER_MAX_SHOT2 15

/* extern 宣言 */
extern int counter;
extern int color_white;
extern char Key[256];

//画像ファイルハンドル
extern int img_background[2];
extern int img_player[4];

//弾
extern int img_player_shot[2];

//構造体
typedef struct{
        double x,y;
        int status,counter;
        int shot [11][15];
} BODY_player_t;

extern BODY_player_t Player;

typedef struct{
        double x,y;
        int flag;
} SHOT_t;

extern SHOT_t PlayerShot[PLAYER_MAX_SHOT1][PLAYER_MAX_SHOT2];

実際にプレイヤーから発射する弾の計算と描画はplayer.cppファイルで行います。

ショットの計算を行うPlayerShotDisp関数と描画を行うPlayerShotDisp関数を作ります。

下のサンプルを見てください。

まず、

PlayerShotDisp関数内の処理から説明します。

if(Key[KEY_INPUT_Z]==1 && counter%5==0){
  for(j=0;j<PLAYER_MAX_SHOT2;j++){
    if(PlayerShot[0][j].flag==0){
      PlayerShot[0][j].flag=1; 
      PlayerShot[0][j].x=Player.x;
      PlayerShot[0][j].y=Player.y;
      break;
    }
  }
}

最初のif文は「Zキーが押されているとき かつ 処理が5周に1回行う」処理で、

縦方向に表示する最大数のショットまでflagを調べていきます。

表示できるショットは最大でPLAYER_MAX_SHOT2つまり15個で、

flagはその弾が発射しているか発射していないかを表します。

1なら発射している。 0なら発射していない。

for文でjをまわしながら

if(PlayerShot[0][j].flag==0){

を行うことで、[0]配列の弾で、発射していないものを探すことが出来ます。

今回は1列しか発射させないので[0]しか使いません。最終的に11列発射させるようにします。

if文の条件にマッチした弾は使用可能であるので、

弾の座標を初期化し、弾のフラグを発射中にします。



次に

for(j=0;j<PLAYER_MAX_SHOT2;j++){
    if(PlayerShot[0][j].flag==1){
        PlayerShot[0][j].y-=10;
        
        if(PlayerShot[0][j].y<-20)
            PlayerShot[0][j].flag=0;
    }
}

ここでは、発射中の弾を探し、座標を上に10シフトします。

もし画面外に出たら、発射フラグを0に戻します。



PlayShotDisp関数の中身の説明をします。

for(j=0;j<PLAYER_MAX_SHOT2;j++){
  if(PlayerShot[0][j].flag==1){
    DrawGraph(PlayerShot[0][j].x-10,PlayerShot[0][j].y-18,img_player_shot[0],TRUE);
  }
}

この処理は単に、発射フラグのたっている弾を描画しているだけです。座標は画像サイズが20x36のものを使っているので

x座標に-10, y座標に-18する必要があります。


/* player.cpp*/
/* 素材 ver1.00以上必要*/

#include "DxLib.h"
#include "ExternGV.h"


void PlayerControl(){
        if(Key[KEY_INPUT_LEFT]==1){
                Player.x-=4.0f;
                if(Player.x<10.0)
                        Player.x=10.0;
        }
        if(Key[KEY_INPUT_RIGHT]==1){
                Player.x+=4.0f;
                if(Player.x>409.0)
                        Player.x=409.0;
        }
        if(Key[KEY_INPUT_UP]){
                Player.y-=4.0f;
                if(Player.y<15.0)
                        Player.y=15.0;
        }
        if(Key[KEY_INPUT_DOWN]==1){
                Player.y+=4.0f;
                if(Player.y>465.0)
                        Player.y=465.0;
        }
        DrawGraph((int)Player.x-16,(int)Player.y-24,img_player[0],TRUE);
}

void PlayerShotCalc(){
        int i,j;
        if(Key[KEY_INPUT_Z]==1 && counter%5==0){
                for(j=0;j<PLAYER_MAX_SHOT2;j++){
                        if(PlayerShot[0][j].flag==0){
                                PlayerShot[0][j].flag=1;
                                PlayerShot[0][j].x=Player.x;
                                PlayerShot[0][j].y=Player.y;
                                break;
                        }
                }
        }
        for(j=0;j<PLAYER_MAX_SHOT2;j++){
                if(PlayerShot[0][j].flag==1){
                        PlayerShot[0][j].y-=10;
                        if(PlayerShot[0][j].y<-20)
                                PlayerShot[0][j].flag=0;
                }
        }
}

void PlayerShotDisp(){
        int i,j;
        for(j=0;j<PLAYER_MAX_SHOT2;j++){
                if(PlayerShot[0][j].flag==1){
                        DrawGraph(PlayerShot[0][j].x-10,PlayerShot[0][j].y-18,img_player_shot[0],TRUE);
                }
        }
}

今回表示する画像を増やしたので、その画像を読み込みます。


/* img_sound_load.cpp*/
/* 素材 ver1.00以上必要*/

#include "DxLib.h"
#include "ExternGV.h"

void img_sound_load(){
        img_background[0] = LoadGraph("Sh/img/back/background0.png");
        img_background[1] = LoadGraph("Sh/img/back/background1.png");
        img_player_shot[0]= LoadGraph("Sh/img/shot/player/1.png");
        img_player_shot[1]= LoadGraph("Sh/img/shot/player/2.png");
        LoadDivGraph( "Sh/img/char/player.png" , 4 , 4 , 1 , 32 , 48 , img_player ) ;
}

今回、弾の発射フラグを作ったので初めは全部0である必要があります。そこで、初期化を行います。


/* initial.cpp*/
/* 素材 ver1.00以上必要*/

#include "DxLib.h"
#include "ExternGV.h"


void initialization(){
        Player.x=200.0;
        Player.y=400.0;
        Player.counter=0;
        Player.status=0;
        for(int i=0;i<PLAYER_MAX_SHOT1;i++)
                for(int j=0;j<PLAYER_MAX_SHOT2;j++)
                        PlayerShot[i][j].flag=0;
}

void SetColor(){
        color_white = GetColor(255,255,255);                   //白色ハンドルを取得
}

main関数から作った関数を呼び出します。


/* main.cpp */
/* 素材 ver1.00以上必要*/

#include "DxLib.h"
#include "GlobalVariable.h"


int WINAPI WinMain( HINSTANCE hInstance, 
                                   HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
        extern void img_sound_load();
        extern void initialization();
        extern void SetColor();
        extern void Background();
        extern void PlayerShotCalc();
        extern void PlayerShotDisp();
        extern void PlayerControl();
        extern void Background2();
        extern void FpsTimeFanction();

        int RefreshTime=0;

        ChangeWindowMode( TRUE ) ;
        if( DxLib_Init() == -1 ) return -1; 

        SetDrawScreen( DX_SCREEN_BACK ) ;                  //裏画面を使用する。

        img_sound_load();
        initialization();
        SetColor();

        while(ProcessMessage() == 0 && GetHitKeyStateAll(Key) == 0){
                RefreshTime = GetNowCount();              //今の時間を取得
                ClearDrawScreen();                                        //裏画面のデータを全て削除

                Background();

                PlayerShotCalc();
            
                PlayerShotDisp();

                PlayerControl();

                Background2();

                FpsTimeFanction();

                ScreenFlip() ;                                            //裏画面データを表画面へ反映

                counter++;

                if(Key[KEY_INPUT_ESCAPE]==1)    break;  //Escapeが押されたら終了
                while(GetNowCount() - RefreshTime < 17);//1周の処理が17ミリ秒になるまで待つ
        }
                
        DxLib_End() ;
        return 0 ;
}

実行画面


戻る                                  次へ
メニューへ戻る


トップページへ

DXライブラリ著作権表示
DX Library Copyright (C) 2001-2006 Takumi Yamada.