開放処理のテクニック

考え方

唐突だが、テクスチャ・オブジェクトやDirectX Graphicsのオブジェクトなどの開放処理は、オブジェクトの種類が違っても同じようなプログラムで行われている。

例)、ReleaseGameTexture関数

//-----------------------------------------------------------------------------
// 関数名 : ReleaseGameTexture()
// 機能概要: ゲーム画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseGameTexture(void)
{
    // テクスチャの開放
    if ( gl_TXBack != NULL ) {
        gl_TXBack->Release();
        gl_TXBack = NULL;
    }
    if ( gl_TXMyChara != NULL ) {
        gl_TXMyChara->Release();
        gl_TXMyChara = NULL;
    }
    if ( gl_TXEnemy != NULL ) {
        gl_TXEnemy->Release();
        gl_TXEnemy = NULL;
    }
}

《POINT》

ということは、この開放処理を関数化すれば、オブジェクトの開放処理が簡単に書けるようになることが分かる。しかしここでは、さらに便利な条件付マクロを使って、より簡単に記述する方法を紹介したい。

条件付マクロを使った開放処理

あるオブジェクトの開放を行うプログラムは次のとおりである。

例)DirectX8オブジェクトの開放

if ( gl_lpD3d != NULL ) {
    gl_lpD3d->Release();
    gl_lpD3d = NULL;
}

これは、条件付マクロを使うと次のように表現できる。

条件付マクロで記述

#define RELEASE(x) if(x!=NULL){x->Release();x=NULL;}

《POINT》

RELEASE(x)マクロを使ってプログラムを修正

作成したマクロ(RELEASE(x))を使って、先ほどのDirectX8オブジェクトの開放処理を記述すると、次のようになる。

RELEASE(gl_lpD3d);

《POINT》

プログラムが非常に簡単に記述できるようになったことが分かるだろうか。このように記述すると、オブジェクトの開放処理を行っている3つの関数(ReleaseD3D、ReleaseStartTexture、ReleaseGameTexture)は、それぞれ次のようになる。

《ReleaseD3D関数》

//-----------------------------------------------------------------------------
// 関数名 : ReleaseD3D()
// 機能概要: DirectX8オブジェクトの開放
//-----------------------------------------------------------------------------
void ReleaseD3D(void)
{
    // テクスチャの開放
    ReleaseStartTexture();
    ReleaseGameTexture();
    //デバイスオブジェクトの開放
    RELEASE(gl_lpD3ddev);
    //DirectX8オブジェクトの開放
    RELEASE(gl_lpD3d);
}

《ReleaseStartTexture関数》

//-----------------------------------------------------------------------------
// 関数名 : ReleaseStartTexture()
// 機能概要: スタート画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseStartTexture(void)
{
    // テクスチャの開放
    RELEASE(gl_TXBack); // 背景
}

《ReleaseGameTexture関数》

//-----------------------------------------------------------------------------
// 関数名 : ReleaseGameTexture()
// 機能概要: ゲーム画面用テクスチャ開放処理
//-----------------------------------------------------------------------------
void ReleaseGameTexture(void)
{
    // テクスチャの開放
    RELEASE(gl_TXBack); // 背景
    RELEASE(gl_TXMyChara); // 自キャラ
    RELEASE(gl_TXEnemy); // 敵キャラ
}

RELEASE(x)マクロの宣言場所

現在のプログラムの場合、オブジェクトの開放処理はNKC_DGraphics.cpp内のReleaseD3D関数でしか行っていない。そのため、NKC_DGraphics.cppのヘッダ部分(#includeの下あたり)に配置すればよい。しかし、今後は他のソースでも開放処理を行うことが考えられるため、共通ヘッダファイル「NKC_Common.h」に配置するのがベストと思われる。

さらに考える(参考)

if文は、条件が成り立つ(真)か成り立たない(偽)かによって処理を分ける命令である。では、真や偽は具体的にどの状態を表わしているのだろうか。

C言語では、真/偽は次のように判断される。

ということは、if(0)は「偽」であるし、if(1)もif(-1)もif(10)もすべて「真」であることがわかる。同じ理由で、while(0)は一度もループしないし、while(1)でもwhile(TRUE)でもwhile(10)でも、すべて無限ループになる。

先ほど、オブジェクトの開放を行うマクロを次のようにプログラムした。

#define RELEASE(x) if(x!=NULL){x->Release();x=NULL;}

実はNULLという定数は、windows.h内で次のように定義されている。

#define NULL 0

ということは、この「NULL以外かどうか」という条件は、「0以外かどうか」という条件と同じ意味になる。つまり、次のように簡略化して書くことができる。

#define RELEASE(x) if(x){x->Release();x=NULL;}

このようにプログラムすれば、xの値で真/偽を判断することになり、条件判断がシンプルになる(CPUにやさしい)。


BACK(共通ヘッダファイルの作成) NEXT(練習問題)