如何编制RPG游戏(上)

 
游戏玩得多了,可能每个人都曾会想过一个问题:要是自己也能制作出一套游戏那多好。究竟编游戏的吸引力在哪里呢?在很多地方,颇具微妙--你就真正控制了故事中剧情的发展、主角的命运,也许还有用自己主观感情去感染别人。这就好比写作,虽然并非人人都会去做,却人人想做,极富魅力。 

那么,在业余条件下能否完成游戏的编制呢?答案是完全可以。 

一套游戏,其中包含的内容很多,涉及了编程技巧的方方面面。本文力求从简便的角度出发介绍RPG类游戏的制作,只要你有一点C语言的基础,就可以按部就班编出一个游戏来,若对C没有一点概念,那么正好趁此机会学习一下C,体会体会当代最实用的编程语言。考虑到现在C及C++各种版本的普及情况,在此拟采用Turbo C 2.0为例,逐一介绍这方面的具体知识。 


一 浅说: 

在正式进入游戏编程前,我们先来谈谈有关屏幕管理的几个有趣的问题。计算机显示器的工作方式有两种:正文方式和图形方式,在每种显示方式下还可分为不同的显示模式。对于我们的GAME来说,她的处理对象主要是图形,所以我们需要采用后一种显示方式。 

在Turbo C中initgraph是一个初始化图形系统的有用函数,它从磁盘装入一个图形驱动程序,且把系统置成图形方式。除了这种动态装入机制外,也可以将一个或几个图形驱动程序文件直接同可执行程序文件连接起来。游戏中通常采用的是640×480或320×200的分辨率。让我们来看看一个子程序: 

setupgraph()  /* 图形初始化 */ 

int driver=VGA,mode=VGAHI; 
/* VGA卡的VGAHI图形模式,640*480同显16色 */ 
initgraph(&driver,&mode,""); 
/* 使用空字符串 "" 表示设备驱动程序在当前目录中 */ 


这个程序装入的图形驱动程序文件为EGAVGA.BGI,在例程中我们也将采用这种640×480的模式进行编程。若想选用其他分辩率,只需改变driver和mode的值便可。 

下面我们来谈谈有关调色板的应用。 

对于VGA显示器,图形模式12H(640×480,16色)共设置了16个颜色寄存器,所以显示器上能同时最多显示16种颜色。系统初始化时,也将颜色寄存器予以初始化,若这种默认颜色值不满足要求的话,只需修改相应颜色寄存器的数据,就可实现从64种颜色中任意选取,使显示的图形更加美观。 

setpalette(调色板号,颜色号)函数可将指定的颜色填入指定的调色板中,从而改变调色板上的默认颜色。例如: 

setpalette (1,4); 

用该函数重新设置后,以后使用1号调色板时,则显示4号颜色红色。 

【注】有效的颜色依赖于当前的图形驱动程序和当前的图形模式,该函数不可用于IBM-8514图形驱动程序,应使用setrgbpalette函数。 

VGA的13H模式是320×200点阵的彩色图形模式,同显256色。

在图形初始化完成后,我们就可以进入富有挑战的游戏编程了。 

二 制作精灵:

在RPG游戏中,有很多能根据不同规则和目的而在背景场地跑来跑去的小目标:象城镇里的居民,野地上的小动物,或者再加上几株会动的小树,当然了,还有最重要的主角--游戏中的英雄或淘气鬼。这些小角色我们通常称之为“精灵”。 

这些精灵要在各自的场地上迅速移动,当它们在草地上跑动时,经过的地方要遮住背景,而当它们经过后,背景的草地又要迅速恢复回来,若是遇到房屋、小河、岩石,就要停下来。那么,这些是如何实现的呢? 
在程序中实现精灵的移动,我们通常采用这样的方法:在屏幕上擦除精灵当前的位置,然后在下一个位置进行重显……依次循环,你就会感到精灵跑动起来。这个原理是很简单的,但重要的是:擦掉并重显的速度必须足够快,才能有活生生的效果。 

构成图形的最基本要素是点,无论背景也好,精灵也好,都是由许许多多的点组成的,所以精灵的重显问题其实也就是擦点画点的问题。在屏幕上画点有两种方法,一种是使用ROM BIOS调用,另一种是直接写显示RAM。这两种方法比较而言,前一种是相当慢的,而后一种极快。正因为如此,我们不能通过ROM BIOS去画点,而必须采用直接写显示RAM的办法画点。

精灵在背景画面上保持动态最好的办法是通过XOR(“逻辑异或”)运算,借助XOR操作,动态精灵在同一显示位置上连续进行两次XOR运算,使画面出现和消失,而不会导致背景画面的任何损坏,我们来看例程:

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

union REGS r; 
color=color|128; 
/* 参数color 和 128相逻辑或,置位最高位 */ 
r.h.bh=0; 
r.h.ah=12; 
r.h.al=color; 
r.x.dx=y; 
r.x.cx=x; 
int86(0x10,&r,&r); 


这个画点程序采取直接写显示RAM的办法,在画每一个点时, 先让彩色值与值128进行逻辑“或”,使彩色值的位7为1,(这就告诉了函数不是以新彩色值替换原彩色值,而是与原彩色值进行逻辑“异或”)。所以这个点总是可见的. 因为它总是与周围其它点颜色不一样,而连续两次XOR运算又很容易使周围曾经被它占据的点恢复成被占据前的颜色。 

