pefs3d さん
>また、解放されないメモリは_CrtSetDbgFlagを使って調べてみるといいかもしれません。
なるほど、これは知りませんでした。早速使ってみようと思います。
ソースコードを添付します。長くなるので、一部抜粋して貼ります。
ウインドウ:グラフィックの初期化呼び出し
コード:
//==============================================================
// <CGame>コンストラクタ
CGame::CGame(const char* app_name, bool zbuffer)
: /*メンバ変数初期化処理(記述省略)*/
{
/*アイコン処理、アクセラレータキー等の処理(記述省略)*/
// ウィンドウの作成
long style=WS_CAPTION|WS_VISIBLE|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
RECT r={0, 0, WindowWidth, WindowHeight};
AdjustWindowRect(&r, style, false);
HWnd=CreateWindow(
app_name, app_name, WS_OVERLAPPEDWINDOW,
100, 100, r.right-r.left, r.bottom-r.top,
GetDesktopWindow(), NULL, wc.hInstance, NULL);
HWndCGameMap.insert(
THWndCGameMap::value_type(HWnd, this));
// グラフィックスの作成
Graphics=new CGraphics(HWnd);
if (!Graphics) {
string s=
"このプログラムにはDirectX 9.0c以上が必要です";
MessageBox(HWnd, s.c_str(), app_name, MB_OK);
exit( EXIT_FAILURE );
}
Graphics->Clear();
Graphics->Present();
if (FullScreen) ResetScreen();
}
グラフィッククラス:DirectXの初期化
コード:
//==============================================================
// コンストラクタ
CGraphics::CGraphics(HWND hwnd)
: /*メンバ変数の初期化*/
{
// ウィンドウスタイルの保存
WindowStyle=GetWindowLong(hwnd, GWL_STYLE);
// クライアント領域のサイズを取得
RECT r;
GetClientRect(hwnd, &r);
Width=r.right-r.left;
Height=r.bottom-r.top;
// Direct3Dインタフェースの作成
D3D=Direct3DCreate9(D3D_SDK_VERSION);
// Direct3Dデバイスの作成
ResetDevice();
}
//==============================================================
// デバイス
// デバイスのリセット
bool CGraphics::ResetDevice() {
// ウィンドウスタイルとサイズの設定:
if (FullScreen) {
SetWindowLong(HWnd, GWL_STYLE, WS_VISIBLE);
} else {
SetWindowLong(HWnd, GWL_STYLE, WindowStyle);
RECT r={0, 0, Width, Height};
AdjustWindowRect(&r, WindowStyle, GetMenu(HWnd)!=NULL);
SetWindowPos(HWnd, HWND_NOTOPMOST,
100, 100, r.right-r.left, r.bottom-r.top, SWP_SHOWWINDOW);
}
// デバイスのパラメータ設定
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.hDeviceWindow=HWnd;
d3dpp.BackBufferWidth=Width;
d3dpp.BackBufferHeight=Height;
d3dpp.Windowed=!FullScreen;
d3dpp.FullScreen_RefreshRateInHz=FullScreen?RefreshRate:0;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat=D3DFMT_A8R8G8B8;
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
d3dpp.EnableAutoDepthStencil=TRUE;
d3dpp.AutoDepthStencilFormat=DepthStencilFormat;
// デバイスの作成・リセット
if (!Device) {
if (FAILED(D3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, HWnd,
D3DCREATE_MIXED_VERTEXPROCESSING,
&d3dpp, &Device))
)
if (FAILED(D3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, HWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &Device))
)
if (FAILED(D3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, HWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &Device))
)
if (FAILED(D3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, HWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &Device))
) return false;
} else {
if (FAILED(Device->Reset(&d3dpp))) return false;
}
// 幅と高さの取得
LPDIRECT3DSURFACE9 back_buffer;
if (SUCCEEDED(Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer))) {
D3DSURFACE_DESC desc;
back_buffer->GetDesc(&desc);
Width=desc.Width;
Height=desc.Height;
back_buffer->Release();
} else {
Width=Height=0;
}
// リフレッシュレートの取得
D3DDISPLAYMODE mode;
if (SUCCEEDED(Device->GetDisplayMode(0, &mode))) {
RefreshRate=mode.RefreshRate;
} else {
RefreshRate=0;
}
IsGDISurface=true;
return true;
}
メッセージループ
コード:
//==============================================================
// <CGame>ゲームの実行
void CGame::Run() {
// ダミーのメッセージハンドラを,
// 正式なメッセージハンドラに置き換える
SetWindowLong(HWnd, GWL_WNDPROC, (long)::WndProc);
// メッセージループ
MSG msg;
ZeroMemory(&msg, sizeof(msg));
ResetTime();
while (msg.message!=WM_QUIT) {
// バックグラウンド処理
if (PauseInTheBackground && HWnd!=GetForegroundWindow()) {
GetMessage(&msg, NULL, 0U, 0U);
if (!TranslateAccelerator(HWnd, HAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ResetTime();
continue;
}
// フォアグラウンド処理
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
if (!TranslateAccelerator(HWnd, HAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
continue;
}
// 一時停止
if (Pause || MenuPause) continue;
// 時間調整
LARGE_INTEGER freq, count;
DWORD tick;
if (QueryPerformanceFrequency(&freq) &&
QueryPerformanceCounter(&count)) {
Elapsed+=FPS*(count.QuadPart-LastPerfCounter.QuadPart)/freq.QuadPart;
LastPerfCounter=count;
} else {
tick=GetTickCount();
Elapsed+=FPS*(tick-LastTickCount)/1000;
LastTickCount=tick;
}
// 移動と描画
if (Graphics->GetRefreshRate()==FPS || Elapsed>=1.0) {
if (DropFrames) {
for (; Elapsed>=1.0; Elapsed-=1.0) Move();
} else {
Elapsed=0;
Move();
}
CGame::DrawScene();
}
}
// メッセージハンドラをダミーに戻す
SetWindowLong(HWnd, GWL_WNDPROC, (long)::DummyWndProc);
// 終了処理
UnregisterClass(AppName.c_str(), GetModuleHandle(NULL));
}
//==============================================================
// <CGame>描画処理
void CGame::DrawScene() {
// デバイスが消失していたら再構築する
switch (Graphics->GetDevice()->TestCooperativeLevel()) {
case D3DERR_DEVICELOST:
Sleep(50);
return;
case D3DERR_DEVICENOTRESET:
OnLostDevice();
if (Graphics->ResetDevice()) OnResetDevice();
return;
}
// 描画開始
LPDIRECT3DDEVICE9 device=Graphics->GetDevice();
Graphics->BeginScene();
Draw();
// 描画完了::
Graphics->EndScene();
Graphics->Present();
}
3Dの描画
コード:
//==============================================================
// 描画
// メッシュの描画
void CMesh::Draw() {
// メッシュの描画
D3DMATERIAL9 mat;
for (DWORD i=0; i<NumMaterials; i++) {
mat=Materials[i];
D3DXCOLOR* col;
#define COLOR_OPERATION(TARGET) \
col=(D3DXCOLOR*)&mat.TARGET;\
D3DXColorModulate(col, col, &ColorMultiplier);\
D3DXColorAdd(col, col, &ColorAddition);
COLOR_OPERATION(Diffuse);
COLOR_OPERATION(Ambient);
COLOR_OPERATION(Specular);
COLOR_OPERATION(Emissive);
Device->SetMaterial(&mat);
Device->SetTexture(0, Textures[i]);
Mesh->DrawSubset(i);
}
}
// 変換行列を指定して描画
void CMesh::Draw(const D3DXMATRIX& mat) {
Device->SetTransform(D3DTS_WORLD, &mat);
CMesh::Draw();
}
以上です。実際には、luaをゲームに組み込んでおり、luabindを通してlua側から
毎フレームCMesh::Draw(mat)を呼ぶという実装になっています。
よろしくお願いします。