Программирование игр на С++ для платформы DirectX 9c |
||
Написание приложения DirectX9c + MFC в среде MSVS 2005 | ||
Данный урок является введением в программирование на C++ в MSVS 2008 Вам нужно иметь установленную среду Microsoft Visual Studio 2005 или 2008 (можно триал), и DirectX SDK 9 версии, или лучше самой последней - 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 File > New > Project > MFC > MFC Application опции
После
генерации приложения нужно настроить проект для использования заголовочных Добавить исходный код из 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. |
||
и добавьте все файлы из папки DXUT_mfc кроме DXUTguiIME.* и ImeUi.* Данные файлы относятся к использованию национальных языков и Вам пока не потребуются. |
||
Добавить шаблонный код для начальной инициализации типового D3D9 - приложения Рассмотрим что нужно добавить на примере проекта D3DAppTemplate В модуле D3DAppTemplate.h нужно внести следующие изменения и дополнения - #include
<d3d9.h> #include "D3DAppTemplateDlg.h" внутри описания класса class CD3DAppTemplateApp ~CD3DAppTemplateApp(); в конце описания класса public: В модуле D3DAppTemplate.cpp #include
"DXUT.h"
//-------------------------------------------------------------------------------------- ID3DXFont*
g_pFont = NULL; // Font for drawing text bool
g_bShowHelp = true; // If true, it renders the UI control text
void InitApp(); void InitialD3DAppSettings();
CD3DAppTemplateApp::CD3DAppTemplateApp()
BOOL
CD3DAppTemplateApp::InitInstance() CWinApp::InitInstance(); AfxEnableControlContainer();
// Standard initialization
pMainWindow = new CD3DAppTemplateDlg(); m_pMainWnd = pMainWindow; InitialD3DAppSettings(); //g_d3dApp.Cleanup3DEnvironment(); delete pMainWindow; pMainWindow = NULL;
// Since the dialog has been closed, return FALSE so that we exit the
void
InitialD3DAppSettings()
// Set the callback functions. These functions allow DXUT to notify DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackKeyboard( KeyboardProc );
// Show the cursor and clip it when in full screen InitApp();
// Initialize DXUT and create the desired Win32 window and Direct3D
/*DXUTCreateWindow( L"D3D9 App Template", 0, 0, LoadMenu(0,
SetWindowLong( DXUTGetHWND(), GWL_STYLE,
// We need to set up DirectSound after we have a window. //InitD3DApp();
// Pass control to DXUT for handling the message pump and
// Perform any application-level cleanup here. Direct3D device resources
are released within the
//return DXUTGetExitCode(); //--------------------------------------------------------------------------------------
// Setup the camera with view matrix
// Need to support ps 2.0
// Need to support A8R8G8B8 textures
return true; //--------------------------------------------------------------------------------------
HRESULT hr;
V( pD3D->GetDeviceCaps( pDeviceSettings->d3d9.AdapterOrdinal,
// If device doesn't support HW T&L or doesn't support 1.1 vertex
shaders in HW
// If the hardware cannot do vertex blending, use software vertex processing.
// If using hardware vertex processing, change to mixed vertex processing
// Debugging vertex shaders requires either REF or software vertex processing
return true;
#if
defined( DEBUG ) || defined( _DEBUG ) #ifdef
DEBUG_VS
return S_OK;
// Setup the camera's projection parameters
// set lighting
return S_OK; //-------------------------------------------------------------------------------------- g_fLastAnimTime = fTime;
// Update the camera's position based on user input
pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
//
pd3dDevice->EndScene();
// Output statistics
txtHelper.End();
return 0;
//g_d3dApp.Cleanup3DEnvironment(); //методы освобождения ресурсов нужно вызывать именно //здесь.
В данном примере g_d3dApp - объект игрового приложения не используется,
поэтому он здесь закомментирован. В приложении с игрой освобождение ресурсов
происходит именно так.
//-------------------------------------------------------------------------------------- SAFE_RELEASE( g_pTextSprite );
|
||
Этот же код вы найдете внутри модулей D3DAppTemplate.h и D3DAppTemplate.cpp в проекте D3DAppTemplate - | ||
Исходный код приложения 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++ ??? - Решать Вам! |
||
[назад] [далее] [к содержанию] |