常规游戏编程指导

下面讨论一下读者所关心,也是游戏编程常用的技术和基本原理,这有利于简化游戏编程的复杂程度。 首先,视频游戏是运行于超高性能计算机上的游戏程序。对于时间或内存要求特别严格的代码部分不能使用高级API来编程,和游戏代码内部盾环有关的部分,大都需自已手工编写,否则游戏将会碰到严重的速度和性能问题。当然,这并不意味着就不能信任DirectX等API编程工具,因为DirectX以高性能和心可能“瘦”的方式编写。但在通常情况下,要避免高级的函数调用。 除上述情况应多加注意外,在编程时还应留意下面的编程技巧。

 

技巧:不要怕使用全局变量,许多视频游戏不使用大量的带有形参的、与时间相关的函数,而是使用一个全局变量来代替,例如一个函数的代码如下:

void Plot(int x,int y,int color)

{ //在屏幕上画一个点像素

   video_buffer[x + y * MEMORY_PITCH] = color;

}

//结束Plot 函数体运行的时间小于函数调用所需的时间。

这是由于参数压入和弹出堆栈造成的。在这种情况下,更好的方法可能是创建一个全局变量,然后在调用前进行赋值,像下面一样:

int gx,gy,gz,gcolor;//定义一些全局变量
void Plot_G(void)

{

//使用全局变量来画一个点像素

video_buffer(gx + gy * MEMORY_PITCH] = gcolor;

}//结束Plot_G

 

技巧:使用内联功能。通过使用内联指令来完全摆脱调用功能甚至能够改善上面的技巧。内联指令不调用函数,而指示编译器将被调用函数代码放在需要调用该函数的最佳位置,这样做会使程序变得更大,但却提高了运行速度。下面是一个实例。

 inline void Plot_I (int x,int y,int color)

{ //在屏幕上画一个点像素

video_buffer[x + y * MEMORY_PITCH] = color;

}//结束Plot_I

 注意:这里并没有使用全局变量,因为编辑器有效运行了相同类型数据的别名,但是全局变量迟早会派上用场,如果在函数调用时,一个或两个形参已改变,由于没有重新加载,所以旧的参数值有可能仍被使用。

技巧:尽量使用32位变量而不用8位变量或16位变量,Pentium和之后的处理器全部都是32位的,这就意味着它们并不喜欢8位或16位的数据字符,实际上,更小的数据可能会由于超高速缓存和其他相关的内存寻址异常而使速度下降,例如,读者可能创建一个如下所示的结构: struct CPOINT { short x,y; unsigned char c; }//结束CPINT

尽管这个结构看上去很好,但实际并非如此!首先,结构本身目前是一个5字符长的结构——2个short+1个char=5。这实际上是一个很差的设计,这将导致内存地址崩溃。更好的结构形式如下:

 struct CPOINT { int x,y; int c; }//结束CPINT
C++ 提示:除了默认的公共可见性外,C++中的结构更像是“类”。

这种新结构要更好一些。首先,所有的成员都是相同尺寸——也就是说整数的大小为4字节。因此,单个指针可以通过递增DWORD(双字节)的边界访问任何单元。当然,这种新结构的大小 就是3个整数长,即12字节,至少是4的倍数,或者在DWORD边界上。这样将明显地提升性能。 实际上,如果读者真想稳妥地话,应当将所有的结构都变为32字节的倍数。
由于Pentium家庭处理器芯片上标准缓存线长度是32倍数,因而这是一个最佳长度。可以通过人工虚设单元或者使用编辑指令(最简单的方法)来满足这个要求。当然,这可能会浪费大量的内存,但是为了提高速度这是值得的。

技巧:注释你的代码,游戏程序员不注释代码是出了名的,不要犯相同的错误。用额外的输入换取整洁,注释良好的代码是值得的。
技巧:程序应以类似RISC(精简指令系统计算机)的形式来编写。换句话说,尽量简化你的代码,而不是使它更复杂。Pentium和PentiumⅡ处理器特别喜欢简单指令,而不是复杂的指令,你的程序可以长些,但应尽量使用简单指令,使程序相对于编辑器来说更加简单些。例如,不要编写类似下面的程序:

if((x+=(2*buffer[index++])>10) { //进行工作 }//结束
应这样做 x+=(2*buffer[index]); index++ if(x>10) { //进行工作 }//结束if

技巧:按照这种方式来编写代码有两个原因,首先,它允许调试程序在代码各部分之间放置断点;第二,这将更易于编译器向Pentium处理器传送简单指令,这样将使处理器使用更多的执行单元并行地处理代码。复杂的代码就比较糟糕。

技巧:按照这种方式来编写代码有两个原因,首先,它允许调试程序在代码各部分之间放置断点;第二,这将更易于编译器向Pentium处理器传送简单指令,这样将使处理器使用更多的执行单元并行地处理代码。复杂的代码就比较糟糕。
对于简单的、是2的倍数的整数乘法运算,应使用二进制移位运算。因为所有的数据在计算机中都以二进制存储,位组合向左或右移动就等同于乘法和除法运算。例如: int y_pos = 10 //将y_pos乘以64 y_pos = (y_pos << 6);//2^6=64
相似的有
{ //将y_pos除以8 y_pos = (y_pos >> 3);//1/2^3=1/8 当读者接触到优化那一章时,将会发现更多的、类似的技巧。哈哈,酷吧!
技巧:编写高效的算法。世界上所有的汇编语言都不会将n^2算法运行得更快些,更好的方法是使用整齐、高效的算法而不是蛮干。

技巧:不要在编程过程中优化代码。这通常会浪费时间。等到完成主要的代码块或整个程序后才开始进行繁重的的优化工作。这样可以节省你的时间,因为你必须处理一些模糊的代码或不必要的优化。当游戏编程完成时,才到了剖析代码、查找问题以优化程序的时间。另一方面,程序要注意错落有致,不要杂乱无章。

技巧:使用C++应谨慎。如果读者是位老练的高手,继续前进去做你喜欢的事,但是不要去疯狂追求类,或使游戏程序过于复杂以至于超出一般计算机的承受能力,简单、直观的代码是最好的程序,也最容易调试。我从来都不想看多重的隶属关系。

技巧:如果感到前路荆棘丛生,那就停下来,回头然后绕路而行,我见过许多游戏程序员开始于一条很差的编程路线,然后葬送自己。能够意识到自己所犯的错误,然后重新编写500行的代码要比得到一个不是期望的代码结构要好得多,因此,如果在工作中发现问题,那就要重新评估并确保它是值得花时间补救的。
技巧:经常备份你的工作。在编写游戏代码时,需要相当频繁地锁定系统。重新做一个排序算法比较容易,但是要为一个新角色或碰撞检测重新编写AI则是另一回事。

技巧:在开始你的游戏项目之前,进行一下组织工作,使用合理的文件名和目录名,提出一种一致的变量命名约定,尽量对图形和声音数据使用分开的目录,而不是将其全部都放置在一个目录中。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值