既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
{
inStr[j]=rinStr[i];
inStr[j+1]='\0';
j++;
}
}
if(strncmp(searchFor,inStr,strlen(searchFor))==0)
{
j=0;
for(i=strlen(searchFor);i<kStringLength;i++)
{
if(inStr[i]==';')
break;
value[j]=inStr[i];
value[j+1]='\0';
j++;
}
StringToNumber(value,&ivalue);
fclose(dataStream);
return ((int)ivalue);
}
}
fclose(dataStream);
return 0;
}
return 0;
}
例8-5 中的函数一开始是接受两个字符串参数。第一个参数是指定要搜寻的脚本名称,而第二个是要搜寻的词汇。然后,这个函数会以指定的文件名打开脚本文件。一旦文件打开了,这个函数就开始检查脚本文件。一次检查一行文字,每一行都会被当做字符串而读进来。
注意,每一行都会读进变量 rinStr 中,再立即复制到 inStr 中,但会去掉空白。
我们利用字符串变量 searchFor 把要搜寻的词传给 fi\_GetData( ) 函数。此时在,在这个函数里,我们用 C 函数 strncmp( ) 搜寻 inStr,以期能找到所要搜寻的词。
如果要搜寻的词没有找到,这个函数就会继续读取脚本文件里的下一行文字。如果找到了,就会进入新的循环,把 inStr 变量中含有该属性值的部分,复制到名为 value 的新字符串中。接着再调用外部函数 StringToNumber( ),把这个字符串转换成整数值,然后,fi\_GetData( ) 函数就返回 ivalue 的值。
### 描述对手行为
直接影响对手的行为是描述机制在游戏软件 AI 中最常用的方式之一。
**描述行为可以让我们直接操纵 AI 对手的行为**。我们需要采取某种方式让脚本能看懂游戏世界和检查条件,以改变 AI 行为。为了做到这一点,我们可以新增预先定义好的全局变量到我们的描述系统里。实际的游戏引擎会替这些变量赋值,而不是由描述语言来指定。
例如,在我们的描述系统里,我们可能有一个全局布尔变量,名叫PlayerArmed,会让胆小的巨人只敢去攻击没有武装的对手,如例8-6所示。
//例8-6:基本行为脚本
if(PlayerArmed==TRUE)
BEGIN
DOFlee();
END
ELSE
BEGIN
DOAttack();
END
在例8-6 中,脚本没有替 PlayerArmed 赋值,此变量是代表游戏引擎里的某个值。游戏引擎将评估此脚本,并把此行为连接到胆小的巨人身上。
**描述行为的另一个方面是 AI 角色的移动。**我们可以在描述系统中应用在第三章中提到的移动模式。之前在第三章中,我们直接将移动模式写进程序代码中,如果每次做出较小的修改之后都得重新编译。图8-1 是游戏设计师用描述系统实现的移动模式范例。
![这里写图片描述](https://img-blog.csdn.net/20170720175936559?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSnVyYm8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
例8-8 显示了我们如何编写一个脚本,借此实现图8-1 中的行为。
//例8-8:移动模式脚本
if(creature.state==kPatrol)
begin
move(0,1);
move(0,1);
move(0,1);
move(0,1);
move(0,1);
move(-1,0);
move(-1,0);
move(0,-1);
move(0,-1);
move(0,-1);
move(0,-1);
move(0,-1);
move(0,1);
move(0,1);
end
在此描述范例中,如果 AI 生物处在巡逻状态中,则使用指定的移动模式。每一步都是从前一位置移动一个单位。要了解移动模式的细节说明,参见 [游戏开发中的人工智能(三):移动模式](https://bbs.csdn.net/topics/618668825)。
### 描述口语互动
智能行为可以让游戏更富有挑战性,而**口语互动也属于智能行为。游戏软件 AI 必须检查一组已知的游戏参数,并据此来做出相应。**
例如,玩家的武装程度怎样,就是可以被检查的参数。然后,我们可以让敌方 AI 角色评论此种武器,看起来就好像计算机控制的角色,可以知道游戏里正在发生什么事情一样。例8-9 是说明这种脚本的简单范例。
//例8-9:口语嘲讽脚本
if(PlayerArmed == Dagger)
Say(“好可爱的小刀”);
if(PlayerArmed == Bow)
Say(“放下弓就让你活命”);
if(PlayerArmed == Sword)
Say(“那把剑正好可以让我当做收藏品”);
if(PlayerArmed == BattleAxe)
Say(“你没有力气挥动那把战斧”);
![这里写图片描述](https://img-blog.csdn.net/20170720180932028?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSnVyYm8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图8-2 是一个假象的游戏场景,一个巨人正在追逐玩家。就此而言,游戏软件 AI 可以使用游戏状态下特有的元素,根据当前情况,提供适当的嘲讽语。
例8-10 显示了游戏软件 AI,如何在计算机控制的巨人和玩家控制的人类之间的战斗中,找出适当的嘲讽语。
//例8-10:巨人嘲讽语脚本
if(CreatureGiant) and (playerHuman)
begin
if(PlayerArmed == Staff)
Say(“你需要更多的棍子吧,小矮人!”);
if(PlayerArmed == Sword)
Say(“放下你的剑,否则我就打扁你!”);
if(PlayerArmed == Dagger)
Say(“你的小刀抵不上我的棍子!”);
当然,这种描述机制不限于哪些要杀玩家的地方角色。友善的计算机控制角色也能利用相同的技巧。例8-11 说明了脚本如何协助剧情,并引导玩家的行为。
//例8-11:友善NPC的AI脚本
if(Creature == FreiendlyWizard)
begin
if(playerHas==RedAmulet)
Say(“你找到了红色护身符,把它拿到石庙,你将得到奖赏”);
end
如例8-11 所示,直到护身符被玩家得到,并且玩家面对友善的法师时,有关护身符应该放在何处的重要信息才会展现出来。
**前几个脚本范例让你知道了游戏软件 AI 可以在指定情况下做出反应,但是有时候,游戏角色还需要和玩家做某种类型的口语互动。**
在这种场景中,玩家必须以某种机制把文字输入给游戏。然后,游戏引擎再把文字字符串送交给描述系统,描述系统再分析文字,并提供适当的响应。图 8-3 显示了在实际游戏里的画面。
![这里写图片描述](https://img-blog.csdn.net/20170720181731304?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSnVyYm8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
就图8-3 所示的情况而言,玩家输入了“What is your name?”,而描述系统做出响应的文字是“I am Merlin”。例8-12 是用于实现此种做法的基本脚本。
//例8-12:基本的询名脚本
If Ask(“What is your name?”);
begin
Say(“I am Merlin”);
end
例8-12 有一个严重的缺点。只有当玩家输入和脚本中的问题完全一样的文字时,才能起作用。
**检查每个口语文字字符串的另一种做法是建立语言分析器,解析每个句子,确定其到底在问什么。不过对于多数游戏来说,可以仅仅搜寻特定的关键字,并据此作出响应即可。**
如例8-14 所示,脚本将检查玩家所输入的文字中,是否有“what”和“name”两个关键字存在。
//例8-14:关键字描述机制
If(Ask(“what”) and Ask(“name”))
begin
Say(“I am Merlin”);
end
下面将介绍如何**根据指定关键字检查玩家输入的问题**。例8-15就是这种做法。
//例8-15:搜寻关键字
Boolean FoundKeyword(char inputText[kStringLength],char searchFor[kStringLength])
{
char inStr[kStringLength];
char searchStr[kStringLength];
int i;
for(i=0;i<=strlen(inputText);i++)
{
inStr[i]=inputText[i];
if( ((int)inStr[i]>=65) && ((int)inStr[i]<=90) )
inStr[i]=(char)( (int)inStr[i]+32 );
}
for(i=0;i<=strlen(searchFor);i++)
{
SearchStr[i]=searchFor[i];
if( ((int)seachStr[i]>=65) && ((int)searchStr[i]<=90) )
searchStr[i]=(char)( (int)searchStr[i]+32 );
}
if(strstr(inStr,searchStr)!=NULL)
return true;
return false;
}
例8-15 是游戏引擎中实际的程序代码,当游戏设计师的脚本中使用了 Ask( ) 函数时,就会被调用。这个函数有两个参数:inputText(玩家输入的文字)以及 searchFor(要搜寻的关键字)。我们在此函数中做的第一件事,就是把字符串都转换成小写。一旦有两个小写字符串,我们可以调用 C 函数 strstr()来比较两个字符串。strstr()函数会搜寻 inStr 中首次出现 searchStr 的地方,如果在 inStr 中找不到 searchStr,就会返回 false。
### 描述事件
![img](https://img-blog.csdnimg.cn/img_convert/af38552e8064e8d4fc789486428a3825.png)
![img](https://img-blog.csdnimg.cn/img_convert/b407fa75e4f48c601aa6e29782f48d96.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
64767836)]
[外链图片转存中...(img-Zt4Vhvh7-1715564767836)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**