本系列文章由 net_assassin 编写,转载请注明出处。
http://blog.youkuaiyun.com/net_assassin/article/category/1100363
作者:net_assassin 邮箱: net_assassin@hotmail.com 期待着与志同道合的朋友们相互交流
windows编程比我们在之前所讲的要博大精深的多,我们所需关注的只是能够让DirectX启动起来的有限代码。一个“真正”的Windows应用程序应该有一个菜单、一个状态栏、一个工具栏及许多对话框,这也是一般的Windows编程书籍又大又后的原因。我们这里要关注的是游戏的创建而不是将大量篇幅花费在操作系统的逻辑上。
我们先来看标准的 WinMain函数:
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
if(!InintInstance(hInstance,nCmdShow))
return FALSE;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
这个版本的WinMain 仅有一个问题:它没有一个连续的循环,只有一个有限的循环用于处理任何尚未处理的消息,然后退出。(while那一行)。
实时游戏循环


1.GetMessage将等到有合适的消息时才返回,而PeekMessage只是撇一下消息队列。
2.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。
在Windows的内部,GetMessage和PeekMessage执行着相同的代码。而两者最大的不同之处则体现在没有任何消息返回到应用程序的情况下。在此种情况下,PeekMessage会返回一个空值到应用程序,GetMessage会在此时让应用程序休眠。
游戏循环
bool gameover = false;
whlie(!gameover)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
//hand any event message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//process game loop
Game_Run();
}
一个GameLoop项目:

/**
Beginning Game Programming, Third Edition
Chapter 2
GameLoop project
**/
#include <windows.h>
#include <iostream>
#include <time.h>
using namespace std;
const string APPTITLE = "Game Loop";
HWND window;
HDC device;
bool gameover = false;
/**
** Loads and draws a bitmap from a file and then frees the memory
** 必须承认的是这个函数很慢,这个函数适合于装载完整的背景图片
** 或者只需将图片绘制一次的小位图。这个函数将位图文件装入内存
**/
void DrawBitmap(char *filename, int x, int y)
{
//load the bitmap image
HBITMAP image = (HBITMAP)LoadImage(0,"c.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
//read the bitmap's properties
BITMAP bm;
GetObject(image, sizeof(BITMAP), &bm);
//create a device context for the bitmap
HDC hdcImage = CreateCompatibleDC(device);
SelectObject(hdcImage, image);
//draw the bitmap to the window (bit block transfer)
BitBlt(
device, //destination device context
x, y, //x,y location on destination
bm.bmWidth, bm.bmHeight, //width,height of source bitmap
hdcImage, //source bitmap device context
0, 0, //start x,y on source bitmap
SRCCOPY); //blit method
//delete the device context and bitmap
DeleteDC(hdcImage);
DeleteObject((HBITMAP)image);
}
/**
** Startup and loading code goes here
**/
bool Game_Init()
{
//start up the random number generator
srand(time(NULL));
return 1;
}
/**
** Update function called from inside game loop
**/
void Game_Run()
{
if (gameover == true) return;
//get the drawing surface
RECT rect;
GetClientRect(window, &rect);
//draw bitmap at random location
int x = rand() % (rect.right - rect.left);
int y = rand() % (rect.bottom - rect.top);
DrawBitmap("c.bmp", x, y);
}
/**
** Shutdown code
**/
void Game_End()
{
//free the device
ReleaseDC(window, device);
}
/**
** Window callback function
**/
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
gameover = true;
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
/**
** MyRegiserClass function sets program window properties
**/
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE.c_str();
wc.hIconSm = NULL;
//set up the window with the class info
return RegisterClassEx(&wc);
}
/**
** Helper function to create the window and refresh it
**/
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
//create a new window
window = CreateWindow(
APPTITLE.c_str(), //window class
APPTITLE.c_str(), //title bar
WS_OVERLAPPEDWINDOW, //window style
CW_USEDEFAULT, //x position of window
CW_USEDEFAULT, //y position of window
640, //width of the window
480, //height of the window
NULL, //parent window
NULL, //menu
hInstance, //application instance
NULL); //window parameters
//was there an error creating the window?
if (window == 0) return 0;
//display the window
ShowWindow(window, nCmdShow);
UpdateWindow(window);
//get device context for drawing
device = GetDC(window);
return 1;
}
/**
** Entry point function
**/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
//create window
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow)) return 0;
//initialize the game
if (!Game_Init()) return 0;
// main message loop
while (!gameover)
{
//process Windows events
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//process game loop
Game_Run();
}
//free game resources
Game_End();
return msg.wParam;
}