Информатика и образование
[Главная]
[Новости]
[Статьи]
[Проекты]
[Автор]
         
[Форум]
на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы
 
 

Здравствуйте! Вы попали на информационно-образовательный сайт посвященный разработке компьютерных игр. Здесь Вы найдете информацию о том, как создать графику, музыку, звук, написать программный код и сюжет и создать полноценную компьютерную игру. Подробнее о целях и задачах сайта в разделе Главная.

 

 
       
  [Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi]    
       
  [Разработка компьютерной игры] [Пример игры Donuts3D]    
       
  Рисуем волка из мультфильма [Delphi 2006 DirectX 9]    
       
 

Программирование игр на С++ для платформы DirectX 9c

Написание приложения DirectX9c + MFC в среде MSVS 2005

   
       
 

Данный урок демонстрирует технику программирования игр на C++ для DirectX 9с

Вам нужно иметь установленную среду Microsoft Visual Studio 2005 или 2008,

и DirectX SDK August 2008 или самой последней версии.

   
       
  [назад] [далее] [к содержанию]    
       
 

Причины побудившие меня к написанию данной серии статей достаточно просты - поделиться своим опытом в области создания игр на VC++ в среде MSVS 2005 для DirectX 9c

В данном уроке я попытаюсь рассказать о том, как подойти к созданию приложения сочетающего использование интерфейсов DirectX 9c и классов из библиотеки MFC

   
       
 

Начнём с того, что в DirectX SDK August 2008 не представлен ни один из примеров приложения, рассчитанного на совместное использование DirectX и классов MFC.

По видимому предполагается, что тема достаточно тривиальна для тех, кто работает с DirectX

Однако мне это представляется не совсем так.

Зачем Вам в приложении DirectX могут понадобится классы MFC?

Во-первых, MFC содержит целый ряд просто необходимых классов, а значит и решения тех стандартных задач, которые трудно решить на голом WinAPI.

В частности если Ваше приложение DirectX подразумевает работу в стандартном окне и является какой-либо утилитой используемой в разработке Вашей игры (например редактор карт), то без использования MFC Вам просто не обойтись.

Во-вторых, даже если Ваша игра будет большую часть времени работать в полноэкранном режиме, классы MFC Вам всё равно понадобятся для решение многих типовых задач.

Именно базируясь на этих двух причинах следует рассмотреть как подойти к совместному использованию DirectX и MFC в своём приложении.

   
       
 

Для простоты мы разберем некий базис - шаблон приложения, рассчитанного на DirectX9c + MFC

Последовательность создания приложения D3D9 (DirectX 9c) + MFC
в MSVS 2005

File > New > Project > MFC > MFC Application

опции
Dialog based
язык - Английский (США) - потом поменяем на русский (при создании диалогов и изменении
их свойств)
MFC standard
Use MFC in a static library
Use Unicode libraries
остальные опции на своё усмотрение или по-умолчанию

После генерации приложения нужно настроить проект для использования заголовочных
файлов и библиотек DirectX 9c как это показано в уроке Первый старт

Добавить исходный код из DXUT - это набор вспомогательного кода, который Вы найдете внутри [DirectXSDK]\Samples\C++\DXUT\

Код данной папки ориентирован на использование в WinAPI-приложении без использования MFC

Для использования в MFC-проекте код потребует небольших модификаций во всех файлах *.cpp из папок Core и Optional нужно добавить строку #include "stdafx.h" перед строкой #include "DXUT.h" в самом начале каждого файла. Для простоты создайте копию содержимого папки DXUT, назвав например DXUT_mfc и смело вносите эти изменения. После этих изменений в качестве заголовочного файла управляющего прекомпилированными модулями будет задан stdafx.h что и имеет место в созданном Вами MFC-приложении, в противном случае Вы получите ошибки во время компиляции.

Код папки DXUT_mfc нужно добавить к коду проекта - в окне Solution Explorer щелкните правой кнопкой по названию проекта, выберите Add > New Filter, который назовите DXUT_mfc.


   
     
       
 

Затем оставив созданный фильтр выбранным повторите операцию, но теперь уже выберите Existing Item

   
       
     
       
 

и добавьте все файлы из папки DXUT_mfc кроме DXUTguiIME.* и ImeUi.*

Данные файлы относятся к использованию национальных языков и Вам пока не потребуются.

   
       
 

