本章内容:

  • 介绍脚本系统是如何用于解决下列问题的:
  • RPG游戏中与内容相关的部分——非玩家角色和场景细节
  • RPG游戏中的物品、武器和敌人
  • 第一人称射击游戏中的物品、谜题和机关
  • 第一人称射击游戏中敌人的行为

1.游戏引擎和内容是完全分离的,所以当游戏玩家购买游戏软件的时候,实际上购买了两个部分:一个编译过的游戏引擎和一系列可以对游戏功能进行扩展的脚本。这种结构称之为模块化结构。这种方法一种常见的应用是以“情节(episode)”的形式发布游戏。这就意味着游戏软件店在在销售游戏软件的时候只出售一部分游戏内容以及可以在上面运行游戏的游戏引擎。当游戏玩家完成了第一个游戏情节的时候,他们就可以以较少的费用下载或者购买另外的如patches和add-ons样式的游戏情节(这不就类似于DLC吗)。

2.角色扮演游戏(Role Playing Games,RPGs)

RPG游戏一般要比其他类型的游戏要使用更多的脚本,原因就在于RPG游戏的确适宜于使用脚本,它们确确实实需要大量的游戏内容。自然而然,RPG的游戏开发人员就需要一个很好的方法以一种结构化的、有组织的方式来开发这些内容。

下面将分析一下RPG游戏的传统内容,以便理解为什么脚本对于设计角色扮演的游戏来说那么适用。

①复杂而又有深度的故事情节:

RPG游戏看起来更像是一部交互式小说,这就意味着游戏中将会出现进行无穷行对话的人物角色和带有无数“场景点”的高度结构化的游戏场景。而在玩家冒险经历的每一个场景点,游戏都需要玩家在到达该处之前完成了哪些主要的事情以确定游戏世界中的现在状态以及将要发生的事情。解决的方法就是采用一组“标记(flags)”来记录场景点或者是游戏世界中的现在状态。每个标记代表游戏中的一个事件,可以为TRUE或者FALSE(当然可以不是布尔类型)。

这套系统的实现方法有很多种。一种就是在引擎的源代码中直接建立标技术组,并向游戏脚本提供一个访问接口,这个接口允许脚本对于数组进行读写操作。这种方法将所有逻辑和功能都写在了脚本上,脚本只需通过接口访问数组就可以完成这套系统。第二种方法就是如果脚本系统能力很强的话,甚至可以将数组从引擎中剥离,直接将数组存储到脚本内部并访问,这种方法是最理想的,因为这让游戏逻辑和引擎进行了分离。不过前者也是可用的。

②非玩家角色(Non-Player Characters, NPCs)

NPC在游戏里也是至关重要的,他们可以为主角进行剧情的引导,或是和他们交换物品。因此,条件逻辑、循环以及读取游戏flags的能力等就会变得很关键。解决方法如下:

一些简单的对话,只需在NPC和脚本之间建立一些一对一的对应关系。当有NPC问一些带有选项的问题时,系统会根据玩家应答的结果的不同而采用不同的对话策略。或者其他的一些不同的情况,使得NPC变得十分逼真和灵活,这就需要一种更加强大的描述语言来描述他们的行为。

这种语言所需要的特征:

(1)应该具备基本的对话能力

(2)在对话中可以通知游戏引擎在什么时候加入动画

(3)能够查看玩家的物品清单

(4)能够提供一组定做的答案

(5)记录玩家和这个角色的交往历史。此外,理论上游戏玩家在这些单独的对话期间可能会退出游戏然后又重新进入,那么就不仅需要在游戏期间在内存上保留信息,在不同的游戏期间还要把它们保存到磁盘上。即无限期地保存这个NPC相关的变化信息

(6)能够改变flags

下面有段对话:

(游戏玩家第一次和NPC进行对话)

NPC:"Hey, you look familiar."(斜着眼睛盯着玩家的脸)

Player:"Do I?I don't believe we've met."

NPC:"Wait a sec- you're the guy who's gonna save the world from the vampires,right?"

