Автор: Борис Клевич «wildboar»

Опубликовано: 13.12.2006

Изменено: 12.01.2007

Постоянная ссылка

Комментарии [5]

Текст на основе ID3DXFont и Счетчик кадров


В статье показывается как сделать простой счетчик кадров для вашего приложения, а также использовать шрифт DirectX.



Страницы: 1 2

Подготовка проекта

Данная статья ориентирована на использование операционной системы Windows, средства разработки Microsoft Visual C++ 2005 и комплекта разработчика DirectX SDK версии 9.00.1126 (лето 2003).

Для работы вы можете использовать бесплатно распространяемую версию Visual C++ 2005 Express Edition, скачать которую можно с сайта компании Microsoft.

Далее приводится необходимый минимум по предотвращению ошибок сборки проекта.
Установите DirectX 9 SDK и укажите компилятору пути к папкам DirectX 9 SDK:

Tools -> Options... -> Projects and Solutions -> VC++ Directories -> Show Directories for Include Files -> $(VCInstallDir)PlatformSDKinclude

поставить на самую верхнюю позицию. Позицией ниже - поставьте папку Include от DirectX 9 SDK (зависит от того, куда вы его установили, например, C:DirectXInclude).
Делаем аналогично для библиотечных файлов:
 

Tools -> Options... -> Projects and Solutions -> VC++ Directories -> Show Directories for Library Files -> $(VCInstallDir)PlatformSDKLib


поставить на верхнюю позицию. Позицией ниже ставим папку Lib от DirectX 9 SDK соответственно вашему железу (Lib, Libx86, Libx64).

В разных версиях Directx 9 SDK есть существенные отличия, возможна некоторая несовместимость! Например, функция D3DXCreateFont в разных версиях SDK – содержит разное число аргументов, соответственно вам придется немного подредактировать исходный код статьи.

Создайте новый Проект (Ctrl+Shift+N) используя шаблон прокта Win 32 Project. Тип приложения - Windows application. Дополнительные опции – Empty Project. После этого создадим новый файл, в котором мы будем писать исходный код программы.
На панельке Solution Explorer (Ctrl+Alt+L), находится папка Source Files, нажмите на ней правой клавишей мыши Add -> New Item..., в поле Templates выбирайте "С++ File(.cpp)" и дайте название файлу в поле Name.

В конце статьи смотрите также небольшой раздел "Возможные ошибки", а также готовые исходные коды.

Создание оконного приложения

Напишем первую программу, которая создаст окно – пространство для работы. В процессе подготовки и настройки проекта мы создали пустой файл c расширением ".cpp", начнем заполнять его кодом.
Для создания первой программы потребуются всего 2 функции (порядок в списке тот же, что и в коде):

1. Создать функцию WindowProc() – обработчик событий
2. Создать функцию WinMain() – вход в программу
3. Создать Класс Окна
4. Зарегистрировать Класс Окна
5. Использовать этот класс для Создания Окна
6. Создать цикл событий для обработки сообщений windows
7. При завершении работы программы – разрушить Окно и Разрегистрировать Класс Окна.

//--------------------------------------------------------------------------------
// Листинг 1.0 – Простое Окно (написанный ниже код выделите, скопируйте и
// вставте в пустой файл, нажмите «F7», когда в Output появится 
// "Build: 1 succeeded" - нажмите «F5»)
//--------------------------------------------------------------------------------
// подключение заголовочных файлов (рассширение «.h» сокрашение от слова «header»)
#include ‹windows.h›	//специальная директива, чтобы не вкл. много-чего отдельно

