ホームへ戻る

 d.4章 ゲームの設計と分割コンパイル(2)

 前章の続きです。
本章では、main.cppと「プレイヤー」の他に「キーボード」というモジュールを作り
キーボードモジュールで計算したキーの入力状態をプレイヤーモジュールから参照して操作出来るようにしてみましょう。

今回は、「Keyboard」モジュールを追加しますので、前章の手順で「Keyboard.cpp」と「Keyboard.h」をソリューションに追加しておいて下さい。

さて、キーボードモジュールにはこちらの章の gUpdateKey関数 を使います。

状態を計算した後、どうやって他のモジュールからキーの入力状態を知ることができるのか。
それには関数の返り値を使います。

int Keyboard_Get( int KeyCode );

という関数を作り、キーの入力状態を確認したいキーコードを関数に渡します。
するとその関数は渡されたキーコードの入力状態を返り値で返すというわけです。

プログラムコードで見てみましょう。


/* Keyboard.cpp */


#include "DxLib.h"

static int m_Key[256];  // キーの入力状態格納用変数

// キーの入力状態更新
void Keyboard_Update(){
        char tmpKey[256];             // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey );  // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        m_Key[i]++;   // 加算
                } else {              // 押されていなければ
                        m_Key[i] = 0; // 0にする
                }
        }
}

// KeyCodeのキーの入力状態を取得する
int Keyboard_Get( int KeyCode ){
        return m_Key[ KeyCode ]; // KeyCodeの入力状態を返す
} 

 Keyboard_Update関数は、前述の2.9章のように、main.cppから毎フレーム呼び出されます。
状態が更新された後、Keyboard_Get関数 を通して他の関数からキーの入力状態が参照出来ます。
引数である KeyCode にはDXライブラリで定められている定義を渡します。キーコードについては2.9章をご覧下さい。
ヘッダファイルには関数のプロトタイプ宣言を書いておきます。


/* Keyboard.h */


#ifndef DEF_KEYBOARD_H //二重include防止

#define DEF_KEYBOARD_H

// キーの入力状態を更新する
void Keyboard_Update();

// 引数のキーコードのキーの入力状態を返す
int Keyboard_Get( int KeyCode );

#endif 

プレイヤーモジュールは、Player_Update関数 の中身のみ変更して、上下キー入力によってキャラを上下出来るようにします。

実装は簡単です。例えば下キーなら Keyboard_Get( KEY_INPUT_DOWN ) で入力状態が取得できるわけですから

void Player_Update(){
  if( Keyboard_Get( KEY_INPUT_UP ) > 0 ){
    m_y--;
  }
  if( Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
    m_y++;
  }
}

このように書くことで、Keyboardモジュールで計算したキーの入力状態を参照出来ます。

では Playerモジュール のプログラムを見てみましょう。


/* Player.cpp */


#include "DxLib.h"
#include "Keyboard.h"

static int m_Image;
static int m_y;

// 初期化をする
void Player_Initialize(){
        m_Image = LoadGraph("画像/キャラクタ01.png");
        m_y = 0;
}

// 動きを計算する
void Player_Update(){
        if( Keyboard_Get( KEY_INPUT_UP   ) > 0 ){
                m_y--;
        }
        if( Keyboard_Get( KEY_INPUT_DOWN ) > 0 ){
                m_y++;
        }
}

// 描画する
void Player_Draw(){
        DrawGraph( 0, m_y, m_Image, TRUE );
}

// 終了処理をする
void Player_Finalize(){
        DeleteGraph( m_Image );
}

/* Player.h */


変更なし


 このように関数を通して変数の値を参照することで、変数の値を書きかえる心配無く参照することが出来ます。
最期に main.cpp の変更部分を見てみましょう。


/* main.cpp */


#include "DxLib.h"
#include "Player.h"
#include "Keyboard.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK );

        Player_Initialize();// 初期化

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

                Keyboard_Update();

                Player_Update();  // 計算
                Player_Draw(); // 描画

        }

        Player_Finalize();  // 終了処理

        DxLib_End();
        return 0;
}

Keyboard_Update関数 を毎フレーム呼び出しているだけです。呼び出せるように、Keyboardモジュールのヘッダファイルをincludeしています。

実行結果




本章で紹介したプロジェクトファイルはこちらです。

プロジェクトファイルはこちら

これまでに紹介したように、モジュール単位でファイルを分割し、グローバル変数はファイル内のみで閉じるようにすることで、

安全にそして管理しやすい設計が出来るようになります。

しかしこれでは、対戦プレイなどでプレイヤーが2人になった時、困ります。

グローバル変数は一つなので、二つの状態を持つことが出来ません。

そこで、変数の実体は、main.cpp で持ち、純粋に処理のみをモジュールにやらせてはどうかという考えになります。

次の章で、多重化出来るモジュール設計についてお話します。

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


- Remical Soft -