Добавить шаблонный код для начальной инициализации типового D3D9 - приложения

Рассмотрим что нужно добавить на примере проекта D3DAppTemplate

В модуле D3DAppTemplate.h нужно внести следующие изменения и дополнения -

#include <d3d9.h>
#include <d3dx9.h>

#include "D3DAppTemplateDlg.h"

внутри описания класса class CD3DAppTemplateApp

~CD3DAppTemplateApp();

в конце описания класса

public:
CD3DAppTemplateDlg* pMainWindow;

В модуле D3DAppTemplate.cpp

#include "DXUT.h"
#include "DXUTcamera.h"
#include "DXUTsettingsdlg.h"
#include "SDKmisc.h"
#include "SDKsound.h"

 

 

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------

ID3DXFont* g_pFont = NULL; // Font for drawing text
ID3DXSprite* g_pTextSprite = NULL; // Sprite for batching draw text calls
CFirstPersonCamera g_Camera; // A model viewing camera
CSoundManager g_DSound; // DirectSound class

bool g_bShowHelp = true; // If true, it renders the UI control text
bool g_bPlaySounds = true; // whether to play sounds
double g_fLastAnimTime = 0.0; // Time for the animations


//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed,
void* pUserContext );
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext );
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext );
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext );
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );
void CALLBACK OnLostDevice( void* pUserContext );
void CALLBACK OnDestroyDevice( void* pUserContext );
void RenderText();

void InitApp();

void InitialD3DAppSettings();

 

CD3DAppTemplateApp::CD3DAppTemplateApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
pMainWindow = NULL;
}

 

 

BOOL CD3DAppTemplateApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();

AfxEnableControlContainer();

// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));

 

pMainWindow = new CD3DAppTemplateDlg();
pMainWindow->Create(CD3DAppTemplateDlg::IDD);
pMainWindow->ShowWindow(SW_SHOW);
pMainWindow->ShowWindow(SW_HIDE);

m_pMainWnd = pMainWindow;

InitialD3DAppSettings();

//g_d3dApp.Cleanup3DEnvironment();

delete pMainWindow;

pMainWindow = NULL;

// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}

 

void InitialD3DAppSettings()
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

// Set the callback functions. These functions allow DXUT to notify
// the application about device changes, user input, and windows messages. The
// callbacks are optional so you need only set callbacks for events you're interested
// in. However, if you don't handle the device reset/lost callbacks then the sample
// framework won't be able to reset your device since the application must first
// release all device resources before resetting. Likewise, if you don't handle the
// device created/destroyed callbacks then DXUT won't be able to
// recreate your device resources.
DXUTSetCallbackD3D9DeviceAcceptable( IsDeviceAcceptable );
DXUTSetCallbackD3D9DeviceCreated( OnCreateDevice );
DXUTSetCallbackD3D9DeviceReset( OnResetDevice );
DXUTSetCallbackD3D9FrameRender( OnFrameRender );
DXUTSetCallbackD3D9DeviceLost( OnLostDevice );
DXUTSetCallbackD3D9DeviceDestroyed( OnDestroyDevice );

DXUTSetCallbackMsgProc( MsgProc );

DXUTSetCallbackKeyboard( KeyboardProc );
DXUTSetCallbackFrameMove( OnFrameMove );
DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );

// Show the cursor and clip it when in full screen
DXUTSetCursorSettings( true, true );

InitApp();

// Initialize DXUT and create the desired Win32 window and Direct3D
// device for the application. Calling each of these functions is optional, but they
// allow you to set several options which control the behavior of the framework.
DXUTInit( true, true ); // Parse the command line and show msgboxes
DXUTSetHotkeyHandling( true, true, true ); // handle the defaul hotkeys

/*DXUTCreateWindow( L"D3D9 App Template", 0, 0, LoadMenu(0,
MAKEINTRESOURCE(IDR_MAINMENU)) );*/
DXUTCreateWindow( L"D3D9 App Template", 0, 0, 0);

SetWindowLong( DXUTGetHWND(), GWL_STYLE,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);

// We need to set up DirectSound after we have a window.
g_DSound.Initialize( DXUTGetHWND(), DSSCL_PRIORITY );


DXUTCreateDevice( true, 631, 380 );

//InitD3DApp();