// Обработчик событий
LRESULT CALLBACK WindowProc(HWND hwnd,		// Дескриптор окна (отправитель)
				UINT msg,	// Идентификатор сообщения
				WPARAM wparam, 	// Доп информация о сообщении
				LPARAM lparam)	// Доп информация о сообщении
{	
	PAINTSTRUCT ps;		//используется в WM_PAINT
	HDC hdc;		//дескриптор контекста устройства

// проверка на получение какого-либо сообщения
switch(msg)
{

  case WM_KEYDOWN: 
  {
	if(wparam==VK_ESCAPE)
	PostQuitMessage(0);
	DestroyWindow(hwnd);	// Разрушить Окно для освобождения памяти
	return 0;		// проверка: если все ОК - 0  
  } break;			// выход из события

  case WM_PAINT: 
  {	
	hdc = GetDC(hwnd);
	//начинаем рисовать (иначе, потом при GDI экран будет моргать)
	hdc = BeginPaint(hwnd,&ps);
	SetTextColor(hdc,RGB(150,50,10));
	SetBkColor(hdc,RGB(250,250,150));
	SetBkMode(hdc,OPAQUE);	
	TextOut(hdc,			//дескриптор
	10,10,				//начальные координаты
	"вывод текста GDI",		//текст
	(int)strlen("вывод текста GDI")); //(целые числа)количество символов в строке
	EndPaint(hwnd,&ps);
	ReleaseDC(hwnd,hdc);
	return 0;          
  } break;				// выход из события
		
  case WM_DESTROY: 
  {
	PostQuitMessage(0);	// освободить память и выйти 
	DestroyWindow(hwnd);	// Разрушить Окно для освобождения памяти
	return 0;		//проверка на успех выполнения
  } break;

  default:break;
} // конец цикла switch

// Обработка сообщений по умолчанию для остальных сообщений
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // конец WindowProc

//-----------------
//Функция WinMain() 
//-----------------
//Декларатор WINAPI – заставляет передавать параметры слева направо (по умолч. CDECL)
int WINAPI WinMain(HINSTANCE hinstance,
			HINSTANCE hprevinstance,
			LPSTR lpcmdline,
			int ncmdshow)
{
WNDCLASSEX winclass; 	//структура для хранения класса, который мы создаём
HWND	hwnd;		//создаем дескриптор окна
MSG	msg;		//создаем сообщение

//заполним структуру класса окна
winclass.cbSize		= sizeof(WNDCLASSEX);	//размер структуры
winclass.style		= CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc	= WindowProc;	//указатель на функцию - обработчик
winclass.cbClsExtra	= 0;
winclass.cbWndExtra	= 0;
winclass.hInstance	= hinstance;
winclass.hIcon		= LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor	= LoadCursor(NULL, IDC_ARROW);
// WHITE_BRUSH 0; LTGRAY_BRUSH 1; GRAY_BRUSH 2; DKGRAY_BRUSH 3;BLACK_BRUSH 4;NULL_BRUSH 5
winclass.hbrBackground	= (HBRUSH)GetStockObject(4);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= "class1";
winclass.hIconSm	= LoadIcon(NULL, IDI_APPLICATION);

// Регистрация класса окна
if (!RegisterClassEx(&winclass))
	return(0); 	//проверка на успех выполнения

// Создание окна
if (!(hwnd = CreateWindowEx(NULL,
	"class1",			//имя класса
	"Простое окно для форточек",	//заглавие окна
	WS_OVERLAPPEDWINDOW | WS_VISIBLE,
	30,30,				//начальная позиция x,y
	700,600,			//ширина "x" и высота "y"
	NULL,				// дескриптор родительского окна 
	NULL,				// дескриптор меню
	hinstance,			// экземпляр этого приложения
	NULL)))				// дополнительный параметр creation parms
return(0); 				//проверка на успех выполнения

// Вход в главный цикл событий c использованием PeekMessage()
while(TRUE)
	{
	// тест есть ли какае-нибудь сообщение
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	   { 
	   // тест на сообщение о выходе
	if (msg.message == WM_QUIT)
           break;
	
	   // преобразование ввода клавиш
	   TranslateMessage(&msg);
	   // отправление сообщений в WindowProc
	   DispatchMessage(&msg);
	   } 
	} // конец цикла событий

// возвращение в Windows + освобождение ресурсов
UnregisterClass("class1", hinstance); //разрегистрируем класс
return (int)msg.wParam; //уточнение - что работаем с целыми числами

} //конец WinMain

Подключаем DirectX

Удалите событие WM_PAINT из обработчика событий (WindowProc), а также:

	PAINTSTRUCT ps;		//используется в WM_PAINT
	HDC hdc;		//дескриптор контекста устройства

Этот код больше не понадобится, если оставить так – всё равно текст GDI не будет отображен. А теперь продолжим использовать предыдущий код, и внесем в него изменения для работы с DirectX.

Подключим к проекту заголовочный файл d3d9.h и библиотеку d3d9.lib

// подключение заголовков
#include ‹windows.h›		// специальная директива
#include ‹d3d9.h›		// direct3d9
#include ‹d3dx9.h›		// заголовок библиотеки утилит direct3d9

// подключение библиотек
#pragma comment (lib,"d3d9.lib")	// direct3d9
#pragma comment (lib,"d3dx9.lib")	// библиотека утилит direct3d9

Создадим указатели на интерфейсы Direct3D

//указатели на интерфейсы DirectX
LPDIRECT3D9 	m_pD3D = NULL;		//указатель на объект Direct3d9
LPDIRECT3DDEVICE9 m_pd3dDevice = NULL;	//указатель на устройство Direct3d9

Напишем функцию инициализации Direct3D - InitDirect3D()

//-------------------------
// Инициализация Direct3D
// Функция InitDirect3D() 
//-------------------------
HRESULT InitDirect3D(HWND hwnd)
{
	if (NULL == (m_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
	return E_FAIL;

	// Переменная для хранения информации об экране
	D3DDISPLAYMODE Display;
	if (FAILED(m_pD3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Display)))
	return E_FAIL;

	// Переменная для хранения параметров представления
	D3DPRESENT_PARAMETERS Direct3DParam;
	ZeroMemory(&Direct3DParam, sizeof(Direct3DParam));
	Direct3DParam.Windowed			= TRUE; // Оконный режим
	Direct3DParam.SwapEffect		= D3DSWAPEFFECT_DISCARD;
	Direct3DParam.BackBufferFormat		= Display.Format;
	Direct3DParam.EnableAutoDepthStencil	= TRUE;
	Direct3DParam.AutoDepthStencilFormat	= D3DFMT_D16;
	Direct3DParam.BackBufferWidth		= GetSystemMetrics(SM_CXSCREEN);
	Direct3DParam.BackBufferHeight		= GetSystemMetrics(SM_CYSCREEN);
	Direct3DParam.BackBufferCount		= 3;
	Direct3DParam.PresentationInterval 	= D3DPRESENT_INTERVAL_IMMEDIATE; // выкл. vsync
	if (FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL, hwnd,
		D3DCREATE_HARDWARE_VERTEXPROCESSING,
		& Direct3DParam, &m_pd3dDevice )))
	return E_FAIL;
	return S_OK;
}

