第一步:程序入口函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
主函数中主要实现以下功能:
初始化窗口对象,并注册
//初始化窗口对象
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.lpszClassName = "MainClass";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
//初始化参数完毕,注册该对象
RegisterClassEx(&wc);
窗口对象初始化完毕后,创建窗口句柄
HWND window = CreateWindow(wc.lpszClassName, APPTitle.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, screenWidth, screenHeight, NULL, NULL, hInstance, NULL);
函数原型:
CreateWindow(lpClassName, lpWindowName, dwStyle, x, y,nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
lpClassName :类型LPCTSTR,指定窗口类名。
lpWindowName :类型LPCTSTR,窗口标题显示在标题栏中。
dwStyle :窗口创建的风格。具体窗口样式见《笔记-窗口样式类型》
x:窗口左上角的位置x
y:窗口左上角的位置y
nWidth:窗口大小
nHeight:窗口大小
hWndParent:父窗口句柄
hMenu:菜单句柄
hInstance:窗口实例
lpParam:需要传递的参数
窗口句柄创建完毕,需要将该窗口显示
//显示并更新窗口
ShowWindow(window,nCmdShow);
UpdateWindow(window);
窗口显示完毕,此时窗口已经构建完成,开始接收来自游戏的消息,从消息队列中取出消息,并进入无限循环
//接收消息
MSG message;
while (!gameOver)
{
if (PeekMessage(&message, window, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
Game_Run(window);
}
Game_End();
第二步:游戏初始化
游戏初始化过程主要是初始化Direct3D,以及外设,同时,初始化表面
初始化Direct3D的版本
//根据版本号初始化Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
设置Direct3D结构体的参数
//声明参数结构体
D3DPRESENT_PARAMETERS d3dpp;
//清空参数 这一步很关键,需要有这一个清空过程,否则的话,将会出现不能创建设备的问题
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullScreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = hWnd;
参数设置完成后,需要创建Direct3D设备对象,如果返回值为D3D_OK,表示创建成功
HRESULT result = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
初始化外设,本项目中主要使用了键盘和鼠标两个,Direct3D只支持微软的xbox的遥控杆,需要的话引入xinput.h和xinput.lib库文件
初始化输入对象
//初始化输入对象
HRESULT result = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dinput, NULL);
GetModuleHandle()函数,用来获取当前程序的实例hInstance的句柄,因为该句柄通常只在WinMain中会出现。
第二个参数为版本号,版本号存在于dinput.h中,需要重新宏定义一下,#define DIRECTINPUT_VERSION 0x0800,定义时,要将该宏定义放在文件的最上方,防止出现宏重定义。
第三个参数为DirectInput版本的引用标识符。这个值目前版本用的是IID_IDirectInput8。
第四个参数是指向主DirectInput对象指针的指针(注意是双重指针)。
最后一个参数总是为NULL
创建输入对象后,需要创建输入设备,以及设置设备
创建键盘设备
//创建设备
dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL);
//设置数据格式
dikeyboard->SetDataFormat(&c_dfDIKeyboard);
//设置协同级别
dikeyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
//获取设备
dikeyboard->Acquire();
创建鼠标设备
//初始化鼠标
dinput->CreateDevice(GUID_SysMouse, &dimouse, NULL);
//设置数据格式
dimouse->SetDataFormat(&c_dfDIMouse);
//设置协同级别
dimouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
//获取设备
dimouse->Acquire();
d3ddev->ShowCursor(false);
设备初始化完成后,需要从文件中读取图片精灵
//声明图片类表面
LPDIRECT3DSURFACE9 image = NULL;
D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info);
if (result != D3D_OK)
{
return NULL;
}
//创建离屏表面
result = d3ddev->CreateOffscreenPlainSurface(info.Width, info.Height, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &image, NULL);
if (result != D3D_OK)
{
return NULL;
}
result = D3DXLoadSurfaceFromFile(image, NULL, NULL, fileName.c_str(), NULL, D3DX_DEFAULT, D3DCOLOR_XRGB(0, 0, 255), NULL);
if (result != D3D_OK)
return NULL;
return image;
首先要引入d3dx9.h这个头文件,这个文件在vs2013在带的SDK库中是不存在的,因此也需要下载Direct9.0c SDK (2010.6)这个版本的SDK,同时,设置项目属性,将包含目录以及库引用目录指向安装好的Direct SDK文件。
该段代码,首先建立一个image的表面,同时声明一个info来获取文件中图片的信息,通过该图片的信息,创建一个image离屏表面。
D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info);
result = d3ddev->CreateOffscreenPlainSurface(info.Width, info.Height, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &image, NULL);
离屏表面创建完成后,将文件图片读取到离屏表面中,之后直接返回该离屏表面。
result = D3DXLoadSurfaceFromFile(image, NULL, NULL, fileName.c_str(), NULL, D3DX_DEFAULT, D3DCOLOR_XRGB(0, 0, 255), NULL);
两个精灵的离屏表面都创建好,通过GetBackBuffer函数,可以获得真实后台的指针地址。
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
第三步:游戏开始运行
游戏开始运行后,首先需要获取的是键盘或者鼠标的状态以及按键
dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state);
dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);
DIK_A 表示按键A,DIKEYBOARD_A表示的是地址映射单元
第四步:绘制表面,并渲染
//绘制表面
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 src)
{
//
D3DSURFACE_DESC desc;
//通过GetDesc可以获得源位图的高度和宽度,由此可以绘制一个矩形
src->GetDesc(&desc);
//创建绘制的矩形
RECT src_Rect = {0,0,(long)desc.Width,(long)desc.Height};
RECT dest_Rect;
dest_Rect.left = (long)x;
dest_Rect.top = (long)y;
dest_Rect.right = (long)x + desc.Width;
dest_Rect.bottom = (long)y + desc.Height;
//绘制表面到源表面
d3ddev->StretchRect(src, &src_Rect, dest, &dest_Rect, D3DTEXF_NONE);
}
//使用colorfill来清空表面上面的内容,这个主要是针对真实后台的缓冲区
d3ddev->ColorFill(backBuffer, NULL, D3DCOLOR_XRGB(255, 255, 255));
//clear清空屏幕上面的内容
//d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);
//开始渲染
if (d3ddev->BeginScene())
{
//将离屏表面上的内容复制到后台缓冲区中
DrawSurface(backBuffer, bomb.x, bomb.y, bomb_suf);
//将离屏表面中的内容复制到后台缓冲区中
DrawSurface(backBuffer, bucket.x, bucket.y, bucket_suf);
//结束渲染
d3ddev->EndScene();
//显示
d3ddev->Present(NULL, NULL, NULL, NULL);
}
源码下载地址:http://download.csdn.net/detail/l_shiwei/9509600