在解决了画点问题后,只要把组成精灵的点归入一个集合,使这些点同时进行运动,那么,精灵的问题也就解决了。 

精灵的造型设计是丰富多彩的, 你尽可以凭你的想象创造出要在游戏中出现的形态各异的人和其它各种角色。我们可以借助Animator pro来完成角色设计,如果精灵不是很复杂的话,我们甚至可以直接“点”出她们:打开Spt或Windows的画笔,我们在“逐点修改”的方格阵上点绘出精灵的造型,反复修改至满意,给精灵定个外框,在四角任取一个点作为参照坐标(X,Y),以(X,Y)为参数组成精灵集合man(int x,int y): 

void man(int x,int y) 

putpoint(x+dx1,y+dy1,color); 
...... 
putpoint(x+dxn,y+dyn,color); 

一般来说,精灵应比较小,以便加快重显速度,使移动看起来比较平滑。若精灵太大,移动起来就比较慢。在例程中,我们用一个9×12的框代替精灵: 
void man(int x,int y,int color) 

int i; 
for (i=0;i<9;i++) 
{putpoint(x+i,y,color); 
putpoint(x+i,y+12,color);} 
for (i=0;i<12;i++) 
{putpoint(x,y+i,color); 
putpoint(x+9,y+i,color);} 

[返回页首] 

三 键盘控制: 

在游戏中,主角的移动一般是由上、下、左、右键或HOME、END、PGUP、PGDN四键控制的,此处还有几个问题:若键入空格、回车等,计算机如何识别?在游戏的中文菜单中如何用上下键移动选择光条?这些都是在游戏编程中会碰到的典型问题。 

在Turbo C中,我们用bioskey (int cs)函数来获取键盘字符。这个函数使用BIOS中断0x14完成各种键盘操作,参数cs确定实际的操作:cs=0,返回从键盘输入的下一键码;cs=1,测试输入键是否有效;cs=2,请求当前移位键(SHIFT)的状态。 

bioskey(0)获得所击键的扩展的扫描码。扩展的扫描码分两部分,即扫描码和ASCⅡ码。当按键是一般ASCⅡ码时,如回车、空格、ESC键,从扩展扫描码的低字节中可以得到它的ASCⅡ码值;当按键是特殊键时,如上、下、END、HOME键,其ASCⅡ码部分为0,所以要将组成扩展扫描码的两部分分开: 

…… 
do 
{key.i=bioskey(0); 
if(key.ch[0]) 
{switch(tolower(key.ch[0])) 
{case ‘\‘: 
程序一 /* 空格键 */ 
case ‘r‘: 
程序二 /* 回车键 */ 
…… 
}} 
else 
{switch(key.ch[1]) 
{case 72: 
程序三 /* 上键 */ 
case 80: 
程序四 /* 下键 */ 
case 75: 
程序五 /* 左键 */ 
case 77: 
程序六 /* 右键 */ 
…… 
}} 
}while(tolower(key.ch[0]!=27); /* ESC键 */ 
…… 
key.ch[0]中为ASCⅡ码部分,key.ch[1]为扫描码部分。ESC键为ASCⅡ字符键,键值为27,所以上面程序最后一行表示当按键不是ESC时,就一直循环。而由于上、下、左、右键为特殊键,所以判别是否按了这些键用switch(key.ch[1])。 
【注】常用键码 HOME: 71 
F1-F10: 59-68 END: 79 
ALT+(F1-F10): 104-113 PAGE UP: 73 
SHIFT+(F1-F10): 84-93 PAGE DOWN: 81 
[返回页首] 

四 边界识别:

让我们再回到第二节所讨论的问题:游戏中精灵的跑动是有限制的,它不能越过墙壁、树林、山脉、河流等,同样也不能超越背景的最大最小边界(这时往往会切换到另一幅背景中去),这些都是属于边界问题或者说障碍识别。 

对后一类问题,有时我们可以凭借屏幕的(X,Y)边界值来识别;但一旦遇到前一种目标较多的情况时,这种算法无疑是极繁琐的,可能会使速度明显下降,最糟糕的是它要对动态装入的每一块新的动画场地都要重新设置。 

很明显,我们经常要采用的是另一类算法,只有对特定的少数目标,如宝藏隐藏点,或旅店、武器店的门,可以用(X,Y)定值来判别。在游戏中,颜色是具有不同含义的。我们可以定义树林的绿色、河流的蓝色、墙壁的土黄色为不可逾越的边界,那么只要检查一下精灵周围各点的颜色有没有这些颜色就可以了。 

我们要用到一个很有用的函数getpixel(x,y),它能取得位于(X,Y)处像素点的颜色。在游戏中,主角移动的每一步叫步长,每走一步前,检查下一步步长范围内的像素点中有没有预先定义的颜色,若有,则原地踏步。在实际编程中,其实无需比较全部像素点,只要检查一下下一步长边缘的A、B、C三点就可以了。在例程中仍检查了全部点:

…… 
case 72: /* 上 */ 
for(j=0;j<=9;j++) 
{for(jj=0;jj<=increment;jj++) /* increment 步长 */ 
{if(getpixel(x+j,y-winys-jj)==12) 
/* 检查颜色是否为红色 12 */ 
{colorbz1=1;break;} /* colorbz1 标志 */ 
}} 
if(y-increment>winys) 
/* winys 屏幕 y轴起始点,通常为 0 */ 
{if(colorbz1!=1) 
y-=increment;} 
colorbz1=0; /* 标志清零 */ 
break; 
……
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值