19:スプライト描画クラスを作成する

 今回はDirect3Dのスプライト描画に関するクラスを作成します。

 Direct3Dのスプライト描画には、ID3DXSprite::Draw()を使い、描画する画像はIDirect3DTexture9で作成されたものを指定します。そこで、スプライトクラスを用意する前に、テクスチャを管理するためのクラスを作ることにしましょう。
 テクスチャを管理するだけであれば特別難しいことはありません。クラスの内部にIDirect3DTexture9を保持するためのオブジェクト(LPDIRECT3DTEXTURE9)を用意し、IDirect3DTexture9へテクスチャイメージを読み込むための関数を追加するだけです。Init()が呼び出されるたびにテクスチャを読み直すケースはあまりないと思うので、ここではコンストラクタからでもイメージを読み込めるようにしています。ファイルからテクスチャを作成するにはD3DXCreateTextureFromFile関数を用いります。ちなみにLPCTSTRは「
const
TCHAR*」と同じ定義です。

 なお、作成したテクスチャのサイズはIDirect3DTexture9::GetLevelDesc()で取得できるD3DSURFACE_DESC構造体のWidthとHeightに格納されています。
#pragma once

#include "GameObject.h"

class CTexture : public CGameObject
{
private:
    // テクスチャを格納するインタフェイス
    LPDIRECT3DTEXTURE9 texture;
    int texwidth, texheight;

public:
    CTexture();
    CTexture(LPCTSTR filename);
    ~CTexture();

    // 画像ファイルからテクスチャを作成する
    BOOL Load(LPCTSTR filename);

    // テクスチャサイズの取得
    void GetTextureSize(int *width, int *height);

    // テクスチャデータを直接取得する
    const LPDIRECT3DTEXTURE9 GetTexture(){ return texture; }
};
#include "Texture.h"

CTexture::CTexture()
{
    texture = NULL;
}

CTexture::CTexture(LPCTSTR filename)
{
    texture = NULL;
    Load(filename);
}

CTexture::~CTexture()
{
    RELEASE(texture);
}

void CTexture::GetTextureSize(int *width, int *height)
{
    *width = texwidth;
    *height = texheight;
}

BOOL CTexture::Load(LPCTSTR filename)
{
    RELEASE(texture);
    BOOL b = SUCCEEDED(D3DXCreateTextureFromFile
        (pD3Ddevice, filename, &texture));

    if(b == TRUE){
        D3DSURFACE_DESC desc;

        // 最上位のテクスチャ情報を取得
        texture->GetLevelDesc(0, &desc);

        texwidth = (int)desc.Width;
        texheight = (int)desc.Height;
    }

    return b;
}
 続いて、CTextureで確保されたテクスチャから2Dスプライトグラフィックを描画するためのCSpriteクラスを作成します。
class CSprite : public CGameObject
{
private:
    CTexture *texture;

public:
    CSprite();
    CSprite(CTexture *source);
    
    void SetTexture(CTexture *source);
    
    void Draw(float x, float y);
};
#include "Sprite.h"

CSprite::CSprite()
{
    texture = NULL;
}

CSprite::CSprite(CTexture *source)
{
    SetTexture(source);
}

void CSprite::SetTexture(CTexture *source)
{
    texture = source;
}

void CSprite::Draw(float x, float y)
{
    if(texture == NULL) return;
    
    pSprite->Begin(NULL);   // スプライト描画開始

    D3DXVECTOR3 vec;    // スプライトの描画位置を格納
    vec.x = x;      // x座標
    vec.y = y;      // y座標
    vec.z = 0.0f;   // z座標(奥行きは0にする)

    pSprite->Draw(
        texture->GetTexture(),  // 描画に用いるテクスチャイメージ
        NULL,                   // イメージの使用する範囲(NULLでテクスチャ全体)
        NULL,                   // テクスチャの中心位置(NULLで左上)
        &vec,                   // スプライトの描画位置
        0xFFFFFFFF              // テクスチャに合成する色(0xFFFFFFFFで元と同じ色のまま)
        );

    pSprite->End();         // スプライト描画終了
}
 画面にスプライトグラフィックを描画するサンプルプログラムを紹介します。必要に応じて、この文章の真下にある「soccerball.png」をそのままダウンロードして、プログラムコードのあるフォルダに保存してください。一般のブラウザであれば、右クリックメニューから画像の保存が行えます。
#pragma once

#include "Sprite.h"

class CSpriteTest : public CGameObject
{
private:
    float x, y, mx, my;
    CTexture tex;
    CSprite sprite;
public:
    CSpriteTest();
protected:
    virtual void Init();
    virtual void Exec();
};
#include "SpriteTest.h"

CSpriteTest::CSpriteTest()
{
    x = 320.0f - 16.0f;
    y = 240.0f - 16.0f;

    mx = my = 2.0f;
}

void CSpriteTest::Init()
{
    tex.Load(_T("soccerball.png"));
    sprite.SetTexture(&tex);
}

void CSpriteTest::Exec()
{
    x += mx;
    if(x < 0){
        x = 0;
        mx = -mx;
    }else if(x > 640 - 32){
        x = 640 - 32;
        mx = -mx;
    }

    y += my;
    if(y < 0){
        y = 0;
        my = -my;
    }else if(y > 480 - 32){
        y = 480 - 32;
        my = -my;
    }
    sprite.Draw(x, y);
}
 上記コードの入力が終わったら、CGameObject::Initialize()の次あたりにCGameObject::AppendObject()を使ってCSpriteTestクラスを追加しましょう。コンパイルして実行すると、サッカーボールが画面内でバウンドする様を見ることができます。