〜サンプルプログラム編〜

更新2006/10/16

基本編をマスターした方、もっと発展知識をつけたい方のために、サンプルプログラムを用意しました。

何かの参考にしていただけたら幸いです☆

もし判らない事があれば
掲示板
で気軽になんでも質問してくださいね☆

今日 昨日

〜サンプルプログラム〜
.
1. 関数ポインタ基本
2. サウンドノベル風文字列表示法1
3. サウンドノベル風文字列表示法2
4. サウンドノベル風文字列表示法3
3. メーターの表示方法
4. 移動速度を一定にする
5. 移動速度を一定にする2
6. 残像処理
7. セーブ・ロード
8. 画面の切り替わりを美しく演出する
9. 当たり判定基本
10. 現在何%ロードしたか表示する方法
11. MessageBox活用法
.
〜ミニテクニック〜
.
1. 画像・音楽ファイルを独自の拡張子に
2. 自作ソフトにオリジナルアイコンをつける
3. リフレッシュレートの考え方
4. 保存データを暗号化する
5.

基本編 と ゲーム入門編

 


1. 関数ポインタ基本


シューティングゲーム等は、敵の攻撃によって様々な関数で計算して玉を発射します。

その時間や状況によって使う関数が変わるのです。すなわち大量の関数名が出てきますね。


if(1回目の攻撃なら)
  ShotType1();
if(2回目の攻撃なら)
  ShotType2();
if(3回目の攻撃なら)
  ShotType3();
if(4回目の攻撃なら)
  ShotType4();


と書いてもいいですけど、なんだかちょっと賢くない書きかたのような気がしますね。

これをあらかじめ、「関数のポインタを配列でまとめて」おいて、配列要素番号を変更する事で

どの関数に処理を渡すか決定できれば随分スムーズにプログラムが書けるんじゃないでしょうか。

if(攻撃モード変更したら)
  i++;
ShotType[i]();

こんな風に書けば随分スマートですね。

では関数をポインタを使って配列にまとめてみるプログラムをかいて見ましょう。

サンプルプログラムでは

ShotType1();
ShotType2();
ShotType3();

という関数をShotFunctionで纏めています。

以後、ShotFunctionを使用する事で、任意のショットタイプ関数へ処理を渡す事が出来ます。


#include "DxLib.h"

int c=0,White,i=0;

void ShotType1( void ) ;        // 敵のショットパターン1関数
void ShotType2( void ) ;        // 敵のショットパターン2関数
void ShotType3( void ) ;        // 敵のショットパターン3関数

void (*ShotFunction[])( void ) =
{
        ShotType2,              //この順番で配列に格納される
        ShotType1,              //[0],[1],[2]の順番で使用すると
        ShotType3,              //2,1,3の順番で処理される。
} ;

void ShotType1( void ){
        DrawString(200,200,"タイプ1ショット発射中。",White);
}
void ShotType2( void ){
        DrawString(200,200,"タイプ2ショット発射中。",White);
}
void ShotType3( void ){
        DrawString(200,200,"タイプ3ショット発射中。",White);
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
        ChangeWindowMode( TRUE ) ;                   //ウィンドウモードに変更
        if( DxLib_Init() == -1 ) return -1;      // DXライブラリ初期化処理 エラーが起きたら終了 
         
        White = GetColor( 255 , 255 , 255 ) ;    //色の取得
        SetDrawScreen( DX_SCREEN_BACK ) ;        // 描画先を裏画面に設定
   
        while( 1 ){
                ClearDrawScreen();                   // 裏画面のデータを全て削除
                
                if     (c==0)
                        i=0;
                else if(c==100)
                        i=1;
                else if(c==200)
                        i=2;
                else if(c==300)
                        break;

                ShotFunction[i]();                                   // 各関数へ処理を渡す
                
                c++;
        ScreenFlip() ;                                       // 裏画面データを表画面へ反映
        }

        DxLib_End() ;                                            // DXライブラリ使用の終了処理
        return 0 ;                                               // ソフトの終了
}