Напишем функцию прорисовки графики Render()

//-------------------------
// Прорисовка графики
// Функция Render()
//-------------------------
void Render()
{
	if(m_pd3dDevice  == NULL)     // Проверка на ошибки
	return;
	// Очистка экрана указанным D3DCOLOR_XRGB цветом
	m_pd3dDevice ->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
						D3DCOLOR_XRGB(0,100,100), 1.0f, 0 );

	// Начало сцены
	m_pd3dDevice ->BeginScene();
	// Функции прорисовки сцены 
    
	// Конец сцены
	m_pd3dDevice ->EndScene();
 	// Отобразить
	m_pd3dDevice ->Present( NULL, NULL, NULL, NULL );
}

Пишем функцию освобождения захваченных ресурсов Release3D()

//-----------------------------------
// Освобожение захваченных ресурсов
// Функция Release3D()
//-----------------------------------
void Release3D()
{
	if( m_pd3dDevice != NULL) 
	m_pd3dDevice ->Release();
	if( m_pD3D != NULL)
	m_pD3D ->Release();
}

Сделаем изменения в WinMain()

// Добавляем InitDirect3D в WinMain
if (SUCCEEDED(InitDirect3D(hwnd)))
{
	ShowWindow(hwnd,SW_SHOWDEFAULT);
	UpdateWindow(hwnd);
	// Вход в главный цикл событий c использованием PeekMessage()
	while(TRUE)
	{
		// Тест есть ли какае-нибудь сообщение
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{ 
		// Тест на сообщение о выходе
		if (msg.message == WM_QUIT)
		break;
		TranslateMessage(&msg);
		DispatchMessage(&msg); // Отправление сообщений в WindowProc
		}
		else Render(); 
	   } // Конец цикла событий while
	} // Конец InitDirect3D()
   // Возвращение в Windows и освобождение ресурсов
   Release3D();			// Вызов функции Release3D()
   UnregisterClass("winclass", winclass.hInstance); // Разрегистрируем класс
   return (int)msg.wParam; // Уточнение - что мы работаем с целыми числами
}// Конец WinMain
Страницы: 1 2