ゲームプログラミングTips(8):DirectX Graphics(3)(テクスチャ管理編)

 

2012年10月28日……前回の講座より、実に約1ヶ月ぶりである。
実際にこの講座を書いたのは実はやはり前回の講座と同日(5月14日)だが、一気に全部載せるのは色々とアレなのでこの調子で進める予定である(`・ω・´)

 

1.DirectX Graphicsとは?(Part3)

 基幹編で解説したから要らんでしょ(´Д`)

 

2.DirectX Graphicsのゲームプログラミングにおける活用事例(Part3)

 今回の内容は、基幹編と読み込み編を踏まえた内容になる。
 基幹編でDirectX Graphics等の初期化を行い、読み込み編でテクスチャの読み込みを行った。
 そして今回は、読み込んだテクスチャの管理ならびに描画等の操作について解説を行っていく。

 

3.具体例(ヘッダ解説)

 本項では、俺が作ったグラフィック管理クラスを掲載する。

/*************************************************
ファイル名:IDraw2D.h
作成者  :あびす
役割   :グラフィック管理クラス(2D)
*************************************************/
/**
*	@file	IDraw2D.h
*	@brief	グラフィック(2D)の管理を行うクラス関係です。
*/
#ifndef DX9A_GRAPHICS_IDRAW2D_H
#define DX9A_GRAPHICS_IDRAW2D_H

namespace nsDX9A{
namespace nsGraphics{
namespace nsIDraw2D{

//グラフィック管理クラス(2D)(インターフェース)
/**
*	@brief	グラフィック(2D)の管理を行うクラスのインターフェースです。
*/
class IDraw2D{
public:
/**
*	@brief	仮想デストラクタです。
*/
	virtual ~IDraw2D(){}												//仮想デストラクタ

/**
*	@brief	\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを取得します。
*	@return	\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを返します。
*/
	virtual IDraw2DReader* GetReader() = 0;								//グラフィックデータ読み込みクラス(2D)を取得(1)
/**
*	@brief	\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを取得します。
*	@return	\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを返します。
*/
	virtual IDraw2DReader* GetReader() const = 0;						//グラフィックデータ読み込みクラス(2D)を取得(2)
/**
*	@brief	\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを設定します。
*	@param	Reader	[in]\link	nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader	グラフィックデータ読み込みクラス\endlinkを指定します。
* 必ずReadメソッドを実行した\link nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader グラフィックデータ読み込みクラス\endlinkを指定してください。 * @return \link nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader グラフィックデータ読み込みクラス\endlinkの設定が成功した場合はtrue、失敗した場合はfalseを返します。 */ virtual bool SetReader(IDraw2DReader* Reader) = 0; //グラフィックデータ読み込みクラス(2D)を設定 /** * @brief グラフィックの通常転送を行います。 * @param x [in]テクスチャの描画先のX座標を指定します。 * @param y [in]テクスチャの描画先のY座標を指定します。 * @param a [in]テクスチャの透過度を指定します。 * @param SrcRect [in]転送元矩形をRECTで指定します。 * @param ScalingX [in]拡大倍率(X方向)を指定します。 * @param ScalingY [in]拡大倍率(Y方向)を指定します。 * @param Degree [in]回転する角度を指定します(単位:度) */ virtual void Blt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f) = 0; //通常転送 /** * @brief グラフィックの加色転送を行います。 * @param x [in]テクスチャの描画先のX座標を指定します。 * @param y [in]テクスチャの描画先のY座標を指定します。 * @param a [in]テクスチャの透過度を指定します。 * @param SrcRect [in]転送元矩形をRECTで指定します。 * @param ScalingX [in]拡大倍率(X方向)を指定します。 * @param ScalingY [in]拡大倍率(Y方向)を指定します。 * @param Degree [in]回転する角度を指定します(単位:度) */ virtual void AddBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f) = 0; //加色転送 /** * @brief グラフィックの減色転送を行います。 * @param x [in]テクスチャの描画先のX座標を指定します。 * @param y [in]テクスチャの描画先のY座標を指定します。 * @param a [in]テクスチャの透過度を指定します。 * @param SrcRect [in]転送元矩形をRECTで指定します。 * @param ScalingX [in]拡大倍率(X方向)を指定します。 * @param ScalingY [in]拡大倍率(Y方向)を指定します。 * @param Degree [in]回転する角度を指定します(単位:度) */ virtual void SubBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f) = 0; //減色転送 }; //グラフィック管理クラス(2D) /** * @brief グラフィック(2D)の管理を行うクラスの基底クラスです。 */ class CDraw2D : public IDraw2D{ public: /** * @brief コンストラクタです。 * @param Outer [in]関係する\link nsDX9A::nsGraphics::nsDX9AGraphic::DX9AGraphic DirectX Graphicsラッパークラス\endlinkを指定します。 * @param Reader [in]使用する\link nsDX9A::nsGraphics::nsIDraw2DReader::IDraw2DReader グラフィックデータ読み込みクラス\endlinkを指定します。 */ CDraw2D(DX9AGraphic* Outer, IDraw2DReader* Reader = NULL); //コンストラクタ(DirectX Graphicsラッパー、グラフィックデータ読み込みクラス(2D)を指定) /** * @brief デストラクタです。 */ ~CDraw2D(); //デストラクタ IDraw2DReader* GetReader(); //グラフィックデータ読み込みクラス(2D)を取得(1) IDraw2DReader* GetReader() const; //グラフィックデータ読み込みクラス(2D)を取得(2) bool SetReader(IDraw2DReader* Reader); //グラフィックデータ読み込みクラス(2D)を設定 void Blt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f); //通常転送 void AddBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f); //加色転送 void SubBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX = 1.0f, float ScalingY = 1.0f, float Degree = 0.0f); //減色転送 private: IDraw2DReader* m_Reader; //グラフィックデータ読み込みクラス DX9AGraphic* m_Outer; //DirectX Graphicsラッパーへのアドレス CDraw2D(); //デフォルトコンストラクタ(禁止) CDraw2D(const CDraw2D&); //コピーコンストラクタ(禁止) CDraw2D& operator =(const CDraw2D&); //代入演算子(禁止) }; } } } #endif