実行結果






2. サウンドノベル風文字列表示法1

ノベルゲームやアドベンチャーゲーム、同人ゲームなどのセリフの表示は、目で追いやすいように、時間差で

表示されていますね。あれを作ってみましょう。まずは、簡単なプログラムから行きます。

あらかじめ、表示する文章を作っておき、実際に画面に表示するための文字列を格納する変数を別につくり、

時間差で、あらかじめ作ってある文字列から、現在文字列を表示する変数に順々にコピーしながら表示すると

よいでしょう。

今回は、入門編の33節で説明した、選択画面の作り方を使って、エンターを押したかどうか判定します。

--------判定の概念--------

OldEnterとNowEnterという2つの変数を用意し、

前回のエンター入力状態をOldEnterに、今のエンター入力状態をNowEnterに格納します。

押されていない時は変数に0が入り、押されている時は変数に1が入ります。

ですからOldEnterが0でNowEnterが1の時、今の瞬間エンターが押されたことがわかります。

--------------------------

時間の測定にはcounter変数を用いています。処理が1周するたびに、counterの値を増やします。

counterの値が5の倍数の時に、処理を進めることで、5周に1度処理をすることが出来ます。

今回はグローバル変数で宣言していますが、メイン関数を読みやすくするためで、グローバルにする必要は全然ありません。



#include "DxLib.h"

int i=0,ch_i=0,counter=0,White;
int NowEnter=0,OldEnter=0;
char Key[256]={0,},disp[80]="",ch[5][80]={
        "プログラムを習得するには、実際に自分で書いてみることが大事。",
        "参考書を読むことも重要だが、数学のように演習を通して、",
        "体に身につけるようにしよう。",
        "きっと、よりはっきりと、関数の使い方、",
        "プログラムの書き方がわかるだろう。"
};


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){

        ChangeWindowMode( TRUE ) ;               //ウィンドウモードに変更
        if( DxLib_Init() == -1 )                 //DXライブラリの初期化
                 return -1;
        SetDrawScreen( DX_SCREEN_BACK ) ;        // 描画先を裏画面に設定

        White=GetColor(255,255,255);             //文字色取得

        while(Key[KEY_INPUT_ESCAPE]==0 && ProcessMessage()==0){
                ClearDrawScreen();               // 裏画面のデータを全て削除
                GetHitKeyStateAll(Key);          // キーの入力状態をKey配列に格納

                NowEnter=Key[KEY_INPUT_RETURN];  // 今のエンターの入力状態を格納

                if(OldEnter==0 && NowEnter==1){  // 前回押されてなくて、今回押されていたら
                        i=0;                     // iを初期値に戻し
                        ch_i++;                  // 表示する配列を1つずらす
                        if(ch_i==5)              // これ以上表示する配列がなくなったらbreak;
                                break;
                }
                if(i<=80-2 && ch[ch_i][i]!='\0' && counter%5==0){
                                                 // 配列の終端-2以下で、今回コピーするiまでの配列要素のi番目が
                                                 // \0じゃなく、カウンターが5の倍数なら
                        i+=2;                    // 全角文字なので配列要素2つずつカウントアップ
                        strncpy(disp,ch[ch_i],i);// iバイトまでの配列要素をdisp配列にコピー
                        disp[i]='\0';            // 終端記号を代入
                }

                DrawFormatString(10,420,White,"%s",disp);//disp配列の文字データを表示

                OldEnter=NowEnter;               // 最後に今のエンター入力状態を古い入力状態へ
                counter++;                          
                ScreenFlip() ;                   // 裏画面データを表画面へ反映
        }
        DxLib_End() ;                            // DXライブラリ使用の終了処理
        return 0 ;                               // ソフトの終了
}

実行画面




以下鋭意製作中



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