12 марта 2010 в 15:45
Direct3D Урок 01: Инициализация приложения
Привет всем! Если вы читаете эту статью, вам очень хочется попробовать себя в роли не простого игрока, а полноценного разработчика игр. Прочитав данную статью вы научитесь Инициализировать Direct3D девятой версии.
Для получения "эффекта" от этой статьи вам необходимо обзавестись:
1. MicroSoft Visual C++ 6.0. Я пользуюсь шестой версией, но теоретически исходники должны скомпилиться и под более поздними версиями.
2. DirectX 9.0 SDK (Software Developement Kit). Взять его можно с официального сайта Microsoft, а именно здесь.
Правда весит он НЕСКОЛЬКО-СОТ-МЕГОВ:( Поэтому для тех кто не имеет скоростного интернета, я выложил библиотеки и заголовочные файлы DirectX 9.0:
DX9.0_Include.rar - (~987Kb) Header'ы для директаикса.
DX9.0_Lib.rar- (~4341Kb) А здесь библиотеки.
С ними вы сразу же сможете начать программировать программы под любые компоненты DirectX 9.0
Да, и на последок: если вы не скачивали SDK, а брали от сюда хедеры и либы, то, чтобы ваш VisualC++ нашел их надо сделать следующее:
1. Открываем MSVisualC++ 6.0
2. Идем в Tools->Options...
3. Там идем в закладку Directories
4. В Show directories for: выбираем Include files
5. В списке Directories: добаляем путь до папки, в которую вы распаковали архив DX9.0_Include.rar
6. В Show directories for: выбираем Library files
7. В списке Directories: добаляем путь до папки, в которую вы распаковали архив DX9.0_Lib.rar
8. Жмем OK. Теперь ваш компилятор готов к работе.
Вот и всЁ. Приступим.
Чтобы начать создание нашей супер-пупер:) игры надо создать новый проект. Делается это так:
1. Загружаете MicroSoft Visual C++ 6.0.
2. Идете в меню File->New...
3. Из списка возможных типов проектов выбираете Win32 Application.
4. В поле Project name вводите название проекта (например, MyFirstProgram).
4. В поле Location вводите путь где будет создана папка с вашим проектом.
5. Кликаете на кнопке OK.
6. Выбираете An empty project.
7. Кликаете на кнопке Finish, затем OK.
Все проект создан. Теперь добавим первый файл, в котором мы будем набирать код нашей программы:
8. Идете в меню File->New...
9. Из списка выбираем C++ Source File.
10. В поле File name вводим название файла (например, main).
11. Жмете OK.
Все теперь можно приступать к работе!
Сначала включаем библиотеки:
#pragma comment(lib, "d3d9.lib") // Ссылка на d3d9.lib #pragma comment(lib, "d3dx9.lib") // Ссылка на d3dx9.lib #pragma comment(lib, "winmm.lib") // Ссылка на winmm.lib
А теперь заголовочные файлы:
//Включаемые заголовочные файлы #include <windows.h> // Заголовочный файл для Windows #include <d3d9.h> // Заголовочный файл для DirectX3D #include <d3dx9.h> // Заголовочный файл для некоторых // функций DirectX3D
Далее идут переменные
//Макрос для освобождения интерфейсов #define SAFE_RELEASE(x) if(x != NULL){ x->Release(); x = NULL; } #define APPNAME "\"Первая программа под Direct3D 9.0\" by L1f" // Название окна #define CLASSNAME "DIRECT3D" // Название класса окна bool isProcess=true; // Флаг процесса рендеринга RECT WindowRect; int Width=640, Height=480; // Высота и Ширина окна bool fullscreen = false; // Оконный/Полноэкранный режим bool keys[256]; // Массив для работы с клавиатурой HWND hWnd; // Здесь хранится экземпляр нашего окна
Далее идут переменные отвечающие за работу с Direct3D
LPDIRECT3D9 g_pD3D = NULL;// Используется для создания Устройство рендеринга LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;// Устройство рендеринга D3DPRESENT_PARAMETERS d3dpp; // Параметры для создания Direct3D
У нас в приложении будет несколько функций. Это:
1. WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) - С нее начинается выполнение нашей программы. В ней создается наше окно, инициализируются все объекты и т.д.
2. MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) - Обработчик сообщений поступающих нашему окну от Windows.
3. bool AllInit() - Здесь производится инициализация всех необходимых нам интерфейсов.
4. void AllShutdown() - А здесь - их удаление.
5. bool InitD3D(int width, int height, bool fscreen) - Эта функция будет инициализировать наше устройство рендеринга - g_pd3dDevice.
6. bool ResetWindow(int width, int height, bool fscreen) - Этой функцией можно изменить наше окно. Например, можно перейти из оконного режима в полноэкранный или изменить размеры окна.
7. Функция void ReSizeD3DScene(int width, int height) будет изменять пропорции экрана при изменении размеров окна, чтобы изображение оставалось неизменным.
8. Две функции bool Cleanup() и bool ReInit() пока нам не нужны.
9. И наконец самая важная (для нас) функция void Render() - Она рисует нашу сцену. Однако пока кроме очищения экрана в различные цвета (для того, чтоб вы видели, что все работает) она не делает, но вскоре всЁ изменится и тогда...
А пока рассмотрим эти функции поподробней:
Итак функция WinMain:
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // Регистрирование класса окна WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_CLASSDC; wc.lpfnWndProc = MsgProc; wc.cbClsExtra = 0L; wc.cbWndExtra = 0L; wc.hInstance = GetModuleHandle(NULL); wc.hIcon = LoadIcon(NULL, IDI_HAND); // Стандартный значек wc.hCursor = LoadCursor(NULL, IDC_ARROW);// Стандартный курсор wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = CLASSNAME; wc.hIconSm = NULL; RegisterClassEx( &wc ); // Регистрируем класс окна DWORD WindowStyle, WindowExStyle; if(fullscreen) { WindowExStyle=WS_EX_APPWINDOW; // Расширенный стиль окна WindowStyle=WS_POPUP; // Стиль окна } else { WindowExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Расширенный стиль окна WindowStyle=WS_OVERLAPPEDWINDOW; // Стиль окна }; WindowRect.left=(long)0; // Устанавливаем позицию окна по оси X WindowRect.right=(long)Width; // Устанавливаем ширину окна WindowRect.top=(long)0; // Устанавливаем позицию окна по оси X WindowRect.bottom=(long)Height; // Устанавливаем высоту окна // согласовываем размеры окна со стилем AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, WindowExStyle); // Создаем окно if (!(hWnd=CreateWindowEx( WindowExStyle, // Расширенный стиль CLASSNAME, // Имя класса APPNAME, // Заголовок окна WindowStyle | // Наш стиль окна WS_CLIPSIBLINGS | // Нужен оконный стиль WS_CLIPCHILDREN, // Нужен оконный стиль 0, 0, // Позиция окна WindowRect.right-WindowRect.left, // Просчет ширины окна WindowRect.bottom-WindowRect.top, // Просчет высоты окна NULL, // Нет родительского окна NULL, // Не нада нам меню wc.hInstance, // Instance NULL))) // Ничего не создавать { MessageBox(NULL,"Не могу создать окно!","ОШИБКА",MB_OK|MB_ICONEXCLAMATION); } ShowCursor(false); // Скрываем курсов ShowWindow( hWnd, SW_SHOWNORMAL ); // Показываем окно SetFocus(hWnd); // Устанавливаем фокус окна UpdateWindow( hWnd ); // Обновляем окно SetForegroundWindow(hWnd); // Немного высокий приоритет // Инициализация if( AllInit() ) { MSG msg; //Начинаем главный процесс рендеринга while (isProcess) { // Обработка всех сообщений if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else { // Если нажат ESCAPE то выходим из цикла if(keys[VK_ESCAPE]) isProcess=false; if(keys[VK_F1]) // Если нажат F1 { //Оконный/полноэкранный режим fullscreen=!fullscreen; ResetWindow(Width, Height, fullscreen); } Render(); // Прорисовываем сцену } } } AllShutdown(); // Вызываем функцию удаления всего что наваяли ShowCursor(true); // Показываем курсор UnregisterClass( CLASSNAME, wc.hInstance ); return 1; }
Следующей функцией, которую мы рассмотрим будет InitD3D, инициализирующая Direct3D 9.0:
bool InitD3D(int width, int height, bool fscreen) { if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) // Если не удалось создать Direct3D выведем сообщение о ошибке MessageBox(NULL,"Не могу создать Direct3D9!","ОШИБКА",MB_OK|MB_ICONEXCLAMATION); ZeroMemory( &d3dpp, sizeof(d3dpp) ); // Очищаем память из-под d3dpp // Если поноэкранное приложение if(fscreen) { d3dpp.BackBufferWidth = width; // Устанавливаем ширину заднего буфера d3dpp.BackBufferHeight = height;// Устанавливаем высоту заднего буфера d3dpp.BackBufferCount = 1; // Устанавливаем кол-во задниих буферов // Двойная буферизация // Устанавливаем чатоту экрана и Вертикальную синхронизацию по дефолту d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } else { d3dpp.FullScreen_RefreshRateInHz =0; d3dpp.PresentationInterval =0; }; d3dpp.hDeviceWindow = hWnd; d3dpp.BackBufferFormat = D3DFMT_R5G6B5; // Формат заднего буфера d3dpp.EnableAutoDepthStencil = true; // Юзать Буфер глубины и стенсил d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // Формат буфера глубины и стенсила d3dpp.Windowed = !fscreen; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Создаем устройство рендеринга: // Пытаемся создать устройство рендеринга с использованием возможностей видеокарты if(FAILED( g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { // Если не получилось // Пытаемся создать устройство рендеринга без использования // возможностей видеокарты if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { // Иначе выводим сообщение об ошибке MessageBox(NULL,"Не могу создать устройство рендеринга!", "ОШИБКА",MB_OK|MB_ICONEXCLAMATION); return false; } } return true; }
И на последок рассмотрим рендеринг ( Render ).
void Render() { HRESULT hr; // Проверяем Direct3dDevice на потерянность hr = g_pd3dDevice->TestCooperativeLevel(); // если окно не в фокусе выходим из цикла рендеринга if(hr==D3DERR_DEVICELOST) return; // если окно опять в фокусе пытаемся восстановить устройство рендеринга if(hr==D3DERR_DEVICENOTRESET) { Cleanup(); g_pd3dDevice->Reset(&d3dpp); if( g_pd3dDevice ) ReInit(); } if( NULL == g_pd3dDevice ) return; // Начинаем отрисовку нашей сцены if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Очищаем задний буфер и буфер глубины g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(rand()%255, rand()%255, rand()%255), 1.0f, 0L); // За счет этих rand'омов на экран будет выводиться разные цвета //--------------------------// // Здесь мы будем рисовать! // //--------------------------// // Закончили рисовать g_pd3dDevice->EndScene(); // Отображаем задний буфер на экран g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } }
Управление:
Esc - Выход
F1 - Переключение между полноэкранным и оконным режимами.
Также приложение хорошо "реагирует" на Alt-Tab.
Продолжение следует...
12 октября 2016 в 11:54
Код не компилируется без основательной доработки напильником. Для начинающих это плохо...http://www.gamedev.ru/code/articles/?id=4658
Вот здесь почти такой же код, но он, тем не менее, сразу работает.
20 августа 2019 в 16:33
Спасибо
авторизуйтесь
или войдите через