 ヘッダに対する解説では、本クラスの使用方法ならびに実装技法を説明する。

 使用方法は簡単である。

 1.インスタンスを生成する
 2.コンストラクタまたはSetReaderメソッドでグラフィックデータ読み込みクラスを設定する
 3.Bltメソッド等でテクスチャの描画を行うことができる

具体例

DX9AGraphic* g_DX9AG = new DX9AGraphic();										//DirectX Graphicsラッパークラス
CDraw2DReader* A = new CDraw2DReader(g_DX9AG, new CFileReader(), "1.bmp", 0);	//グラフィックデータ読み込みクラス
CDraw2D B(g_DX9AG, A);															//グラフィック管理クラス
RECT SrcRect = { 0, 0, 32, 24 };												//転送元矩形
A.Blt(100, 100, 255, &SrcRect, 1.5, 1.5, 40)									//描画
g_DX9AG->Present();																//画面を更新

 ……これだけである、特に変なところはない筈だ。

 では、以下にて具体的な説明を行っていく。
 ただし、なるべく説明は簡略に行う。

 ヘッダの説明

  何故2Dだけなの?3Dは?

   はいはいへぼプログラマで悪うござんしたさーせん('A`)
   真面目に答えると、今のところ3Dゲームを作る予定がない(かつ技術もない)からである。

  IDraw2Dクラスの仮想デストラクタがpublicなのは何故?

   グラフィックデータ読み込みクラスはprotectedだったが、本クラスはpublicにしている。
   これは、グラフィック管理クラスに対しては動的生成を強制する必要はないと判断したからである。
   グラフィックデータ読み込みクラスは、必ず他のクラスに管理され最終的には解体される運命である。
   それに対し、グラフィック管理クラスはスコープを抜けた際に自動で解体される場合があると考えられる。

 

4.具体例(ソース解説)

 次はソース解説である。

#include "stdafx.h"
#include "../index.h"
#include "IDraw2D.h"

namespace nsDX9A{
namespace nsGraphics{
namespace nsIDraw2D{

//コンストラクタ(DirectX Graphicsラッパー、グラフィックデータ読み込みクラス(2D)を指定)
CDraw2D::CDraw2D(DX9AGraphic* Outer, IDraw2DReader* Reader){
	m_Reader = NULL;
	m_Outer = Outer;
	SetReader(Reader);
}
//デストラクタ
CDraw2D::~CDraw2D(){
	SAFE_RELEASE(m_Reader);
}

//グラフィックデータ読み込みクラス(2D)を取得(1)
IDraw2DReader* CDraw2D::GetReader(){
	return(m_Reader);
}
//グラフィックデータ読み込みクラス(2D)を取得(2)
IDraw2DReader* CDraw2D::GetReader() const{
	return(m_Reader);
}
//グラフィックデータ読み込みクラス(2D)を設定
bool CDraw2D::SetReader(IDraw2DReader* Reader){
	if(Reader){
		if(Reader->IsRead()){
			SAFE_RELEASE(m_Reader);
			m_Reader = Reader;
			return(true);
		}
		else{
			DX9AErrOut("Failed : CDraw2D::SetReader() Draw2DReader Not IsRead\n");
		}
	}
	else{
		SAFE_RELEASE(m_Reader);
		return(true);
	}
	return(false);
}

//通常転送
void CDraw2D::Blt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX, float ScalingY, float Degree){
	m_Outer->GeneralBlt(m_Reader->GetTexture(), x, y, D3DCOLOR_ARGB(a, 255, 255, 255), SrcRect, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, ScalingX, ScalingY, Degree);
}
//加色転送
void CDraw2D::AddBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX, float ScalingY, float Degree){
	m_Outer->GeneralBlt(m_Reader->GetTexture(), x, y, D3DCOLOR_ARGB(a, 255, 255, 255), SrcRect, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ONE, ScalingX, ScalingY, Degree);
}
//減色転送
void CDraw2D::SubBlt(int x, int y, BYTE a, const RECT* SrcRect, float ScalingX, float ScalingY, float Degree){
	m_Outer->GeneralBlt(m_Reader->GetTexture(), x, y, D3DCOLOR_ARGB(a, 255, 255, 255), SrcRect, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_ONE, ScalingX, ScalingY, Degree);
}

}
}
}

 特に難しいことは行っていない、ポインタを渡したクラスのメソッドを必要に応じて呼び出しているだけである。

 

 

 

……以上で本項は終了である、お疲れ様でした(´Д`)
本項は前項に引き続き、いやそれ以上に易しい内容である。
次回はテキスト描画クラスを解説予定、若干難しいかも……!?

 

前へ                                        戻る                                     次へ