27:キーボード入力の改良
前回の結果をふまえて、テストプログラムを作成してみることにしましょう。用意するクラスはこの3つです。CInputTestStartクラスでは、入力クラスと戦闘機クラスの登録を行います。
- CInputTestStart : プログラム自体の初期化を行う
- CShip : プレイヤーの動かすキャラクター
- CShoot : プレイヤーの発射したミサイル
// データ初期化クラス
class CInputTestStart : public CGameObject
{
protected:
void Init();
};
void CInputTestStart::Init()
{
// テクスチャデータを作成する
CTexture *texdata = new CTexture(_T("ship.png"));
AppendObject(texdata, -1, "texture", true);
// hash_mapに登録
AppendItemBox("texture", texdata);
// 入力クラスを追加
AppendObject(new CInput(), -1, "input", true);
// 戦闘機クラスを作成(後述)
CShip *ship = new CShip();
AppendObject(ship, 1000, "ship", true);
// hash_mapに登録
AppendItemBox("ship", ship);
RemoveObject(this);
}
CShootクラスではミサイルキャラクターの制御を行います。ミサイルは1フレームごとに上へ5ピクセル移動し、画面外まで移動したら自分自身を破棄しています。
今回サンプルプログラムに使用したテクスチャはこれです。好みの画像に差し替えるのもよいでしょう。ちなみにこのCGも「六角大王Super 5.5」のサンプルデータを使って作成されています。

// 戦闘機・ミサイル共通クラス
class CCharactor : public CGameObject
{
protected:
CSprite sprite;
CTexture *tex;
public:
float x, y;
};
// 戦闘機クラス
class CShip : public CCharactor
{
private:
CInput *input;
protected:
void Init();
void Exec();
};
// ミサイルクラス
class CShoot : public CCharactor
{
protected:
void Init();
void Exec();
};
void CShip::Init()
{
input = (CInput*)FindObject("input");
sprite.SetTexture((CTexture*)FindItemBox("texture"));
sprite.SetSpriteSize(64, 64);
x = 320.0f;
y = 240.0f;
}
void CShip::Exec()
{
// VK_LEFTにあらず
if(input->IsKeyDown(DIK_LEFT)){
x -= 1.0f;
sprite.SetFrame(0);
}else if(input->IsKeyDown(DIK_RIGHT)){
x += 1.0f;
sprite.SetFrame(2);
}else{
sprite.SetFrame(1);
}
if(input->IsKeyDown(DIK_UP)) y -= 1.0f;
if(input->IsKeyDown(DIK_DOWN)) y += 1.0f;
if(input->IsKeyDown(DIK_SPACE)){
// ミサイル発射
AppendObject(new CShoot(), 900, true);
}
sprite.Draw(x, y);
}
void CShoot::Init()
{
sprite.SetTexture((CTexture*)FindItemBox("texture"));
sprite.SetSpriteSize(64, 64);
sprite.SetFrame(3);
// 戦闘機と同じ位置にミサイルを配置
CShip* its = (CShip*)FindItemBox("ship");
x = its->x;
y = its->y;
}
void CShoot::Exec()
{
y -= 5.0f;
// 画面外へ出たら削除する
if(y < -32.0f){
RemoveObject(this);
return;
}
sprite.Draw(x, y);
}
class CInput : public CGameObject
{
private:
LPDIRECTINPUT8 pInput;
LPDIRECTINPUTDEVICE8 pKeyDevice;
BYTE keydata[256], lastkeydata[256];
public:
/* 省略 */
BOOL IsKeyDown(int key);
BOOL IsKeyPressed(int key);
BOOL IsKeyReleased(int key);
/* 省略 */
};
void CInput::Exec()
{
if(pKeyDevice){
// 入力の受け付け開始
pKeyDevice->Acquire();
memcpy(lastkeydata, keydata, 256);
pKeyDevice->GetDeviceState(256, keydata);
}
}
BOOL CInput::IsKeyPressed(int key)
{
if(pKeyDevice == NULL) return FALSE;
// 現在押されていてかつ直前に押されていないときTRUEを返す
if((keydata[key] & 0x80) && !(lastkeydata[key] & 0x80)) return TRUE;
return FALSE;
}
BOOL CInput::IsKeyReleased(int key)
{
if(pKeyDevice == NULL) return FALSE;
// 現在押されておらずかつ直前には押されていたときTRUEを返す
if(!(keydata[key] & 0x80) && (lastkeydata[key] & 0x80)) return TRUE;
return FALSE;
}