Window Direct3D游戏开发入门——Bomb游戏

第一步:程序入口函数
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

你可能感兴趣的:(函数,对象,游戏开发,Direct3D,winapi)