专题 |  新闻 |  转载文档 |  控件 |  产品 |  人才 |  项目管理 |  博客  
 论坛 |  Windows |  Visual Studio |  ASP.NET |  VB.NET |  C#.NET |  开源项目 |  搜索  
当前所在位置:首页游戏设计  >  正文
专题: 软件 | 服务器 | IT 电子产品 | PC 电脑 | 笔记本 | IE7 | Windows Mobile | Windows 2003 Server | ISA 2006 | Windows Vista
java经典游戏制作教程(二)
作者:游戏设计 发布时间:20070123 文章来源:

java经典游戏制作教程(2)

6.游戏中的智能系统处理

游戏中的智能对手
  AI在游戏中最普通的形式是创建计算机控制的对手。因为大多数游戏是单人游戏,所以要设计游戏者在游戏中必须战胜对手。为了达到这个目的,你可以使用某种类似A*搜索的简单AI算法,以帮助对手穿过迷宫向游戏者发起进行。你也可以使用简单的算法预测游戏者的反应。
  但是,记住没有必要创建世界上最强大的对手。你的对手只要能给游戏者提供足够的挑战性就可以了。还有,要注意游戏的内容。例如:一个战棋式RPG游戏中策略占的是主要地位;而在纯RPG中故事情节和角色开发就更重要一些。千万不要因为计算机对手太强大而让游戏者们陷入失败的泥沼。

游戏中的非智能对手
  通常,在游戏开发中AI技术是与计算机对手紧紧联系在一起的。这是因为早期的大部分类似角棋的游戏是一对一的。但是,任何好的探险游戏或RPG 游戏开发者都知道,AI同样可以用于非对手角色。例如:如果你正在建立一个RPG游戏并且你想让你的世界活起来,这就是说,让城市里的人以智能的方式活动,那么你可以使用某种算法确定在一天中的某个时候,角色应该在那里。你可以使用类似于AI算法如A*来辅助你将一个对象从一处移动到另一处并绕过障碍物。

游戏中的智能系统
游戏中的AI在本质上是最具有模仿性的,但它们基本上是依赖一些AI要素。 你可以将所有具有决策功能的对象在一个游戏中融合为一个整体。例如:在一个战争游戏中,你的各个部分可以依据各自所处的具体环境来作出各自的AI决策。
   使用这种方法,你得把精力集中于怎样在各个独立的决策个体之间建立联系,以及这些联系怎样才能使游戏成为融会贯通的整体。是用一个高级决策影 响其它决策,还是各个决策个体之间平等地互相影响呢?举个战争游戏来说, 你有十辆坦克,它们的思维模式基本相同。所以它们都决定去攻击敌人阵营中 HP值最低的一辆坦克。但是这时其中一辆坦克说:“这个敌人归我了!”那么 剩下的九辆坦克就应该依据这条信息各自调整下一步的攻击目标。当你建立智能个体时,要考虑在一个智能系统整体环境下,它应该如何行动。

7.电脑游戏中的人工智能制作

 电脑游戏随着硬件执行效率与显示解析度等大幅提升,以往很多不可能或非常难以实现的电脑游戏如此都得以顺利完成。虽然电脑游戏的呈现是那么地多样化,然而却与我们今日所要探讨的主题,人工智能几乎都有着密不可分的关系。
  在角色扮演游戏中,程序员与企划人员需要精确地在电脑上将一个个所谓的“怪物”在战门过程中栩栩如生地制作出来;所以半兽人受了重伤懂得逃跑,法师懂得施展攻性法术。
  目前能让人立刻想到与人工智能有密切关系的游戏有两种:
一是所谓的战棋/策略模拟游戏,二则是棋弈游戏。人工智能的比重与深浅度,在不同的游戏类型中各有不一。有的电脑游戏非标榜着高人工智能不可,不然没有人买;有的则是几乎渺茫到让玩家无法感觉有任何人工智能的存在。            

 导向式思考 AI最容易制作的的方式,同时也是早期游戏AI发展的主要方向就是规则导向或称之为假设导向。在一些比较简单的电脑游戏中,程序员可以好不困难地将游戏中的规则与设定转化成一条条的规则,然后将它们写成电脑程序。让我们以角色扮演游戏为例。决大多数的企画在设定所谓电脑怪物时,所设定的属性通常有以下几种:  生命值 攻击力 防御力 法力  属性 最后一个“属性”是我在设定时喜欢增加的项目之一。透过这项属性的设定,我可以把怪物设定成“贪生怕死的”,也可以把战士设定为“视死如归”。以目前我们所掌握的资料,在战门系统中的大纲如是诞生了:                          规则一if (生命值< 10) // 边临死亡了吗 
{  if (属性== 贪生怕死)               
    结果 = 试图逃跑               
   if (有任何恢复生命值的物品或法术可用)      
    结果 = 使用或施展相关物品或法术       
}                                                  规则二
 
if (可施攻击性法术 && 有足够法力)
{                        
    结果 = 施展攻攻击性法术             
}                          由以上一连串的“如果--就--”规则设定,建立了最基本的AI。说这样的制方式只能建立基本AI其实并不当然正确。只要建立足够及精确的规则,这样的方式仍然有一定水准的表现。
  规则导向的最大优点就是易学易用。在没有深奥的理论概念的前提下,仍有广大的使用群。所以很多老道的玩家常常没两下就摸清楚敌人的攻击策略,移动方式等等。 推论式思考 相信曾经接触过电脑语言课程,或是自习过相关书籍的朋友们,都曾曾经听过一个著名的程序,那就是井字游戏。用井字游戏作为讨论AI的入门教材,我个人觉得是最适当的例子。或许有人还不知道井字游戏怎么玩。只要任何一方在三乘三的方格中先先成一线便胜利了。我们在前面谈过的规则导向,在这里也可以派得上用场。 if任何一线已有我方两子&&另外一格仍空//我方即将成一线吗
   结果 = 该空格                     
  if任何一线已有敌方两子&&另外一格仍空//防止敌方作成一线 
   结果 = 该空格                     
  if任何一线已有我方一子&&另外两格仍空//作成两子    
   结果 = 该空格

 有一次我在某本电脑书上,同样地也看到某些以井字游戏为介绍的范例。不同的是,我几乎看不到任何规则导向的影子。但在仔细分析该程序码后,我得到了极大的启发,原来AI是可以不用这么多规则来制作的。它用的方法正是在电脑AI课程中重要的概念:极大极小法。我在这里只说明这法则的概念。继续以井字游戏为例,电脑先在某处下子,接着会以假设的方式,替对方下子,当然,必须假设对方下的是最佳位置,否则一切则毫无意义。在假设对方下子的过程中,自然又需要假设我方的下一步回应,如此一来一往,直到下完整局游戏为止。 底下是节录书中的程序片段:                       
 
