オブジェクト指向を意識してC++でシューティングゲームを作る(2)

前の投稿でゲームループとシーン切り替えクラスを作ったので、今回はいよいよ自機を描画する所までやりたいと思います。

前回はこちらオブジェクト指向を意識してC++でシューティングゲームを作る(1)

やること

  1. Playerクラスを作る
  2. 自機の描画
  3. 自機を動かす

Playerクラスを作る


最初にPlayerクラスを作るためにcppとhファイルを作成します
f:id:haina817:20160924215441p:plain

playerクラスでdxライブラリを使用するので、先にcppファイル内でDxlibとplayerをincludeしてください。
(そういえばDXライブラリの環境構築に全く触れていなかったので、もしまだの方はこちらから環境構築を行ってください。)

f:id:haina817:20160924215926p:plain

次にPlayer.cppにプレイヤークラスを作り、ここでプレイヤーの描画には欠かせない位置情報とプレイヤーの画像を格納する変数をそれぞれ宣言します。
Player.h

#pragma once

class CPlayer
{
	//DXライブラリで定義されている構造体(中身はfloat型のx,y,z)
	VECTOR pos;
	//画像データ格納
	int graphic;
public:
//コンストラクタ(インスタンス生成時に最初に呼ばれる関数)
	CPlayer();
//デストラクタ(インスタンス削除時に呼ばれる関数)
	~CPlayer();
};

cppファイルではCPlayerのコンストラクタを使ってgraphicとposの初期化を行います。

Player.cpp

CPlayer::CPlayer()
{
	//画像データ格納
	graphic = LoadGraph("画像のパス");
	//位置を初期化(座標はウインドウの中心)
	pos = VGet(320,240,0);
}
CPlayer::~CPlayer()
{
}

使用した画像はこちら(手抜きではない)
f:id:haina817:20160924230400p:plain
これで自機の画像データが読み込まれ、描画する準備が整いました。
では実際に描画してみましょう。

自機の描画

CPlayerクラスにRender関数を作ってそこで描画します。

CPlayer.h

#pragma once

class CPlayer
{
	//DXライブラリで定義されている構造体(中身はfloat型のx,y,z)
	VECTOR pos;
	//画像データ格納
	int graphic;
public:
//コンストラクタ(インスタンス生成時に最初に呼ばれる関数)
	CPlayer();
//デストラクタ(インスタンス削除時に呼ばれる関数)
	~CPlayer();
//更新
	void Render();
};

Player.cpp

void CPlayer::Render()
{
	//読みこんだグラフィックを回転描画
	DrawRotaGraph(pos.x, pos.y, 1.0, 0, graphic, TRUE);
}

DrawRotaGraph関数説明
CPlayerのインスタンスはCGameクラスで動的確保します。
どのようにするかと言うと、まずCGameクラスの上にCPlayerクラスのプロトタイプ宣言をしてCPlayerクラスのポインタ変数を作り、
CGameクラス内のコンストラクタとデストラクタを、cppファイルに移動します。

CGame.h

#pragma once
class CPlayer;
class CGame:public CScene
{
	//自機のポインタ変数
	CPlayer *player;
public:
	CGame(CManager *pManager);
	~CGame();
	void Update();
	void Render();
};

Game.cpp

CGame::CGame(CManager *pManager) : CScene(pManager)
{
}
CGame::~CGame()
{
}

そしてPlayer.hをincludeした後、CGameのコンストラクタの中でCPlayerを動的確保(new)し、デストラクタの中でそれを解放して、最後にRender関数内でplayerのRenderを呼べば自機の描画が完成です。

Game.cpp

#include"Player.h"
CGame::CGame(CManager *pManager) : CScene(pManager)
{
	//プレイヤーを動的確保
	player = new CPlayer();
}
CGame::~CGame()
{
	//動的確保したものを解放する
	delete player;
}
void CGame::Render()
{
	//DrawFormatString(0, 0, GetColor(255, 255, 255), "ゲーム");
	player->Render();
}

起動してみるとこんな感じ

f:id:haina817:20160925002433p:plain

自機を動かす
最後に自機を動かす処理をして今回は終わります。
やることは、オブジェクト指向を意識してC++でシューティングゲームを作る(1)でCManagerクラスの中で作ったキー取得関数「GetKey」をCPlayer内でも使えるようにして、CPlayerの更新関数内で自機を動かす処理をします。
まず最初に、CManagerクラスのポインタを格納する変数をCPlayerクラスに作成してそれをコンストラクタの引数で取得できるようにします。
あとついでに更新関数も作っておきましょう。

Player.h

#pragma once
class CManager;
class CPlayer
{
	CManager *manager;
	//DXライブラリで定義されている構造体(中身はfloat型のx,y,z)
	VECTOR pos;
	//画像データ格納
	int graphic;
public:
	//コンストラクタ(インスタンス生成時に最初に呼ばれる関数)
	CPlayer(CManager *);
	//デストラクタ(インスタンス削除時に呼ばれる関数)
	~CPlayer();
	//描画
	void Render();
	//更新
	void Update();
};

Player.cpp

CPlayer::CPlayer(CManager *pManager)
{
	//CManagerのアドレス格納
	manager = pManager;
	//画像データ格納
	graphic = LoadGraph("graphic/Player/player.png");
	//位置を初期化
	pos = VGet(320,240,0);
}


では、いよいよキー入力で自機を動かす部分を作ります。
まずCManagerクラスを使用するので、Managerをincludeするのと、自機の移動量を決めて上に定義(define)しておきましょう。
次に上下左右キーが押されているか判定する条件文を作成します。
そしてベクトル取得する変数を定義して、4方向の移動量を取得してから現在の座標に加算します。

Player.cpp

#include"DxLib.h"
#include"Player.h"
#include"Manager.h"
#define PLAYER_SPEED 10.0f


void CPlayer::Update()
{
	//移動する向き
	VECTOR vPos = VGet(0,0,0);
	//移動していないときは座標を動かす必要がないのでこれで移動しているか確認する
	bool moveFlag = false;
	if (manager->GetKey()[KEY_INPUT_LEFT] > 0)
	{
		vPos.x -= 1.0f;
		moveFlag = true;
	}
	if (manager->GetKey()[KEY_INPUT_RIGHT] > 0)
	{
		vPos.x += 1.0f;
		moveFlag = true;
	}
	if (manager->GetKey()[KEY_INPUT_UP] > 0)
	{
		vPos.y -= 1.0f;
		moveFlag = true;
	}
	if (manager->GetKey()[KEY_INPUT_DOWN] > 0)
	{
		vPos.y += 1.0f;
		moveFlag = true;
	}
	if (moveFlag)
	{
		vPos = VNorm(vPos);
		vPos = VScale(vPos, PLAYER_SPEED);
		//現在の座標に移動量を加算する
		pos = VAdd(pos, vPos);
	}
	
}

これで後はこのUpdate関数をCGameのUpdateで呼び出せば完成です。

CGame.cpp

CGame::CGame(CManager *pManager) : CScene(pManager)
{
	//プレイヤーを動的確保
	player = new CPlayer(pManager);
}
void CGame::Update()
{
	player->Update();
}

では実行して移動できるか試してみましょう。
f:id:haina817:20160925002647p:plain
f:id:haina817:20160925002753p:plain

しっかり移動できました。


一応参考になるかと思い私自身がプログラムを書く流れをそのまま書いているのですが少し長くなってしまいますね...
本当は弾の発射まで行きたかったのですがそれはオブジェクト指向を意識してC++でシューティングゲームを作る(3)で説明することにします。