著 Andy Pike
译 Aman JIANG
第一章: 准备就绪
What you will need (你需要什么)
Introduction (序)
(原著的话)
欢迎阅读本DX教程。本教程至少能帮你入门、使你了解怎样用DX8 来开发Windows游戏。我写这个教程的原由有二:首先,当出现DX时,我还是一个初学者。所以,我想边学习边写一个教程来锻炼自己。其次,对初学者来说,DX SDK 并不是很有帮助。而且,网上也没有什么像样的Dx8教程。另外,就像上面我提到的,我也是个初学者,所以,如果你发现教程中有什么地方不对,请给我写信:webmaster@andypike.com。
译者言
我也是一名初学者,所以,有言在先:如果你读英文能如履平地,建议你还是去读原著。此教程很适合入门,等你入门以后,你会发现,其实一切并没有想象的那样复杂。这是个不错的Dx8教程,我会尽最大努力把它翻译好。注:我并没有完全按照原著来译,不适之处,请多包涵。嗯,你应该弄到教程附带的源代码,没有那个可不行!可以到www.andypike.com去下载。欢迎指出我的错误,或与我联系,我的Email:Chaoyu_JIANG@hotmail.com or Aman_JIANG@163.com , QQ:15852673。
COM
What is COM? COM 是什么呢?COM 就是 Component Object Model, 组件对象模型。COM 接口和C++的抽象类相似(但不一样),就像抽象类没有与之相关的实际代码一样,COM描述了一套符号和语法而非实现过程。你也可以把 COM 对象就想象成一套为某个主题而设计的一整套库函数。DX 就提供了一套完整的设计3D游戏的库。最棒的就是,使用DX时,你不必去直接接触硬件,而由DX帮你代理了。这使得一些事情变得简单了。
使用 COM 时应该注意,必须在程序结束前释放所有的 COM 对象(或接口)。而且,释放它们的顺序应该和创建它们的顺序相反。就像这样:
1. Create interface A.
2. Create interface B.
3. Release interface B.
4. Release interface A.
调用它们的 Release 模块来释放它们。
Page Flipping (页翻动)
页翻动又是什么呢?嗯,你知道电影的原理吗?电影通过以每秒钟24幅的速度连续的闪动图像,每幅图像之间的差别又很小,由于人眼的滞留作用,我们看到的画面就是连续的了。这不难理解。其实,DirectX 也是这样工作的。我们把要显示的物体通通绘制到一个不可见的页上,我们称这个页为“后缓冲区”。绘制完后,快速的把它翻动到可见的“前缓冲区”上,并重复这个过程。当用户正在观看新绘制的可见页(前缓冲区)时,程序要降下一幅要显示的东西绘制到“后缓冲区”上。快速而连续的重复次过程,用户就会看到像电影一样连续的图像了。不过一般情况下,我们每秒钟能绘制的页数要比电影多很多。
如果我们不是用页翻动技术,那用户看到的屏幕中的物体,将会一个个的被绘制出来,虽然速度可能很快,但效果会很差,那并不是我们想要的。
所以,我们的游戏需要一个循环,称之为“Game Loop”。每次循环,我们都要清除“后缓冲区”,把该绘制的物体按照一定的逻辑都绘制到那上面,然后把它翻动到“前缓冲区”上,然后进入下一次循环。这个循环得直到游戏退出了才能结束。有时我们可能需要好几个这样的“后缓冲区”(多缓冲)来组成一个“交换链”(Swap Chain),以求更好的效果。
Devices (设备)
What is a device? 设备是什么?简单的说,就是你的3D卡。 你得创建一个接口来代表设备,然后使用那个接口来绘制东西。
Game Loop (游戏循环)
什么是游戏循环呢?游戏循环是一段代码,在游戏退出之前循环执行的代码。这段代码在每次循环中都要:在屏幕上绘制物体(或场景人物随便什么)、处理游戏的逻辑过程(如:物体的移动、人工智能等等)、处理Windows的消息等等。基本上就是这样了。
Creating Your First Project (创建你的第一个项目)
译者:嗯,这部分我就不用译了吧,这可是基础的东西。不过还是说说初学者容易忽略的一点:一定要把你的DX SDK的Include目录和Lib目录的路径添加到VC的目录设置列表中去,而且不要把Include和Lib的地方放错了,而且还要放在第一位。还要把d3d8.lib添加到项目设置的Lib列表中,否则编译不了。
Okay, that’s enough theory lets get started. Follow the step-by-step guide below to create your first DirectX Graphics project.
下面就是本章的例子了,好好研究吧,不难。
#include <d3d8.h>
LPDIRECT3D8 g_pD3D = NULL;
LPDIRECT3DDEVICE8 g_pD3DDevice = NULL;
HRESULT InitialiseD3D(HWND hWnd)
{
//First of all, create the main D3D object. If it is created successfully we
//should get a pointer to an IDirect3D8 interface.
g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if(g_pD3D == NULL)
{
return E_FAIL;
}
//Get the current display mode
D3DDISPLAYMODE d3ddm;
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
{
return E_FAIL;
}
//Create a structure to hold the settings for our device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
//Fill the structure.
//We want our program to be windowed, and set the back buffer to a format
//that matches our current display mode
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
d3dpp.BackBufferFormat = d3ddm.Format;
//Create a Direct3D device.
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,
&g_pD3DDevice)))
{
return E_FAIL;
}
return S_OK;
}
void Render()
{
if(g_pD3DDevice == NULL)
{
return;
}
//Clear the back buffer to a green colour
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
//Begin the scene
g_pD3DDevice->BeginScene();
//Rendering of our game objects will go here
//End the scene
g_pD3DDevice->EndScene();
//Filp the back and front buffers so that whatever has been rendered on the
//back buffer will now be visible on screen (front buffer).
g_pD3DDevice->resent(NULL, NULL, NULL, NULL);
}
void CleanUp()
{
if(g_pD3DDevice != NULL)
{
g_pD3DDevice->Release();
g_pD3DDevice = NULL;
}
if(g_pD3D != NULL)
{
g_pD3D->Release();
g_pD3D = NULL;
}
}
void GameLoop()
{
//Enter the game loop
MSG msg;
BOOL fMessage;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
while(msg.message != WM_QUIT)
{
fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
if(fMessage)
{
//Process message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//No message to process, so render the current scene
Render();
}
}
}
//The windows message handler
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_KEYUP:
switch (wParam)
{
case VK_ESCAPE:
//User has pressed the escape key, so quit
DestroyWindow(hWnd);
return 0;
break;
}
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//Application entry point
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
//Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"DX Project 1", NULL};
RegisterClassEx(&wc);
//Create the application's window
HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1",
WS_OVERLAPPEDWINDOW, 50, 50, 500, 500,
GetDesktopWindow(), NULL, wc.hInstance, NULL);
//Initialize Direct3D
if(SUCCEEDED(InitialiseD3D(hWnd)))
{
//Show our window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
//Start game running: Enter the game loop
GameLoop();
}
CleanUp();
UnregisterClass("DX Project 1", wc.hInstance);
return 0;
}
你会得到一个绿色背景的窗户(读者:是窗口,白痴),虽然看起来不怎么样,但至少是一个好的开始,不是吗?好地开头,就是成功地半拉!(读者:… …)
(译者:嗯,那个老外用WinXP?我看还是Win2K好… …)
(读者:切~~别在那废话。)
WinMain
此乃Win32程序的入口点,代码会从这里开始执行。这是我们注册、创建、显示窗口的地方。然后,我们要初始化Direct3D并进入游戏循环(Game Loop)。
WinProc
这是应用程序的消息处理过程。Windows发给我们的程序的消息,都要有它处理。注意我们上面的例子,我们处理了两种消息:WM_DESTROY(结束程序) 和 WM_KEYUP(有按键被按下)。其他的消息我们都交给默认消息处理过程DefWindowProc处理了。
g_pD3D
这是指向IDirect3D8接口的指针,我们得通过它来创建Direct3D设备接口。
g_pD3DDevice
这是 IDirect3DDevice8(D3D 设备) 的接口的指针,它实际上代表了你的硬件3D卡。
InitialiseD3D
我们的这个函数是用来初始化Direct3D的。首先,创建IDirect3D8对象,通过这个对象我们得到了当前屏幕的显示模式。然后,根据刚刚我们获取的信息(显示模式),创建了兼容的设备。
译者:因为一些显示卡的显示模式并不相同,所以,我们的程序要在每块显卡上都能执行,就要了解这块显卡的显示模式等等一些信息。然后,根据这些信息,创建我们的D3D设备。
GameLoop
这就是上面提到的“游戏循环”的具体实现了。当初始化结束后,它就开始了。
他会检测有没有Windows的消息,没有的话,就调用Render来绘制屏幕。
Render
首先,我们清除了后缓冲区准备作画。然后,调用了BeginScene函数来告知DX我们要作画了。这时,我们就可以作画了(教程2)。结束了绘制,我们调用EndScene来告知DX我们画完了。最后,我们调用了Present来完成关键的一步:翻动后缓冲区到前缓冲区(屏幕)。这时,用户就能看到我们画的东西了。
CleanUp
我们在此做清洁工作:释放所有的被创建的对象。因为程序要推出了。
Summary (摘要)
译者:嗯,好了,这就是我们教程的第一章了。并不难,不是吗?看起来虽然字不多,翻译起来,蛮累呢!
研究明白了的话,看下一章吧!下一章我们就会真正的画一些东西了!呵呵,真是令人期待呢… …
也让老外说几句吧:
Ok, that’s it for the first tutorial. I know that the finished program wasn’t the most spectacular thing in the world, but just wait for the next tutorial when we will be drawing some shapes!
欢迎光临 下沙论坛 (http://bbs.xiasha.cn/) | Powered by Discuz! X3.3 |