小菜鸟的C++游戏编程学习日记(二)
作者:杨帆
参考书籍:Beginning Game ProGramming(中文版)
学习时间:2016.7.27
#include <windows.h>
#include <iostream>
#include <time.h> //include header source
using namespace std;
const string APPTITLE = "Game Loop";
HWND hWnd;
HDC hDc;
bool gameover = false;
//local and draws a bitmap from file and then free the memory
//(not really suitable for a game loop but it's self contained)
void DrawBitmap(char* filename,int x,int y)
{
//load the bitmap image
HBITMAP image = (HBITMAP)LoadImage(0, "000.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//read the bitmap's properties
BITMAP bmp;
GetObject(image, sizeof(BITMAP), &bmp);
//creat a device context for the bitmap
HDC hdcImage = CreateCompatibleDC(hDc);
SelectObject(hdcImage, image);
//draw the bitmap to the window (bit block transfer)
BitBlt(
hDc, //destination device context
x, y, //x,y location on destination
bmp.bmWidth, bmp.bmHeight, //width,height of source bitmap
hdcImage, //source bitmap device context
0, 0, //start x,y on source bitmap
SRCCOPY //bit method
);
//delete the device context and bitmap
DeleteDC(hdcImage);
DeleteObject((HBITMAP)image);
}
//startup and loading code goes here
bool GameInit()
{
//start up the random number generator
srand((unsigned)time(NULL));
return true;
}
//update function called from inside game loop
void GameRun()
{
if (gameover == true)
{
return;
}
//get the drawing surface
RECT rect;
GetClientRect(hWnd, &rect);
//draw bitmap at random location
int x = rand() % (rect.right - rect.left);
int y = rand() % (rect.bottom - rect.top);
DrawBitmap("000.bmp", x, y);
}
//shut down code
void GameEnd()
{
//free the device
ReleaseDC(hWnd,hDc);
}
//window callback function
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
switch (message)
{
case WM_DESTROY:
gameover = true;
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
//register the window
ATOM MyRegisterWindowClass(HINSTANCE hInstance)
{
// creat a window class struct
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.lpszClassName = APPTITLE.c_str();
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClassEx(&wc);
}
//helper function to create the window and refresh it
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
//creat new window
hWnd = CreateWindow(
APPTITLE.c_str(), //ClassName
APPTITLE.c_str(), //WindowName
WS_OVERLAPPEDWINDOW, //style
CW_USEDEFAULT, CW_USEDEFAULT, //x,y position in window (use default)
800, 500, //window size
NULL, NULL, //WndParent hMenu
hInstance, //Window instance
NULL //lParam
);
//was here an error creating the window
if (!hWnd)
{
return 0;
}
//display the window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//get device context for drawing
hDc = GetDC(hWnd);
return 1;
}
//Entry point function
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
//creat window
MyRegisterWindowClass(hInstance);
if (!InitInstance(hInstance,nCmdShow))
{
return 0;
}
//initialize the game
if (!GameInit())
{
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
GameRun();
}
//free game resource
GameEnd();
return msg.wParam;
}
这里对比昨天主要是对消息循环进行了新的处理,使得游戏过程有了一个完整的循环过程。并且藉此和之前看过的一点视频学习了关于贴图的知识,利用之前有的资源写了另一份代码。效果如下(没错就是会动的):