// Pass control to DXUT for handling the message pump and
// dispatching render calls. DXUT will call your FrameMove
// and FrameRender callback when there is idle time between handling window messages.
DXUTMainLoop();

// Perform any application-level cleanup here. Direct3D device resources are released within the
// appropriate callback functions and therefore don't require any cleanup code here.

//return DXUTGetExitCode();
}

//--------------------------------------------------------------------------------------
// Initialize the app
//--------------------------------------------------------------------------------------
void InitApp()
{
// Add mixed vp to the available vp choices in device settings dialog.
DXUTGetD3D9Enumeration()->SetPossibleVertexProcessingList( true, false, false, true );

// Setup the camera with view matrix
D3DXVECTOR3 vEye( .5f, .55f, -.2f );
D3DXVECTOR3 vAt( .5f, .125f, .5f );
g_Camera.SetViewParams( &vEye, &vAt );
g_Camera.SetScalers( 0.01f, 1.0f ); // Camera movement parameters

}


//--------------------------------------------------------------------------------------
// Called during device initialization, this code checks the device for some
// minimum set of capabilities, and rejects those that don't pass by returning false.
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
// Skip backbuffer formats that don't support alpha blending
IDirect3D9* pD3D = DXUTGetD3D9Object();
if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
return false;

// Need to support ps 2.0
if( pCaps->PixelShaderVersion < D3DPS_VERSION( 2, 0 ) )
return false;

// Need to support A8R8G8B8 textures
if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
AdapterFormat, 0,
D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8 ) ) )
return false;

return true;
}

//--------------------------------------------------------------------------------------
// This callback function is called immediately before a device is created to allow the
// application to modify the device settings. The supplied pDeviceSettings parameter
// contains the settings that the framework has selected for the new device, and the
// application can make any desired changes directly to this structure. Note however that
// DXUT will not correct invalid device settings so care must be taken
// to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
assert( DXUT_D3D9_DEVICE == pDeviceSettings->ver );

HRESULT hr;
IDirect3D9* pD3D = DXUTGetD3D9Object();
D3DCAPS9 caps;

V( pD3D->GetDeviceCaps( pDeviceSettings->d3d9.AdapterOrdinal,
pDeviceSettings->d3d9.DeviceType,
&caps ) );

// If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW
// then switch to SWVP.
if( ( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ||
caps.VertexShaderVersion < D3DVS_VERSION( 1, 1 ) )
{
pDeviceSettings->d3d9.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// If the hardware cannot do vertex blending, use software vertex processing.
if( caps.MaxVertexBlendMatrices < 2 )
pDeviceSettings->d3d9.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

// If using hardware vertex processing, change to mixed vertex processing
// so there is a fallback.
if( pDeviceSettings->d3d9.BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING )
pDeviceSettings->d3d9.BehaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;

// Debugging vertex shaders requires either REF or software vertex processing
// and debugging pixel shaders requires REF.
#ifdef DEBUG_VS
if( pDeviceSettings->d3d9.DeviceType != D3DDEVTYPE_REF )
{
pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
#endif
#ifdef DEBUG_PS
pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_REF;
#endif
// For the first device created if its a REF device, optionally display a warning dialog box
static bool s_bFirstTime = true;
if( s_bFirstTime )
{
s_bFirstTime = false;
if( pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF )
DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
}

return true;
}


//--------------------------------------------------------------------------------------
// This callback function will be called immediately after the Direct3D device has been
// created, which will happen during application initialization and windowed/full screen
// toggles. This is the best location to create D3DPOOL_MANAGED resources since these
// resources need to be reloaded whenever the device is destroyed. Resources created
// here should be released in the OnDestroyDevice callback.
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
{
HRESULT hr;



// Initialize the font

V_RETURN( D3DXCreateFont( pd3dDevice, 10, 0, 0, 1, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L"MS Sans Serif ", &g_pFont ) );



// Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the
// shader debugger. Debugging vertex shaders requires either REF or software vertex
// processing, and debugging pixel shaders requires REF. The
// D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the
// shader debugger. It enables source level debugging, prevents instruction
// reordering, prevents dead code elimination, and forces the compiler to compile
// against the next higher available software target, which ensures that the
// unoptimized shaders do not exceed the shader model limitations. Setting these
// flags will cause slower rendering since the shaders will be unoptimized and
// forced into software. See the DirectX documentation for more information about
// using the shader debugger.
DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;

#if defined( DEBUG ) || defined( _DEBUG )
// Set the D3DXSHADER_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DXSHADER_DEBUG;
#endif

#ifdef DEBUG_VS
dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif

return S_OK;
}


//--------------------------------------------------------------------------------------
// This callback function will be called immediately after the Direct3D device has been
// reset, which will happen after a lost device scenario. This is the best location to
// create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever
// the device is lost. Resources created here should be released in the OnLostDevice
// callback.
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
HRESULT hr;


// get device caps
D3DCAPS9 caps;
pd3dDevice->GetDeviceCaps( &caps );


if( g_pFont )
V_RETURN( g_pFont->OnResetDevice() );


// Create a sprite to help batch calls when drawing many lines of text
V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );

// Setup the camera's projection parameters
float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
g_Camera.SetProjParams( D3DX_PI / 3, fAspectRatio, 0.001f, 100.0f );

// set lighting
pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_ARGB( 255, 255, 255, 255 ) );
pd3dDevice->LightEnable( 0, TRUE );
pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );


// reset the timer
g_fLastAnimTime = DXUTGetGlobalTimer()->GetTime();

return S_OK;
}

//--------------------------------------------------------------------------------------
// This callback function will be called once at the beginning of every frame. This is the
// best location for your application to handle updates to the scene, but is not
// intended to contain actual rendering calls, which should instead be placed in the
// OnFrameRender callback.
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{

g_fLastAnimTime = fTime;

// Update the camera's position based on user input
g_Camera.FrameMove( fElapsedTime );


}


//--------------------------------------------------------------------------------------
// This callback function will be called at the end of every frame to perform all the
// rendering calls for the scene, and it will also be called if the window needs to be
// repainted. After this function has returned, DXUT will call
// IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{

pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
0xFFA1E1FF, 1.0f, 0L );

if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{

//
// Output text information
//
RenderText();

pd3dDevice->EndScene();
}
}


//--------------------------------------------------------------------------------------
// Render the help and statistics text. This function uses the ID3DXFont interface for
// efficient text rendering.
//--------------------------------------------------------------------------------------
void RenderText()
{
// The helper object simply helps keep track of text position, and color
// and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
// If NULL is passed in as the sprite object, then it will work however the
// pFont->DrawText() will not be batched together. Batching calls will improves performance.
CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 10 );
const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetD3D9BackBufferSurfaceDesc();

// Output statistics
txtHelper.Begin();
txtHelper.SetInsertionPos( 5, 5 );
txtHelper.SetForegroundColor( 0xFF0000FF );


txtHelper.DrawTextLine( DXUTGetFrameStats( true ) );

txtHelper.End();
}


//--------------------------------------------------------------------------------------
// As a convenience, DXUT inspects the incoming windows messages for
// keystroke messages and decodes the message parameters to pass relevant keyboard
// messages to the application. The framework does not remove the underlying keystroke
// messages, which are still passed to the application's MsgProc callback.
//--------------------------------------------------------------------------------------
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
if( bKeyDown )
{
switch( nChar )
{
case VK_F1:
g_bShowHelp = !g_bShowHelp; break;
}
}
}


//--------------------------------------------------------------------------------------
// Before handling window messages, DXUT passes incoming windows
// messages to the application through this callback function. If the application sets
// *pbNoFurtherProcessing to TRUE, then DXUT will not process this message.
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext )
{


g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );

return 0;
}


//--------------------------------------------------------------------------------------
// This callback function will be called immediately after the Direct3D device has
// been destroyed, which generally happens as a result of application termination or
// windowed/full screen toggles. Resources created in the OnCreateDevice callback
// should be released here, which generally includes all D3DPOOL_MANAGED resources.
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{

SAFE_RELEASE( g_pFont );

//g_d3dApp.Cleanup3DEnvironment(); //методы освобождения ресурсов нужно вызывать именно

//здесь. В данном примере g_d3dApp - объект игрового приложения не используется, поэтому он здесь закомментирован. В приложении с игрой освобождение ресурсов происходит именно так.
}

