Win32实现简单游戏引擎

来源:互联网 发布:c语言数据类型 编辑:程序博客网 时间:2024/04/25 19:30

通过win32实现了简单的游戏引擎,通过模拟游戏引擎的加载、图形渲染以及游戏退出的操作来理解游戏引擎的基本原理。
文中分别使用了GDI以及Direct3D来实现,希望对你有所帮助。

// MyEngine.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include "MyEngine.h"#include <time.h>#include <d3d9.h>#pragma comment(lib,"D3d9.lib")#define MAX_LOADSTRING 100// 全局变量: HINSTANCE hInst;                                // 当前实例WCHAR szTitle[] = L"游戏引擎 - FPS:0";               // 标题栏文本WCHAR szWindowClass[] = L"MyGameEngine";         // 主窗口类名HWND  g_hMainWnd;TCHAR g_Key[256] = { 0 };       // 按键检测DWORD nWidth = 0;               // 保存当前窗口的宽DWORD nHeight = 0;              // 保存当前窗口的高LPDIRECT3D9 g_pD3D = NULL;LPDIRECT3DDEVICE9 g_pDev = NULL;LPDIRECT3DSURFACE9 g_pBackBuffer = NULL;LPDIRECT3DSURFACE9 g_pSurface = NULL;#define KEYDOWN(x) g_Key[x] DWORD GetRand(DWORD dwBase);    // 获取随机数// 使用GDI绘图测试DWORD OnGameInit_GDI();         // 模拟游戏引擎的加载DWORD OnGameRender_GDI();       // 模拟游戏进行画面的渲染DWORD OnGameOver_GDI();         // 模拟游戏退出时的清理工作// 使用Direct3D测试bool OnGameInit_D3D();          // 模拟游戏引擎的加载bool OnGameRender_D3D();        // 模拟游戏进行画面的渲染DWORD OnGameOver_D3D();         // 模拟游戏退出时的清理工作LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);int APIENTRY wWinMain(_In_ HINSTANCE hInstance,                     _In_opt_ HINSTANCE hPrevInstance,                     _In_ LPWSTR    lpCmdLine,                     _In_ int       nCmdShow){    WNDCLASSEXW wcex;    wcex.cbSize = sizeof(WNDCLASSEX);    wcex.style = CS_HREDRAW | CS_VREDRAW;    wcex.lpfnWndProc = WndProc;    wcex.cbClsExtra = 0;    wcex.cbWndExtra = 0;    wcex.hInstance = hInstance;    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYENGINE));    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);    wcex.lpszMenuName = NULL;    wcex.lpszClassName = szWindowClass;    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));    RegisterClassExW(&wcex);    hInst = hInstance; // 将实例句柄存储在全局变量中    HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,        600, 300, 800, 600, nullptr, nullptr, hInstance, nullptr);    if (!hWnd) return 0;    g_hMainWnd = hWnd;    ShowWindow(hWnd, nCmdShow);    UpdateWindow(hWnd);    //OnGameInit_GDI();    if (!OnGameInit_D3D())return 0;    DWORD dwFPS = 0;                        // 帧率    DWORD dwLastTime = GetTickCount();      // 上一次渲染时间    DWORD dwNowTime = 0;                    // 当前渲染时间    DWORD dwLastFPSTime = dwLastTime;       // 保存最后次计算FPS的时间    DWORD dwDelta = 0;                      // 每帧的运行时间    LARGE_INTEGER nLast;                    // 精确定时    LARGE_INTEGER nNow;    LARGE_INTEGER _animationInterval;    LARGE_INTEGER freq;    QueryPerformanceFrequency(&freq);    _animationInterval.QuadPart = freq.QuadPart*1.0 / 60;    QueryPerformanceCounter(&nLast);    MSG msg = { 0 };    while (TRUE)// 此处 PeekMessage 与 GetMessage    {        if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))// 无论消息队列中是否有消息,都进行探测        {            if (WM_QUIT == msg.message)                break;            TranslateMessage(&msg);            DispatchMessage(&msg);        }        QueryPerformanceCounter(&nNow);        dwFPS++;        if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)        {            //OnGameRender_GDI();            OnGameRender_D3D();            nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % _animationInterval.QuadPart);            if (dwFPS)            {                char szTitle[32];                sprintf(szTitle, "游戏引擎 - FPS:%d", dwFPS);                SetWindowTextA(g_hMainWnd, szTitle);                dwFPS = 0;            }        }        Sleep(1);        // 使用GetTickCount控制帧率//      OnGameRender_GDI();//      OnGameRender_D3D();//      dwFPS++;//      dwNowTime = GetTickCount();//      dwDelta = dwNowTime - dwLastTime; // 计算本帧的运行时间//      // 控制每一帧在10ms左右//      if (dwDelta < 20)//      {//          Sleep(20 - dwDelta);//      }// //      if ((dwNowTime - dwLastFPSTime) > 1000)//      {//          char szTitle[32];//          if (dwFPS)//          {//              sprintf(szTitle, "游戏引擎 - FPS:%d", dwFPS);//              SetWindowTextA(g_hMainWnd, szTitle);//              dwLastFPSTime = dwNowTime;//              dwFPS = 0;//          }//      }//      dwLastTime = dwNowTime;           // 保存上一次更新的时间     }    //OnGameOver_GDI();    OnGameOver_D3D();    return (int) msg.wParam;}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    switch (message)    {    case WM_CLOSE:    case WM_DESTROY:        PostQuitMessage(0);        break;    case WM_KEYDOWN:        g_Key[wParam] = 1;        break;    case WM_KEYUP:        g_Key[wParam] = 0;        break;    default:        return DefWindowProc(hWnd, message, wParam, lParam);    }    return 0;}// 计算并获取0~dwBase的随机值DWORD GetRand(DWORD dwBase){    DWORD result = 0;    __asm {        rdtsc       // 取CPU执行的指令数        mov result,eax    }    return result % dwBase;}DWORD OnGameInit_GDI(){    RECT rc;    GetWindowRect(g_hMainWnd, &rc);    nWidth = rc.right - rc.left;    nHeight = rc.bottom - rc.top;    return 0;}DWORD OnGameRender_GDI(){    if (KEYDOWN(VK_ESCAPE))    {        SendMessage(g_hMainWnd, WM_CLOSE, 0, 0);    }    HDC hdc = GetDC(g_hMainWnd);    HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));    SelectObject(hdc, hPen);    MoveToEx(hdc, GetRand(nWidth), GetRand(nHeight), NULL);    LineTo(hdc, GetRand(nWidth), GetRand(nHeight));    DeleteObject(hPen);    ReleaseDC(g_hMainWnd,hdc);    return 0;}DWORD OnGameOver_GDI(){    return 0;}bool OnGameInit_D3D(){    // 初始化Direct3D    g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);    if (NULL == g_pD3D)    {        MessageBox(g_hMainWnd, _T("Init Direct3D failed!"), _T("Error"), MB_OK | MB_ICONERROR);        return false;    }    RECT rc;    GetWindowRect(g_hMainWnd, &rc);    nWidth = rc.right - rc.left;    nHeight = rc.bottom - rc.top;    D3DDISPLAYMODE displayMode;    if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode)))        return false;    // 设置Direct3D的属性    D3DPRESENT_PARAMETERS d3dpp;    ZeroMemory(&d3dpp, sizeof(d3dpp));    d3dpp.Windowed = TRUE;    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    d3dpp.BackBufferFormat = displayMode.Format;    d3dpp.BackBufferCount = 1;    d3dpp.BackBufferWidth = nWidth;    d3dpp.BackBufferHeight = nHeight;    d3dpp.hDeviceWindow = g_hMainWnd;    d3dpp.EnableAutoDepthStencil = TRUE;    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;    // 按要求建立Direct3D设备    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hMainWnd,        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pDev)))    {        int err1 = E_FAIL;        int err = GetLastError();        MessageBox(g_hMainWnd, _T("CreateDevice failed!"), _T("Error"), MB_OK | MB_ICONERROR);        return false;    }    //D3DERR_DEVICELOST D3DERR_INVALIDCALL D3DERR_NOTAVAILABLE D3DERR_OUTOFVIDEOMEMORY    srand(time(NULL));    // 将背景色设置为黑色    g_pDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);    // 获取后台渲染指针    if (FAILED(g_pDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackBuffer)))        return false;    // 建立离屏表面 (类似GDI双缓存)    if(FAILED(g_pDev->CreateOffscreenPlainSurface(nWidth,nHeight,displayMode.Format,        D3DPOOL_DEFAULT,&g_pSurface,NULL)))        return false;    return true;}bool OnGameRender_D3D(){    if (KEYDOWN(VK_ESCAPE))        SendMessage(g_hMainWnd, WM_CLOSE, 0, 0);    // 确认Direct3D设备    if (!g_pDev) return false;    // 开始渲染    if (g_pDev->BeginScene())    {        // 将离屏幕表面填充随机颜色        int r = rand() % 255;        int g = rand() % 255;        int b = rand() % 255;        g_pDev->ColorFill(g_pSurface, NULL, D3DCOLOR_XRGB(r, g, b));        // 画离屏表面到后台g_psurface的指定区域        RECT rc;        rc.left = rand() % nWidth / 2;        rc.right = rc.left + rand() % nWidth / 2;        rc.top = rand() % nHeight;        rc.bottom = rc.top + rand() % nHeight / 2;        g_pDev->StretchRect(g_pSurface, NULL, g_pBackBuffer, &rc, D3DTEXF_NONE);        // 定制渲染        g_pDev->EndScene();        // 完成后台画面与前台的交互        g_pDev->Present(NULL, NULL, NULL, NULL);    }    return 0;}DWORD OnGameOver_D3D(){    return 0;}

源码VS2015
本文难免有所错误,如有问题欢迎留言。

原创粉丝点击