NPC:(如果游戏玩家说的是Yes)"I knew it!Here, take this garlic!"(将大蒜交给游戏玩家)

Player:"Thanks!"

(游戏玩家再次和NPC进行对话)

NPC:"Sorry, I don't have any more garlic.I gave you all I had last time we spoke."

Player:"Well that sucks."(跺脚)

(游戏玩家第三次和非玩家角色进行对话)

NPC:"Dude I told you, I gave you all my garlic.Leave me alone!"

Player:"But I ran out, and there's still like 10 more vampires that need to be valiantly defeated!"

NPC:"Hmm...well, my brother lives in the next town over, and he owns a garlic processing plant.I'll tell him you're in the area,and to batch ready for you.Next time you're there,just talk to him, and he'll give you all the garlic you need."

Player:"Thanks, mysterious garlic-dispensing stranger!"

NPC:"My name's Gary."

Player:"Whatever."

(游戏玩家和NPC进行了三次以上的对话)

NPC:"So,have you seen my brother yet?"

这段对话可以用以下类似于C/C++的脚本代码编写:

static int iConverseCount = 0;
static bool bIsPlayerHero = FALSE;
main()
{string strAnswer;if(iConverseCount == 0){NPCTalk("Hey, you look familiar.");PlayAnim(NPC, SQUINT);PlayerTalk("Do I?I don't believe we've met.");strAnswer = NPCAsk("Wait a sec- you're the guy who's gonna save the world from the vampires,right?", "Yes", "No");if(iAnswer == "Yes"){NPCTalk("I knew it!Here, take this garlic!");GiveItem(GARLIC, 4);PlayerTalk("Thanks!");bIsPlayerHero = TRUE;}else{NPCTalk("Ah.My mistake.");bIsPlayerHero = FALSE;{}else{if(bIsPlayerHero){if(iConverseCount == 1){NPCTalk("Sorry, I don't have any more garlic.I gave you all I had last time we spoke.");PlayerTalk("Well that sucks.");PlayAnim(PLAYER, STAMP_FEET);}else if(iConverseCount == 2){NPCTalk("Dude I told you, I gave you all my garlic.Leave me alone!");PlayerTalk("But I ran out, and there's still like 10 more vampires that need to be valiantly defeated!");NPCTalk("Hmm...well, my brother lives in the next town over, and he owns a garlic processing plant.I'll tell him you're in the area,and to batch ready for you.Next time you're there,just talk to him, and he'll give you all the garlic you need.")PlayerTalk("Thanks, mysterious garlic-dispensing stranger!");NPCTalk("My name's Gary");PlayerTalk("Whatever.");SetGameFlag(GET_GARLIC_FROM_GARYS_BROTHER);}else{NPCTalk("So,have you seen my brother yet?");}}else{NPCTalk("Hello again.");{}iConverseCount ++;
}

会发现仅仅只是添加了一些新的特征,这个语言就突然变得和C/C++语言相似了。同样的,在编写一个RPG游戏的过程中,数组、指针、动态资源分配等许多更加高级的语言特性也会大放异彩。通常有两种方法来设计脚本:①先设计一个类似于C/C++的语法体系,然后在你需要的时候添加新内容;②同时设计语法和语言的总体结构。前者要比后者容易的多。采用C/C++也会是你的系统更加统一和标准

③物品和武器:

因为很多物品的行为都非常像是宏,可以采用基于指令的语言来编写它们。

物品脚本和游戏脚本一般都需要完成一系列的任务。首先要提到的就是它的后台功能,即这个物品是攻击敌人的,还是治疗友军的,还是打开一道门,还是清理一个过道等等。这个功能只要简单地更改一些代码就可以实现。基于命令的语言可以满足。然而,另一个方面是玩家可以感受到这种武器或者物品的功能的具体表现,比如武器的动画效果等。基于命令的语言就不能满足这个需求了。

解决方法:

最好还是采用那些C/C++样式的、面向对象的语言,因为它们允许物品和武器在脚本内部定义自己的图形效果并且直到最为细节的部分。整个过程很简单,只是涉及到至少要提供一组可供脚本调用的基本的图形程序。所有这些所必须必备的不过就是下面这些常见的东西——制作图形、绘制精灵,也可能是播放电影文件使得玩家可以预览动画效果,通常由DirectX、OpenGL以及SDL所提供的图形API的精选子集组成。

下面举例写一个武器实例:

武器名为Fire Sword。Fire Sword的功能是向敌人发射火球,对于冰系或水系的怪物尤其有效。相反,对火属性的敌人效果较差。同时,由于它的热量,当游戏玩家每次使用这个武器时也会对自身造成一定程度上的伤害。我们就可以通过编写一个火球的动画来完成这个想法。综上,从技术层面来考虑这个武器的功能:

(1)需要能够修改游戏中人物的统计数据,也就是他们的体力值。还要考虑属性的克制时的伤害结算

(2)需要能够真正在屏幕上看到由玩家所在位置到敌人所在位置发射的火球,以及爆炸声。需要处理动画和声音,因此需要条件逻辑和循环。基于命令的语言已经不适用了。此外,主应用程序还应提供一个基本的多媒体API使得脚本最起码能够在屏幕上绘制精灵和播放声音。

(3)还要处理由宝剑发射出来的热量对于自身所造成的的轻微伤害。与(1)类似,仅仅涉及到一些数据的问题,这意味着需要能够访问到玩家的具体状态。

以上任务(2)比较难以解决,其余两个只要基于命令的语言就可解决。这就排除了基于命令的语言而改用C/C++体系的语言。代码如下:

Player.HP -= 4;int Y = Player.OnScreenY;
for(int X=Player.OnScreenY; X<Enemy.OnScreenX; X++)BlitSprite(FIREBALL, X, Y);
PlaySound(KA_BOOM);if(Enemy.Type==ICE || Enemy.Type==WATER)Enemy.HP -= 16;
else if(Enemy.Type == FIRE)Enemy.HP -= 4;
elseEnemy.HP -= 8;

④敌人:

敌人最为主要的部分在于它同时利用了前面的两个概念:它具有NPC的特征或者是个性为中心的方面,同时它还具有物品和武器的功能以及破坏特性。因此敌人是这两个实体背后的概念相结合的过程。

解决方法:

RPG的打斗场面的主体框架是循环的,再循环过程的每一次迭代过程中,游戏玩家和敌人都要对输入进行分析。当敌人执行相应的打斗脚本时,玩家要准备接受输入的数据;当玩家执行相应的打斗脚本时,敌人要准备接受输入的数据。代码如下:

void Act()
{int iWeakestPlayer, iLastAttacker;if(iHitPoints < 20)if(rand() % 10 == 1)Flee();else{iWeakestPlayer = GetWeakestPlayer();if(Player[iWeakestPlayer].iHitPoints<20)Attack(iWeakestPlayer, METEOR_SHOWER);else{iLastAttacker = GetLastAttacker();switch(Player[iLastAttacker].iType){case NINJA:{Attack(iLastAttacker, THROW_FIREBALL);break;}case MAGE:{Attack(iLastAttacker, BROADSWORD);break;}case WARRIOR:{Attack(iLastAttacker, SUMMON_DEMON);break;}}}}
}

代码解释:首先,敌人脚本会根据它会被打败的可能性有多大。如果这个结果低于一定的临界值(上述代码是低于20个体力值),那么它就会模拟一个试图从打斗现场逃跑的动作。如果在随机1~10之间随到了1,那么就会逃跑。然而,如果他觉着有必要接着继续打斗,那么它就会调用引擎提供的函数来确定哪个是对手中最弱的。如果敌人觉着玩家比较接近被打败的状态(上述代码是玩家体力值低于20),那么就会进行Meteor Shower来将对手打败。如果这个最弱的敌人并不是十分的弱小以至于很容易被打败出局,敌人就会转去袭击那个最后攻击他的人,并会基于对手的类型选择一个具体的进攻策略。

(笔记)《游戏脚本高级编程》——第2章 脚本编程系统的应用(上)相关推荐

  1. 计算机组成原理笔记(王道考研) 第七章:输入输出系统

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  2. minecraft编程java_第一章 minecraft编程mod

    本帖最后由 ggsshh 于 2017-5-16 11:05 编辑 [size=14.0000pt]第一章 [size=14.0000pt]minecraft编程mod[size=14.0000pt] ...

  3. 11. Python语言的核心编程 · 第十一章 Python语言的面向对象(上)

    Pythin语言的面向对象(上) 1. 面向对象简介 2. 类(class) 3. 对象的创建流程 4. 类的定义 5. 类中的属性和方法 6. 参数self 总结小便条 1. 面向对象简介   Py ...

  4. Python核心编程-第2章-网络编程(1)

    一.基本概念 1.嵌套字 套接字是计算机网络数据结构,它体现了上节中所描述的"通信端点"的概念.在任何类型的通信开始之前,网络应用程序必须创建套接字.可以将它们比作电话插孔,没有它 ...

  5. 计算机组成原理笔记(王道考研) 第四章:指令系统

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  6. 计算机组成原理笔记(王道考研) 第五章:中央处理器

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  7. 计算机组成原理笔记(王道考研) 第六章:总线

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  8. python编程入门经典教程-python编程入门经典

    第七章主要是文件操作相关,这么看用python---便,是一个不错的工具. <Python编程入门经典>主要内容:介绍用于存储和操作数据的变量的概念:讨论用于读写数据的文件和输入/输出:总 ...

  9. python编程入门-Python编程入门经典pdf(Python编程入门教程) 高清中文版

    Python编程入门经典pdf(Python编程入门教程)下载.Python编程入门经典pdf高清版帮助各位更好的进行Python编程的学习以及理解,最经典的课题,最深入的概念,让你在Python编程 ...

  10. 【笔记】Cocos2d-x高级开发教程:制作自己的捕鱼达人 笔记一:序_前言_第一章

    [笔记]Cocos2d-x高级开发教程:制作自己的<捕鱼达人> 笔记一:序_前言_第一章 转载请注明出处:http://blog.csdn.net/l_badluck/article/de ...

最新文章

  1. ubuntu18.04上安装TensorFlow2.0
  2. sqlserver创建对于job失败_创建维护计划失败创建 对于 JobStep“子计划”失败
  3. 判断一个对象是否是可调用对象
  4. 最长公共子序列 nyoj-36
  5. 事务的隔离级别演示-避免脏读,演示不可重复读发生
  6. mysql 加随机数,如何插入随机数MySql
  7. Redis手动failover
  8. SQLSERVER查询存储过程内容
  9. Verilog初级教程(10)Verilog的always块
  10. 58集团监控业务实践:将网站运行信息透明化
  11. 在浏览器中清除缓存和 Cookies
  12. Burp Suite抓包讲解
  13. 起码数学常识凸显中学数学的重大错误0
  14. AI产品经理-人工智能的发展
  15. TX2(Ubuntu16.04)安装TP-link外接网卡驱动及AP热点创建
  16. 【web前端】小人行走
  17. iphone转通用,xib里面的view怎么改成ipad大小?
  18. 使用javamail、阿里云邮箱发送邮件
  19. 淘宝新手入门视频教程哪里有?
  20. Go by Example 中文版

热门文章

  1. ajax上传文件判断大小,JavaScript检测上传文件大小的方法
  2. activiti6创建28张表
  3. 初级程序员和二级Java哪个难,软考初级程序员和计算机二级哪个更受欢迎
  4. 微信小程序实现随机抽签功能
  5. 李雅普诺夫稳定性理论
  6. CAPL-如何调用外部的可执行程序
  7. burpsuite插件xssValidator的安装及使用(XSS自动扫描工具)
  8. kindeditor在线HTML编辑器
  9. aac,ogg等音频测试文件下载地址
  10. vdbench测试过程中遇到的小问题