文档库 最新最全的文档下载
当前位置:文档库 › 游戏编程 第一部 基础篇

游戏编程 第一部 基础篇

二、基于动画原理的提高
首先要介绍的第一位主角是 Windows 编程中的必要元素: RECT 。是英语 rectangle 的简写,意思是矩形。它有什么用呢?我们在上面不是讲到了动作的分解动作吗?我们看右图:

#define m_Width 32 // 每个动作的 宽度
#define m_Height 48 // 每个动作的 高度

void ShowThePic()
{
static RECT rect; // 矩形对象,用于精确定位所要的当前动作
static int CurrentFrame = 0; // 当前动作的编号
static int Direction = 0; // 当前的方向
rect.top = Direction; rect.bottom = (Direction+1)*m_Height; // 对当前矩形的大小定义,数学的问题哦
rect.left = CurrentFrame; rect.right = (CurrentFrame+1)*m_Width; // 根据英文的意思也可以知道在给谁赋值
BltPicToScreen(); // 一个伪函数,作用是将当前矩形内的图形复制到屏幕上。
CurrentFrame++;
if( CurrrentFrame==3 )
CurrentFrame = 0; // 这个步骤能够保证动作的循环
}

之所以要采用 static 静态变量,是因为我们这个函数程序要循环运行。如果直接写个 int 的话,每次执行都会被赋回原值 0,那么图片就不会变了。

上面这段代码其实并不是那么理想。因为程序自己在那儿一个劲地运行,完全没有我们控制的份儿。别急!来看下面这份修改过的伪代码:

#define m_Width 32 // 每个动作的 宽度
#define m_Height 48 // 每个动作的 高度

void ShowThePic()
{
static RECT rect; // 矩形对象,用于精确定位所要的当前动作
static int CurrentFrame = 0; // 当前动作的编号
static int Direction = 0; // 当前的方向
rect.top = Direction; rect.bottom = (Direction+1)*m_Height; //对当前矩形的大小定义,数学的问题哦
rect.left = CurrentFrame; rect.right = (CurrentFrame+1)*m_Width; //根据英文的意思也可以知道在给谁赋值
BltPicToScreen(); // 一个伪函数,作用是将当前矩形内的图形复制到屏幕上。

if( LeftArrowDown() ) // 如果 左箭头 被按下
{
Direction = 1; // 赋值方向为 1
CurrentFrame++;
}

if( RightArrowDown() )
{
Direction = 3;
CurrentFrame++;
}

if( UpArrowDown() )
{
Direction = 2;
CurrentFrame++;
}

if( DownArrowDown() )
{
Direction = 0;
CurrentFrame++;
}

if(CurrrentFrame==3)
CurrentFrame = 0; // 这个步骤能够保证动作的循环
}



三、游戏的基石: 窗口 的建立

我们来看,一个基本的 Windows 程序是一个窗口对吧:)我们所玩的游戏,其实也是有窗口的,只不过是看不见的,而且被 DirectDraw 掩盖了而已。那么,如何创建一个窗口呢?我

们来看:

BOOL Init(HINSTANCE hInst, int nCmdShow)
{
HWND hWnd; // 窗口的句柄,就是一个储存窗口的对象
WNDCLASS WndClass; // 用于注册窗口的对象

WndClass.style = CS_HREDRAW | CS_VREDRAW; // 定义窗口的类型
WndClass.lpfnWndProc = WinProc; // 指定了窗口消息的处理函数 ** 关键!
WndClass.cbClsExtra = 0; // 没有特定意义
WndClass.cbWndExtra = 0; // 没有特定意义
WndClass.hInstance = hInst; // 窗口的实例
WndClass.hIcon = LoadIcon(hInst, IDI_APPLICATION); // 指定窗口的图标
WndClass.hCursor = LoadCursor(hInst, IDC_ARROW); // 指定程序的指针
WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 指定背景色为黑色
WndClass.lpszMenuName = NULL; // 指定菜单为无,游戏不需要
WndClass.lpszClassName = "GDIM_GAME_ENGINE"; //这个程序注册的名字
RegisterClass(&WndClass); // 注册程序

hWnd = CreateWindowEx(WS_EX_TOPMOST, "GDIM_GAME_ENGINE", "GDIM_GAME", WS_POPUP, 112, 84, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInst, NULL);
// 这段代码就是实现了一个窗口的创建
// 我们可以通过来检测是否创建成功。如果失败将返回一个 FALSE 的值。
if(!hWnd) return FALSE;
ShowWindow(hWnd, nCmdShow); // 显示窗口
UpdateWindow(hWnd); // 更新窗口
}

好了,到这儿呢,我们就成功的创建了一个窗口。我们回头看我注了“**”的地方,关于这个函数,我们得写个同名函数来处理 Windows 的消息。呵呵,不好意思,再看一个函数:

BOOL bActive = FALSE; // 用于判断程序是否运行的变量

long PASCAL WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_ACTIVATE:
bActive = TRUE; // 当程序被激活时,赋值 TRUE
break;
case WM_SETCURSOR:
SetCursor(NULL); // 设定鼠标为不显示
return TRUE;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE: // 处理按下 ESC 键的反应
PostMessage(hWnd, WM_CLOSE, 0, 0); // 发送一个关闭窗口的命令
break;
}
break;
case WM_DESTROY: // 在窗口即将销毁时的反应
PostQuitMessage(0); // 发送一个结束的消息,必须的!
break;
}
return DefWindowProc(hWnd, message, wParam, lParam); // 一些没有像上面一样具体定义的消息的处理
}

这个函数就是用来处理 Windows 的消息的,是一个标准程序必要的。

再来最后一个重要的函数。不好意思哦,实在是不想这么写,但是想想,在这个函数结束后,你就可以实现一个具体的窗口

了哦:)

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // 定义一个消息的对象

if(!Init(hInst, nCmdShow)) return FALSE; // 还记得上面的那个函数吗?

while(1) // 程序的循环
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) // 不要特别注意的
{
if(!GetMessage(&msg, NULL, 0, 0 ))
return msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(bActive) // 就是上面的“程序是否激活”的变量判断
{
ShowThePic(); // 显示人物图片的函数,上节的内容,就是整合在这儿的!
}
else WaitMessage(); // 没有消息时,就等消息:)
}
}



相关文档