bestMove(int p, int*v)
{   int i; 
    int lastTie;                  
    int lastMove;                 
    int subV;                                   
/*First, check for a tie*/            
     if (isTie()) {              
      *v=0;               
      return(0);              
    };
/*If not a tie, try each potential move*/
  for (*v=-1, lastTie=lastMove=-1,i=0;i<9;i++)
   {
    /*If this isn't a possible, skip it*/          
    if (board !=0) continue;
    /* Make the move. */
     lastMove=i; 
     board =p;                             
    /* Did it win? */                       
     if (hasWon(p)) *v=1;                     
     else{                             
    /*If not, find out how good the other side can do*/
      bestMove(-p,&subV);                      
    /* If they can only lose, this is still a win.*/
       if (subV==-1) *v=1;       
    /* Or, if it's a tie, remember it. */         
        else if (subV==0){                 
           *v=0;       
           lastTie=i; 
           };                          
        };                              
/* Take back the move. */           
            board =0;          
/*If we found a win, return immediately
      (can't do any better than that)*/     
   if (*v==1) return(i);                     
/*If we didn't find any wins, return a tie move.*/         
   if (*v==0) return(lastTie);                      
/*If there weren't even any ties, return a loosing move.*/     
   else return(lastMove); 
};

国外的一些论坛曾举行过256字节的游戏设计比赛。作品非常多,其中有一件作品正巧也是井字游戏。作者用区区两百多行就写了与上述程序演算方式完全相同的作品,可见功力确实了的。另外,我也很希望类似的活动能在国内推展起来。对了,在这样的比赛条件限制下,除了汇编语言外,几乎没有其它的选择了。       .386c                        
  code      segment byte public use16      
          assume cs:code, ds:code      
                            
          org   100h            
                            
  tictac     proc  far             
                            
  start:                       
          push  cs             
          pop   ds             
          mov   ax,0B800h     ; 清除屏幕
          mov   es,ax       ;    
          xor   di,di       ;    
          mov   cx,7D0h      ;    
          mov   ax,0F20h      ;    
          rep   stosw       ;    
          xor   cx,cx       ;    
          mov   dl,5            
  loc_1:                       
          call  printBoard         
  loc_2:                       
          mov   ah,8        ; 等待按键
          int   21h             
                            
          movzx  bx,al            

          sub   bl,31h       ; 如果不是1..9
          jc   loc_2       ; 则重新输入 
          cmp   bl,8              
          ja   loc_2              
          cmp   data_1[bx],al          
          jne   loc_2              
          mov   byte ptr data_1[bx],'x'     
          dec   dl               
          jz   short loc_3           
          mov   al,'o'             
          call  bestMove            
          mov   [si],al             
          call  isWin   ; 判断是否已取得胜利 
          jnc   loc_1              
  loc_3:                          
          call  printBoard           
          mov   ax,4C00h            
          int   21h               
                              
  data_1     db   '12'              
  data_2     db   '3456789'            
  data_3     db   0                
                              
  tictac     endp                  
                              
                              
  printBoard   proc  near              
          mov   si,offset data_1        
          mov   di,548h             
          mov   cl,3              
                              
  locloop_4:                       
          movsb                  
          add   di,5              
          movsb                  
          add   di,5              
          movsb                  
          add   di,133h             
          loop  locloop_4            
                              
          retn                  
  printBoard   endp                  
                              
                              
  isWin      proc  near              
          mov   bx,1              
          mov   bp,3              
          call  sub_3    ; 检查横向是否完成 
          inc   bx               
          inc   bx               
          dec   bp               
          dec   bp               
          call  sub_3    ; 检查纵向是否完成 
          call  sub_4    ; 检查斜向是否完成
          clc
          retn                  
  isWin      endp

 

loc_5:                         
          stc                   
          retn                  
                                                            
  sub_3      proc  near              
          mov   ah,3              
          mov   si,offset data_1        
  loc_6:                         
          mov   di,si              
          call  sub_5              
          add   si,bp             
          dec   ah               
          jnz   loc_6              
          retn                  
  sub_3      endp                  
                             
  sub_4      proc  near              
          mov   di,offset data_1       
          inc   bx              
          call  sub_5             
          mov   di,offset data_2        
          dec   bx               
          dec   bx               
          call  sub_5              
          retn                  
  sub_4      endp                  
                              
                              
  sub_5      proc  near              
          mov   cl,3              
                              
  locloop_7:                       
          cmp   [di],al             
          jne   short loc_ret_8         
          add   di,bx              
          loop  locloop_7            
                              
          add   sp,4              
          jmp   short loc_5           
                              
  loc_ret_8:                       
          retn                      
  sub_5      endp                      
                                  
  bestMove    proc  near                  
          mov   bx,31FEh                
          mov   cl,9                  
          mov   di,offset data_1            
                                  
  locloop_9:                           
          cmp   [di],bh     ; #empty?        
          jne   short loc_12  ; #no, skip       
          mov   [di],al                 
          pusha                      
          call  isWin      ; #CY: Win       
          popa          ;            
          jnc   short loc_10  ;            
          mov   bl,1 

转载文档
.NET
Visual Basic
Visual C++
游戏开发
Java
ASP
Perl
Delphi
Javascript
其他开发语言
数据库开发
网站制作技术
文件格式
其他
文章投稿
Web.Service
ASP.Net
C#.Net
VB/VC.Net
Borland
JAVA
数据库
Unix/Linux
图形美工
安全
VS.Net

中国DotNet俱乐部 || 博客.中国  版权所有
京ICP备05037360号