//--------------------------------------------------------------------------------------
// This callback function will be called immediately after the Direct3D device has
// entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
// in the OnResetDevice callback should be released here, which generally includes all
// D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for
// information about lost devices.
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{

if( g_pFont )
g_pFont->OnLostDevice();

SAFE_RELEASE( g_pTextSprite );




}

   
       
  Этот же код вы найдете внутри модулей D3DAppTemplate.h и D3DAppTemplate.cpp в проекте D3DAppTemplate -    
       
  Исходный код приложения D3DAppTemplate - 270 Кб, архив WinRaR 3.3 Исходный код приложения D3DAppTemplate - 269 Кб, архив WinRaR 3.3    
       
  Особенностью работы данного приложения является то, что в качестве первоначального (главного) окна используется стандартное окно диалога. Это окно создается как немодальное (modeless), затем оно отображается и тут же скрывается, уступая очередь созданному окну DirectX-приложения    
       
 

Схема функционирования выглядит следующим образом -

   
       
     
       
 

В начале создается объект класса CD3DAppTemplateApp путём вызова его конструктора

CD3DAppTemplateApз();

Затем вызывается метод InitInstance() внутри которого и осуществляется вся ицициализация, касающаяся mfc и directx.

Вместо созданного модального диалога, содержащего кнопки OK и Cancel создается немодальное окно, которое отображается и тут же скрывается, а далее вызывается функция InitialD3DAppSettings() которая отвечает за всё дальнейшее связанное с directx.

Для настройки directx вызывается функция InitialD3DAppSettings(); Внутри неё происходит настройка directx, создание окна directx-приложения и запуск цикла очереди сообщений вызовом функции DXUTMainLoop(); Как это реализовано в деталях - смотри выше или в исходном коде проекта D3DAppTemplate

Далее все необходимые сообщения системы можно обрабатывать внутри функции MsgProc, а собственно игровую логику и отрисовку игровой сцены производить внутри функций OnFrameMove и OnFrameRender

При выходе из приложения вызовом exit() или PostQuitMessage DXUTMainLoop завершается, управление возвращается внутрь метода InitInstance, метод возвращает FALSE, что свидетельстует о ненужности запуска цикла очереди сообщений и приложение закрывается. При уничтожении вызывается метод деструктора ~CD3DAppTemplateApp() внутри которого удаляется созданный объект немодального главного окна приложения.

   
       
 

Особенность данного решения поставленной задачи: mfc + directx9c в простоте реализации.

Недостаток состоит в том, что требуется использование вспомогательного окна, которое в целом никак не используется - лишь отображается, а затем скрывается. Но использование его требуется по той причине, что класс CWinApp в своём свойстве m_pMainWnd обязательно требует окна производного от CWnd, каковым окно приложения, создаваемое для directx-приложения средствами WinAPI не является.

Можно конечно предложить более сложный способ - использовать главное окно для целей directx, однако это значительно усложнит задачу, потребуя сильных изменений в реализации функции InitialD3DAppSettings() главным образом для использования готового окна, а не его создания, переделки DXUTMainLoop для работы исходя из очереди сообщений прокачиваемых через методы CWinApp и некоторые другие.

 

   
       
 

Моей целью было предложить Вам достаточно простой способ совместного использования directx9c и mfc и я считаю, что таковой и предложил Вам. По мере накопления Вами опыта в программирования на directx + mfc Вы, возможно, найдете для себя более оптимальные решения, еще более подходящие для Ваших нужд.

Так что желаю Вам всяческих успехов на этом поприще.

Сам же я, являясь по-сути Delphi DirectX - программистом вот уже начиная с далекого 2002 года, могу сказать, что использование для этих целей VC++ не намного сложнее, а в чём-то даже проще. Но то, что Вы выберете для использования с DirectX - C++ или Delphi будет всецело зависеть от Ваших возможностей в настоящем времени, главным образом касающихся наличия у Вас под рукой той или иной среды программирования BDS (Borland Developer Studio) или MSVS (Microsoft Visual Studio) и опыта в работе с ними.

При желании Вам всегда можно будет перейти с C++ на Delphi и наоборот, как это имело место в моём случае.

   
       
 

Так что же лучше Delphi или C++ ???

- Решать Вам!

   
       
       
 

Новости о развитии проекта смотрите на сайтах -

http://megainformaticsite.pochta.ru

http://www.megainformatic.narod.ru

   
       
 

Cвои пожелания, вопросы или заметки отправляйте на:

megainformatic@mail.ru

 
     
  (c) Мега Информатик 2006-2009          
         
       


Hosted by uCoz