win32 游戏编程.ppt
《win32 游戏编程.ppt》由会员分享,可在线阅读,更多相关《win32 游戏编程.ppt(82页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、WIN32 游戏编程游戏编程Author:景落西轩:景落西轩C+数值类型bool(逻辑型)char(字符或8位整数)short(16位整数)int(16位或32位整数)long(32位整数)float(32位浮点数)double(64位浮点数)long double(80位浮点数)Tip:在整数数据类型前可加上unsigned表示为无符号数,数的范围可增大一倍。变量与常量所有变量定义的前面均可加上修饰符const表示它是常量,不能在程序中改变它的值。其实如果我们不打算在程序中改变某变量的值,我们就可以把它声明为常量以防止意外改动。我们还可加上修饰符static表示此变量是静态变量,这个要举一个
2、例子以方便说明:比如说在某一个函数内有这样一条定义:static int count=0;,那么程序执行前就会为count这个变量开辟一块固定的空间并把count的初值设为0。以后每次执行这个函数时,程序不会象普通变量那样重新为它分配空间,也就是不会改变它的位置和数值,换句话说,它的生命周期与整个程序一样。这样只要在函数中再加一句count=count+1即可统计这个函数执行了多少次。如果局部变量和全局变量重名,调用时会使用局部变量,如果一定要使用那个全局变量,调用时在变量名前加上:即可。这里建议大家尽量少用全局变量,因为它可能使程序变得混乱和难于调试。NAMESPACENamespace是一
3、个挺有趣的东西,它的引入是为了方便我们使用相同名字的变量、常量、类(在第二章我们会接触类)或是函数。一个Namespace是这样定义的:namespace xxx/xxx是是namespace的名字的名字在在这里可以像平常一里可以像平常一样定定义各种各种东西西以后要使用某个namespace中的东西,比如说xxx中的aaa,像这样:xxx:aaa即可。不过这样好像挺麻烦的-平白无故就多出了一个xxx:。于是有了using namespace xxx;这种语句,可以帮你省下这几个字符。记住,using namespace也只是在最紧挨它的一对和符号内起作用,在所有函数之外执行的这条语句才在整个文
4、件中有效。注意:namespace s1int a=0;namespace s2float a=0;void main()using namespace s1;using namespace s2;/a=a+1;/这句是句是错误的!因的!因为编译器此器此时无法确定无法确定a在哪个在哪个namespaces1:a=s2:a+1;/这样就是正确的就是正确的操作符与表达式在逻辑表达式中,用=表示相等,!=表示不等,比如说(4=5)为FALSE;大于等于用=表示,小于等于则是=。&表示逻辑与,|表示逻辑或,!表示逻辑非。(右移)非常好用,我们可以看到,左移和右移可以代替乘或除2的n次方的作用,而且这样
5、做可以节省不少CPU运算时间。在程序优化中这一种方法是十分重要的,例如a*9可用(a3)+a代替(注意,+运算比(指向的类的成员)2、!(逻辑非).(位取反)-(负号)+(加1)-(减1)&(变量地址)3、*(指针所指内容)sizeof(长度计算)4、*(乘)/(除)%(取模)5、+(加)-(减)6、(位右移)7、(小于)(大于)=(大于等于)8、=(等于)!=(不等于)9、&(位与)10、(位异或)11、|(位或)12、&(逻辑与)13、|(逻辑或)14、?:(?表达式)15、=+=-=(联合操作)预编译指令(1)#include 指令该指令指示编译器将xxx.xxx文件的全部内容插入此处。
6、若用括起文件则在系统的INCLUDE目录中寻找文件,若用括起文件则在当前目录中寻找文件,再在系统默认目录下搜索。(2)#define指令(3)#if、#else和#endif指令这些指令一般这样配合使用:#if defined(标识)/如果定如果定义了了标识要要执行的指令行的指令#else 要要执行的指令行的指令#endif在头文件中为了避免重复调用(比如说两个头文件互相包含对方),常采用这样的结构:#if!(defined XXX)/XXX为一个在你的程序中唯一的一个在你的程序中唯一的标识符,符,/每个每个头文件的文件的标识符都不符都不应相同。相同。/起起标识符的常符的常见方法是若方法是若头
7、文件名文件名为abc.h /则标识为abc_h#define XXX真正的内容,如函数声明之真正的内容,如函数声明之类#endif结构,联合和枚举结构构结构可以把不同变量变为一个变量的成员。例如:struct S/定定义结构构Sshort hi;/结构构S的第一个成的第一个成员short lo;/结构构S的第二个成的第二个成员;S s;/定定义S类型的型的变量量s然后我们就可以像s.hi和s.lo一样使用s的成员。联合合联合可以让不同变量共享相同的一块空间,举个例子:#include using namespace std;struct Sshort hi;short lo;union MIX
8、longl;Ss;charc4;void main()MIX mix;mix.l=100000;coutmix.s.hiendl;coutmix.s.lo;此时mix所在的内存位置的情况是这样的:图1.2枚枚举枚举的用处是迅速定义大量常量。例如:enum YEAR/可以可以给枚枚举起一个名字起一个名字january=1,/如果不加上如果不加上=1月份将依次月份将依次为0-11,不符合我,不符合我们平平时的的习惯,所以,所以/可以加上它。可以加上它。february,march,april,may,june,july,august,september,october,november,decem
9、ber;控制语句控制语句判断和跳转语句(if、goto)选择语句(switch)break语句循环语句(for、while)指针、数组与字符串指针、数组与字符串C+中的字符串其实也是指针的一种,因为并没有一种基本数据类型是字符串,所谓字符串实际是一个以/0(这叫做转义符,代表一个ASCII码为0的符号)作为结束标志的一个字符指针(char*),它实际上是一个字符数组extern的作用就是告诉编译器此变量会在其它程序文件中声明。把这种外部变量声明放在头文件里,再在每个文件中都包含这个头文件,然后只要在任何一个文件中声明变量,所有文件就都可以使用这个变量了。如果不加extern,各个文件使用的变量
10、虽然同名但内容不会统一。在各个文件中也需要先声明函数,之后才能使用它。不过这时用不着使用extern了。最后我们来看看一个简单的多文件程序的例子:/*-main.h-*/#if!(defined MAIN_H)#include using namespace std;extern int a;void print();#define MAIN_H#endif/*-main.cpp-*/#include main.hint a;void main()a=3;print();/*-function.cpp-*/#include main.hvoid print()couta;C+语法(以后再补)语
11、法(以后再补)基本基本WINDOWS程序程序代码见备注代码见备注WINMAIN函数int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)第一个参数hInstance是标识该应用程序的句柄。不过句柄又是什么呢?其实就是一个指向该程序所占据的内存区域的指针,它唯一地代表了该应用程序,Windows使用它管理内存中的各种对象。当然,它十分重要。在后面的初始化程序主窗口的过程中就需要使用它作为参数。第二个参数是hPrevInstance,给它NULL吧,这个参数只是为了保持
12、与16位Windows的应用程序的兼容性。第三个参数是lpCmdLine,是指向应用程序命令行参数字符串的指针。比如说我们运行test hello,则此参数指向的字符串为hello。最后一个参数是nCmdShow,是一个用来指定窗口显示方式的整数。关于窗口显示方式的种类,将在下面说明。注册窗口类注册窗口类 创建窗口前通常要填充一个窗口类WNDCLASS,并调用RegisterClass()对该窗口类进行注册。每个窗口都有一些基本的属性,如窗口标题栏文字、窗口大小和位置、鼠标、背景色,窗口消息处理函数(后面会讲这个函数)的名称等等。注册的过程就是将这些属性告诉系统,然后再调用CreateWind
13、ow()函数创建出窗口。(见备注)风格 含义CS_HREDRAW如果窗口宽度发生改变,重绘整个窗口CS_VREDRAW如果窗口高度发生改变,重绘整个窗口CS_DBLCLKS能感受用户在窗口中的双击消息CS_NOCLOSE禁用系统菜单中的关闭命令CS_SAVEBITS把被窗口遮掩的屏幕图像部分作为位图保存起来。当该窗口被移动时,Windows使用被保存的位图来重建屏幕图像创建窗口当窗口类注册完毕之后,我们就可以创建一个窗口,这是通过调用CreateWindow()函数完成的。窗口类中已经预先定义了窗口的一般属性,而在CreateWindow()中的参数中可以进一步指定窗口更具体的属性。下面举一个
14、例子来说明CreatWindow()的用法:显示和更新窗口显示和更新窗口窗口创建后,并不会在屏幕上显示出来,要真正把窗口显示在屏幕上,还得使用ShowWindow()函数,其原型如下:BOOL ShowWindow(HWND hWnd,int nCmdShow);参数hWnd就是要显示的窗口的句柄。nCmdShow是窗口的显示方式,一般给它WinMain()函数得到的nCmdShow的值就可以了。常用的窗口显示方式有:ShowWindow()函数的执行优先级不高,当系统正忙着执行其它的任务时窗口不会立即显示出来。所以我们使用ShowWindow()函数后还要再调用UpdateWindow(HW
15、ND hWnd);函数以保证立即显示窗口。消息循环 在WinMain()函数中,调用InitWindow()函数成功地创建了应用程序主窗口之后,就要启动消息循环,其代码如下:for(;)if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)if(msg.message=WM_QUIT)break;TranslateMessage(&msg);DispatchMessage(&msg);消息处理函数消息处理函数消息处理函数又叫窗口过程,在这个函数中,不同的消息将被switch语句分配到不同的处理程序中去。Windows的消息处理函数的原型是这样定义的:LRESULT CA
16、LLBACK WindowProc(HWND hwnd,/接收消息窗口的句柄接收消息窗口的句柄UINT uMsg,/主消息主消息值WPARAM wParam,/副消息副消息值1LPARAM lParam/副消息副消息值2);常用常用WINDOWS函数函数见备注见备注描绘游戏的画笔描绘游戏的画笔DirectDraw是DirectX的重要组成部分,它就像一支画笔,主要负责各种把各种图像显示在屏幕上,对Windows环境中的游戏非常重要。现在就让我们进入激动人心的DirectDraw部分吧。初始化DIRECTDRAW 为了告诉编译器我们需要使用DirectDraw,我们要在程序文件中#include
17、,并把ddraw.lib和dxguid.lib加入工程。记住,做完了这些工作后DirectDraw程序才能被正常编译。简介:见备注简介:见备注DIRECTDRAW对象对象如果要使用DirectDraw,必须创建一个DirectDraw对象,它是DirectDraw接口的核心。用DirectDrawCreateEx()函数可以创建DirectDraw对象,DirectDrawCreateEx()函数是在ddraw.h中定义的,它的原型如下:HRESULT WINAPI DirectDrawCreateEx(GUID FAR*lpGUID,LPVOID*lplpDD,REFIID iid,IUnk
18、nown FAR*pUnkOuter);参数介参数介绍见备注注设置控制级和显示模式设置控制级和显示模式DirectDrawCreate函数调用成功后,lpDD已经指向了一个DirectDraw对象,它是整个DirectDraw接口的最高层领导,以后的步骤都是在它的控制之下。我们用IDirectDraw7:SetCooperativeLevel()来设置DirectDraw程序对系统的控制级。它的原型如下:HRESULT SetCooperativeLevel(HWND hWnd,DWORD dwFlags)第一个参数是窗口句柄,我们给它hWnd,使DirectDraw对象与主窗口联系上。第二个
19、参数是控制级标志。这里使用DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN,表示我们期望DirectDraw以独占和全屏方式工作。控制级描述了DirectDraw是怎样与显示设备及系统作用的。DirectDraw控制级一般被用来决定应用程序是运行于全屏模式(必须与独占模式同时使用),还是运行于窗口模式。但DirectDraw的控制级还可设置如下两项:(1)允许按Ctrl+Alt+Del重新启动(仅用于独占模式,为DDSCL_ALLOWREBOOT)。(2)不允许对DirectDraw应用程序最小化或还原(DDSCL_NOWINDOWCHANGES)。普通的控制级(DDSCL_N
20、ORMAL)表明我们的DirectDraw应用程序将以窗口的形式运行。在这种控制级下,我们将不能改变显示器分辨率,或进行换页操作(这是一个重要的操作,在4.2节会介绍)。除此之外,我们也不能够调用那些会对显存产生激烈反应的函数,如第五章要讲的Lock()。当应用程序为全屏并且独占的控制级时,我们就可以充分的利用硬件资源了。此时其它应用程序仍可创建页面、使用DirectDraw或GDI的函数,只是无法改变显示模式。下一步我们使用IDirectDraw7:SetDisplayMode()来设置显示模式,其原形为:HRESULT SetDisplayMode(DWORD dwWidth,DWORD
21、dwHeight,DWORD dwBPP,DWORD dwRefreshRate,DWORD dwFlags);dwWidth and dwHeight用来设置显示模式的宽度和高度。dwBPP用来设置显示模式的颜色位数。dwRefreshRate设置屏幕的刷新率,0为使用默认值。dwFlags现在唯一有效的值是DDSDM_STANDARDVGAMODE。创建页面创建页面下一步是创建一个DirectDrawSurface对象。DirectDrawSurface对象代表了一个页面。你可以把页面想象为一张张可供DirectDraw描绘的画布。页面可以有很多种表现形式,它既可以是可见的,称为主页面(P
22、rimary Surface);也可以是作换页用的不可见页面,称为后台缓存(Back Buffer),在换页后,它成为可见(换页在4.2节会讲);还有一种始终不可见的,称为离屏页面(Off-screen Surface),它的作用是存储图像。其中,最重要的页面是主页面,每个DirectDraw应用程序都必须创建至少一个主页面,一般来说它就代表着我们的屏幕。创建一个页面之前,首先需要填充一个DDSURFACEDESC2结构,它是DirectDraw Surface Description的缩写,意思是DirectDraw的页面描述。它的结构非常庞大,这里只能作一个最简单的介绍。要注意的是在填充此
23、结构前一定要将其清空!下面是一个典型的主页面的页面描述:ddsd.dwSize=sizeof(ddsd);/给dwSize页面描述的大小面描述的大小ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;/有后台有后台缓存存ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;/为主主页面,有后台面,有后台缓存,有存,有换页链ddsd.dwBackBufferCount=1;/一个后台一个后台缓存存再看看一个普通表面的页面描述:ddsd.dwSize=sizeof(ddsd
24、);ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;/高、高、宽由我由我们指指定定ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;/这是离屏是离屏页面面ddsd.dwHeight=480;/高高ddsd.dwWidth=640;/宽页面描述填充完毕后,把它传递给IDirectDraw7:CreateSurface()方法即可创造页面。CreateSurface()的原形是:HRESULT CreateSurface(LPDDSURFACEDESC2 lpDDSurfaceDesc,LPDIRECTDRAWSURF
25、ACE FAR*lplpDDSurface,IUnknown FAR*pUnkOuter);CreateSurface()函数的第一个参数是被填充了页面信息的DDSURFACEDESC2结构的地址,此处为&ddsd;第二个参数是接收主页面指针的地址,此处为&lpDDSPrimary;第三个参数现在必须为NULL,为该函数所保留。如果函数调用成功,lpDDSPrimary将成为一个合法的主页面对象。由于在前面已经设置了该程序的工作模式为独占和全屏,所以,此时主页面所代表的实际上是我们的整个显示屏幕。在主页面上所绘制的图形将立即反映到我们的显示屏幕上。DirectDraw初始化函数最后创造了一个离
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- win32 游戏编程 游戏 编程
限制150内