Уважаемые корифеи игростроя!
Я пытаюсь учиться в построении своего игрового движка. При этом использую книги.
На данный момент -- это "Искусство программирования игр на С++" (Михаил Фленов)[2006]
Но по ходу возникают проблемы, которые я решить не в состоянии.
Я думаю, что не одинок в таком положении. Поэтому тема может быть интересна и другим новичкам игростроя.
По ходу буду задавать вопросы.
Заранее ОЧЕНЬ ПРИЗНАТЕЛЕН тем, кто даст ясные и понятные комменты и разъяснения.
Вопрос №1.
При инициализации Direct3D не работает режим fullscreen. программа вылетает с ошибкой.
Вот исходники:
Что там нужно изменить или добавить?
ЗЫ. Да, забыл сказать, что у меня Виста(SP2) стоит на рабочей машине.
vkd
выкладывай сорсы сюда, влом что-то качать
Mimon
> выкладывай сорсы сюда, влом что-то качать
вот первая часть
#pragma once
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3dxof.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "winmm.lib")
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <mmsystem.h> // подключаем системную библиотеку
#include <d3dx9core.h> // подключаем заголовочный файл для работы со шрифтом
#include <d3dx9Mesh.h> //
// Global Variables:
char szWindowClass[] = "Direct3DTemplateProj";
char szTitle[] = "Direct3D";
// Direct3D objects
IDirect3D9 *pD3D = NULL;
IDirect3DDevice9 *pD3DDevice = NULL;
int iWidth=800;
int iHeight=600;
// Функция инициализации Direct3D
HRESULT DX3DInit(IDirect3D9 **ppiD3D9,
IDirect3DDevice9 **ppiD3DDevice9,
HWND hWnd,
DWORD iWidth,
DWORD iHeight,
BOOL bFullScreen)
{
// Инициализация
if((*ppiD3D9 = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
return E_FAIL;
// Заполняем основные параметры представления
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = iWidth;
d3dpp.BackBufferHeight = iHeight;
// Запрос на отображение в полноэкранном режиме
int iRes;
if (!bFullScreen)
iRes=MessageBox(hWnd, "Use fullscreen mode?", "Screen", MB_YESNO | MB_ICONQUESTION);
else
iRes = IDYES;
if(iRes == IDYES)
{
// Полноэкранный режим
// Установка параметров полноэкранного режима
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.Windowed = FALSE;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
else
{
// Оконный режим
RECT wndRect;
RECT clientRect;
GetWindowRect(hWnd, &wndRect);
GetClientRect(hWnd, &clientRect);
iWidth = iWidth + (wndRect.right-wndRect.left) - (clientRect.right-clientRect.left);
iHeight = iHeight + (wndRect.bottom-wndRect.top) - (clientRect.bottom-clientRect.top);
MoveWindow(hWnd, wndRect.left, wndRect.top, iWidth, iHeight, TRUE);
// Получить формат пикселя
D3DDISPLAYMODE d3ddm;
(*ppiD3D9)->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
// Установка параметров
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.Windowed = TRUE;
}
DWORD Flags= D3DCREATE_MIXED_VERTEXPROCESSING;
// Создать 3D устройство
HRESULT hRes;
if(FAILED(hRes = (*ppiD3D9)->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd, Flags,
&d3dpp, ppiD3DDevice9)))
return hRes;
// Установить перспективу
float Aspect = (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight;
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4.0f, Aspect, 0.001f, 1000.0f);
(*ppiD3DDevice9)->SetTransform(D3DTS_PROJECTION, &matProjection);
(*ppiD3DDevice9)->SetRenderState(D3DRS_LIGHTING, FALSE);
return S_OK;
}
HRESULT DX3DInitZ(IDirect3D9 **ppiD3D9,
IDirect3DDevice9 **ppiD3DDevice9,
HWND hWnd,
DWORD iWidth,
DWORD iHeight,
BOOL bFullScreen)
{
// Инициализация
if((*ppiD3D9 = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
return E_FAIL;
// Заполняем основные параметры представления
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = iWidth;
d3dpp.BackBufferHeight = iHeight;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.EnableAutoDepthStencil = TRUE;
// Запрос на отображение в полноэкранном режиме
int iRes;
if (!bFullScreen)
iRes=MessageBox(hWnd, "Use fullscreen mode?", "Screen", MB_YESNO | MB_ICONQUESTION);
else
iRes = IDYES;
if(iRes == IDYES)
{
// Полноэкранный режим
// Установка параметров полноэкранного режима
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.Windowed = FALSE;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
else
{
// Оконный режим
RECT wndRect;
RECT clientRect;
GetWindowRect(hWnd, &wndRect);
GetClientRect(hWnd, &clientRect);
iWidth = iWidth + (wndRect.right-wndRect.left) - (clientRect.right-clientRect.left);
iHeight = iHeight + (wndRect.bottom-wndRect.top) - (clientRect.bottom-clientRect.top);
MoveWindow(hWnd, wndRect.left, wndRect.top, iWidth, iHeight, TRUE);
// Получить формат пикселя
D3DDISPLAYMODE d3ddm;
(*ppiD3D9)->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
// Установка параметров
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.Windowed = TRUE;
}
DWORD Flags= D3DCREATE_MIXED_VERTEXPROCESSING;
// Создать 3D устройство
HRESULT hRes;
if(FAILED(hRes = (*ppiD3D9)->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd, Flags,
&d3dpp, ppiD3DDevice9)))
return hRes;
Mimon
> выкладывай сорсы сюда, влом что-то качать
вот вторая (продолжение) (я все в один файл слил)
// Установить перспективу
float Aspect = (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight;
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4.0f, Aspect, 1.0f, 5000.0f);
(*ppiD3DDevice9)->SetTransform(D3DTS_PROJECTION, &matProjection);
(*ppiD3DDevice9)->SetRenderState(D3DRS_LIGHTING, TRUE);
return S_OK;
}
DWORD LoadMesh(char *filename, IDirect3DDevice9 *ppiD3DDevice9,
ID3DXMesh **ppMesh,
LPDIRECT3DTEXTURE9 **pMeshTextures,
char *texturefilename,
D3DMATERIAL9 **pMeshMaterials
)
{
LPD3DXBUFFER pD3DXMtrlBuffer;
DWORD dwNumMaterials;
D3DXLoadMeshFromX(filename, D3DXMESH_SYSTEMMEM,
ppiD3DDevice9, NULL, &pD3DXMtrlBuffer, NULL, &dwNumMaterials, ppMesh);
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
(*pMeshTextures) = new LPDIRECT3DTEXTURE9[dwNumMaterials];
(*pMeshMaterials) = new D3DMATERIAL9[dwNumMaterials];
for( DWORD i=0; i<dwNumMaterials; i++ )
{
// Копируем материал
(*pMeshMaterials) = d3dxMaterials.MatD3D;
// Создаем текстуру
if( FAILED(D3DXCreateTextureFromFile(ppiD3DDevice9,
d3dxMaterials.pTextureFilename, &(*pMeshTextures))))
if( FAILED(D3DXCreateTextureFromFile(ppiD3DDevice9,
texturefilename, &(*pMeshTextures))))
(*pMeshTextures) = NULL;
}
// (ID3DXMesh *)(*ppMesh)->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);
return dwNumMaterials;
}
bool LoadTexture(DWORD* text_buf, int iWidth, int iHeight, char* filename)
{
HANDLE hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
BITMAPFILEHEADER bmpfilehdr;
DWORD dwRead;
if(!ReadFile(hFile, &bmpfilehdr, sizeof(bmpfilehdr), &dwRead, NULL))
return FALSE;
char* ptr=(char*)&bmpfilehdr.bfType;
if (*ptr!='B' || *++ptr!='M')
return FALSE;
BITMAPINFOHEADER bmpinfohdr;
if(!ReadFile(hFile, &bmpinfohdr, sizeof(bmpinfohdr), &dwRead, NULL))
return FALSE;
if (bmpinfohdr.biCompression!=BI_RGB)
return 0;
int iImageSize=bmpinfohdr.biSizeImage;
if (iImageSize==0)
iImageSize=((iWidth*4+3) & ~3)*iHeight;
BYTE* buf=new BYTE[iImageSize];
if(!ReadFile(hFile, buf, iImageSize, &dwRead, NULL))
return FALSE;
if (bmpinfohdr.biBitCount!=24)
return FALSE;
int bytesgiven=(iWidth*3+3) & ~3;
DWORD* btSurf = text_buf;
BYTE* imagebits = (BYTE*)(&buf[(iHeight-1)*bytesgiven]);
for (int i=0; i<iHeight; i++)
{
RGBTRIPLE* tlImage=(RGBTRIPLE*)imagebits;
for (int p=0; p<iWidth; p++)
{
*btSurf = (DWORD)((tlImage->rgbtBlue) | (tlImage->rgbtGreen << 8) |
(tlImage->rgbtRed << 16) | (0xFF << 24));
tlImage++;
btSurf++;
}
imagebits -= bytesgiven;
}
delete [] buf;
return TRUE;
}
// имя: DeleteDirect3D()
// назначение: освобождение захваченных ресурсов
VOID DeleteDirect3D()
{
if (pD3DDevice)
pD3DDevice -> Release();
if (pD3D)
pD3D -> Release();
}
// Объявление фукций, включенных в этот модуль:
// Функция инициализации Direct3D
HRESULT DX3DInit(IDirect3D9 **ppiD3D9,
IDirect3DDevice9 **ppiD3DDevice9,
HWND hWnd,
DWORD iWidth,
DWORD iHeight,
BOOL bFullScreen
);
HRESULT DX3DInitZ(IDirect3D9 **ppiD3D9,
IDirect3DDevice9 **ppiD3DDevice9,
HWND hWnd,
DWORD iWidth,
DWORD iHeight,
BOOL bFullScreen
);
DWORD LoadMesh(char *filename, IDirect3DDevice9 *ppiD3DDevice9,
ID3DXMesh **ppMesh,
LPDIRECT3DTEXTURE9 **pMeshTextures,
char *texturefilename,
D3DMATERIAL9 **pMeshMaterials
);
bool LoadTexture(DWORD* text_buf, int iWidth, int iHeight,
char* filename);
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool Init(HWND hWnd);
void GraphEngine();
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
MSG msg;
HWND hWnd;
CoInitialize(NULL);
// Register window class
wcex.cbSize = sizeof(wcex);
wcex.style = CS_CLASSDC;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInst;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wcex))
return FALSE;
// Create the main window
hWnd = CreateWindow(szWindowClass, szTitle, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, iWidth, iHeight, NULL, NULL, hInst, NULL);
if(!hWnd)
return FALSE;
ShowWindow(hWnd, SW_NORMAL);
UpdateWindow(hWnd);
if(Init(hWnd) == TRUE)
{
while (true)
{
// если есть сообщение в очереди
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
// обработать сообщение
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT) break;
}
// Вызвать функцию движка игры
GraphEngine();
}
}
// Освобождаем захваченные ресурсы:
DeleteDirect3D();
CoUninitialize();
return 0;
}
// Реализации ф-ций:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool Init(HWND hWnd)
{
if (DX3DInitZ(&pD3D, &pD3DDevice, hWnd, iWidth, iHeight, FALSE)!=S_OK)
{
MessageBox(hWnd, "DirectX Initialize Error", "Error", MB_OK);
return FALSE;
}
return TRUE;
}
void GraphEngine()
{
pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
if (SUCCEEDED(pD3DDevice->BeginScene()))
{
pD3DDevice->EndScene();
}
pD3DDevice->Present(NULL, NULL, NULL, NULL);
}
может все и не стоило приводить, да я так, на всякий случай...
код полностью рабочий за исключением вышеописанной проблемы.
vkd
> При инициализации Direct3D не работает режим fullscreen. программа вылетает с
> ошибкой.
А она у тебя вообще компилируется? Прежде, чем собрал модуль, исправил с десяток синтаксических ошибок.
После сборки и оконный, и фулскирин работают(!). Собственно, не понял: в чем проблема :) У тебя карточка сочетание D3DFMT_R5G6B5+D3DFMT_D24S8 поддерживает (проверь через IDirect3D9::CheckDepthStencilMatch())?
destrator
> А она у тебя вообще компилируется?
Компилится и работает нормально кроме режима fullscreen.
Видюха у меня GF 7000M. Что, может не поддерживать D3DFMT_R5G6B5+D3DFMT_D24S8 ?
Какие параметры вставлять в ф-цию IDirect3D9::CheckDepthStencilMatch()?
Это ж надо "для изучения" сразу прыгнуть в дебри Direct3D.
Скачай какой нибудь простой движок вроде HGE, разберись на нём сначала, он от тебя все тонкости интимных отношений с D3D спрячет.
kvakvs
> он от тебя все тонкости интимных отношений с D3D спрячет
вот этого как раз и не хочется! Я хочу научиться в ПРОЦЕССЕ!
vkd
> На данный момент -- это "Искусство программирования игр на С++" (Михаил
> Фленов)[2006]
Хорош прикалываться.
З.Ы.
Задай себе правильный вопрос - какой движок написал Михаил Фленов от 2006 года.
Вот такой же напишешь и ты.
vkd
Лучше Джим Адамса почитай, это реально лучше. (Джим Адамс Программирование ролевых игр с DirectX). Вроде на netlib онлайн библиотека есть
http://www.netlib.narod.ru/library/book0051/index.htm
сорцы качнул с инета.
В свое время я долго и мучительно искал ошибки, когда у меня была такая же проблема.
vkd
> "Искусство программирования игр на С++" (Михаил Фленов)[2006]
Плохая книга. Точнее я ее не читал, но автор не крутой.
Тебе нужно учиться по вот таким примерно урокам.
http://www.codesampler.com/dx9src.htm
Просто и понятно.
Раньше еще был сайт ultimategameprogramming.com но сейчас он мертв. Поищи может найдешь уроки с него.
Еще есть gametutorials платный, но CD можно найти на торрентах.
graveman
Pokimon
Спасибо! Сейчас буду смотреть.
Pokimon
> Плохая книга. Точнее я ее не читал, но автор не крутой.
Ты прям стереотип ходячий xD
d.m.k
> Ты прям стереотип ходячий xD
Что Вы имеете ввиду?
graveman
> Лучше Джим Адамса почитай, это реально лучше. (Джим Адамс Программирование
> ролевых игр с DirectX). Вроде на netlib онлайн библиотека есть
> http://www.netlib.narod.ru/library/book0051/index.htm
Она реально лучше?
> сорцы качнул с инета.
Где?
> В свое время я долго и мучительно искал ошибки, когда у меня была такая же
> проблема.
Решились благодаря этой книге?
Тема в архиве.