ホームへ戻る

 sp2章. キーが押されているフレーム数を取得する

/***** Singleton.h *****/

#pragma once

template <typename _T>
class Singleton {

protected:
	Singleton() {}
	virtual ~Singleton() {}	
	Singleton(const Singleton& r){}
  	Singleton& operator=(const Singleton& r){}

public:
	static _T* Instance() {
		static _T inst;
		return &inst;
	};

};


#pragma once は、多重include防止です。
templateを使っているので、型に依存せず使えます。型が_Tになっただけで、実質変わりありません。
コンストラクタは継承先から呼べる必要があるので、private→protectedに変更しています。

ではこれをKeyboardクラスに継承してみます。
今回は「押されカウンタ」「離されカウンタ」を用意してフレーム数をカウントします。
関数としてはそれを取得するものと、状態を更新するものを用意します。


#pragma once

#include "Singleton.h"

class Keyboard : public Singleton<Keyboard> {

	Keyboard();
	friend Singleton< Keyboard >;

public:
	bool Update();	//更新
	int GetPressingCount(int keyCode);//keyCodeのキーが押されているフレーム数を取得
	int GetReleasingCount(int keyCode);//keyCodeのキーが離されているフレーム数を取得

private:
	static const int KEY_NUM = 256;	//キー総数
	int mKeyPressingCount [KEY_NUM];//押されカウンタ
	int mKeyReleasingCount[KEY_NUM];//離されカウンタ

	bool IsAvailableCode(int keyCode);//keyCodeが有効なキー番号か問う
};

/***** Keyboard.cpp *****/

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

Keyboard::Keyboard(){
    memset(mKeyPressingCount,  0, sizeof(mKeyPressingCount) );
    memset(mKeyReleasingCount, 0, sizeof(mKeyReleasingCount));
}

//更新
bool Keyboard::Update(){
    char nowKeyStatus[KEY_NUM];
    GetHitKeyStateAll( nowKeyStatus );       //今のキーの入力状態を取得
    for(int i=0; i<KEY_NUM; i++){ 
        if(nowKeyStatus[i] != 0){            //i番のキーが押されていたら
            if(mKeyReleasingCount[i] > 0){//離されカウンタが0より大きければ
                mKeyReleasingCount[i] = 0;   //0に戻す
            }
            mKeyPressingCount[i]++;          //押されカウンタを増やす
        } else {                             //i番のキーが離されていたら
            if(mKeyPressingCount[i] > 0){ //押されカウンタが0より大きければ
                mKeyPressingCount[i] = 0;    //0に戻す
            }
            mKeyReleasingCount[i]++;         //離されカウンタを増やす
        }
    }
    return true;
}

//keyCodeのキーが押されているフレーム数を返す
int Keyboard::GetPressingCount(int keyCode){
    if(!Keyboard::IsAvailableCode(keyCode)){
        return -1;
    }
    return mKeyPressingCount[keyCode];
}

//keyCodeのキーが離されているフレーム数を返す
int Keyboard::GetReleasingCount(int keyCode){
    if(!Keyboard::IsAvailableCode(keyCode)){
        return -1;
    }
    return mKeyReleasingCount[keyCode];
}

//keyCodeが有効な値かチェックする
bool Keyboard::IsAvailableCode(int keyCode){
    if(!(0<=keyCode && keyCode<KEY_NUM)){
        return false;
    }
    return true;
}



Updateで更新し、Get○○で欲しい情報を取得しているだけです。
キーが押されていればPressingCountを上げ、
キーが押されていなければReleasingCountを上げています。

最後にmain.cppです。


/***** main.cpp *****/

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

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

	int white = GetColor(255,255,255);

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
		Keyboard::Instance()->Update();
		DrawFormatString(0, 0,white,"押している:%d", Keyboard::Instance()->GetPressingCount (KEY_INPUT_RETURN));
		DrawFormatString(0,20,white,"離している:%d", Keyboard::Instance()->GetReleasingCount(KEY_INPUT_RETURN));
	}

	DxLib_End();
	return 0;
}


実行結果


このようにキーボードをsingletonにより実装することで、複数インスタンスを生成してしまって不具合を生じさせてしまうことが無くなります。
システムに必ず1つしかないもので、状態が変化するもの、複数インスタンスを生成しては不具合のもとになってしまうようなものについてはシングルトンを使うとよいことを覚えておきましょう。

ただし、このシングルトンは言わばC言語のグローバル変数のようにも使えます。
C++の設計がまだ身についておらず、ついついグローバル変数を使いたくなってしまい、シングルトンに頼るような設計だと破たんしてしまうでしょう。
しっかり使いどころを見極めて使っていきましょう。

本節のサンプルプログラムのプロジェクトをダウンロード


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


- Remical Soft -