(笔记)《游戏脚本⾼级编程》——第1章脚本编程概论
1.怎样具体设计⼀个游戏呢?程序员使⽤⼀个编译器将设计⽂档中的具体说明编写成实际的功能程序,美术设计⼈员使⽤Photoshop和3ds max之类的图像处理和⽣成软件将概念艺术和框架转化为具体的图形,⽽⾳乐制作⼈员则利⽤⼀个MIDI⽣成器或其他的跟踪软件将他们脑海中的声⾳转化成⾳乐游戏。那么,问题来了,没有⼯具或器械能够将故事情节和游戏⾓⾊也“输⼊”进去。
2.解决的⽅法:
①让程序员在游戏引擎中⼿⼯编写出所有这些编码。以游戏的物品为例,为描述物体,要写⼀个结构体:
typedef struct _Item
{
char * pstrName; //物品的名称
int iType; //物品的具体类型
int iPrice; //在物品店的价格
int iPower; //具有的能量数量
}Item;
其中iType是物品的类型,游戏引擎需要利⽤这个数据了解该物品被使⽤时应具有什么功能。类似这种描述物品功能的常量应该事先定义:
const HEAL = 0;
const MAGIC_RESTORE = 1;
const ARMOR_REPAIR = 2;
const TELEPORT = 3;
这为选择物品类型提供了⼀个⾮常实⽤的⽅法。如果⼀个物品类型是Heal,那么它存放的就是游戏玩家的健康值。下⼀个是魔⼒值,接着是修复装甲,最后是在⼀定的游戏条件下,游戏玩家由⼀个游戏世界快速跳到另⼀个游戏世界中。
iPower的作⽤是⽆论当你准备使⽤这个物品实现什么样的处理,该物品都应该达到这个数量或者这种程度。即如果物品想要存放HP,⽽且iPower=32,那么玩家就可以取出这32点⽣命值并使⽤它们。
这样就可以定义很多物品了,物品的定义暂且忽略,不过会出现⼀个问题,那就是物品的平衡问题,该问题贯穿整个游戏开发,并不是⼀件⼩事情,要不断地进⾏修改,但是你在游戏引擎中修改后会花费⼤量的时间进⾏重新编译,更加糟糕的是,重新编译的代码中有99.9%的内容并没有改变。
这种⽅法的弊端已经出现了:⾸先,当你直接将你的物品描述实现在游戏代码之中时,你就需要重新编译和它相关的所有内容,浪费了⼤量的时间;其次,是它的组织结构。RPG的游戏引擎问题也很复杂。
②通过将逻辑和具体实现相互分离来改善这种⽅法:
现在问题的关键是如何将游戏代码和游戏内容加以分离。
⽤第①种⽅法定义物品的代码是:
ItemArray[1].pstrName = "Magic Potion Lv 6";
ItemArray[1].iType = MAGIC_RESTORE;
ItemArray[1].iPrice = 250;
ItemArray[1].iPower = 60;
现在,将等号右边的所有内容提取出来,存放到某个ASCII⽂件中:
Magic Potion Lv 6
MAGIC_RESTORE
250
60
这两种⽅法表⽰形式相同,唯⼀的区别是它所封装的所有C/C++代码都是被分离的,在经过以下步骤装载到游戏中:
(1)打开⽂件并确定物品描述数组⾥⾯的哪个索引是⽤来存储相关内容的。可采取循环⽅式
(2)读取第⼀个字符串并将其存放到变量pstrName中
(3)读取下⼀⾏,如果本⾏的内容是HEAL,就将变量iType赋值为HEAL,以此类推
(4)读取下⼀段内容,将其由字符串类型转化为整型并将其存放到变量iPrice中
(5)读取下⼀段内容,将其由字符串类型转化为整型并将其存放到变量iPower中
(6)重复上⾯的(1)~(5)步,知道所有的物品都被赋值为⽌
这样,每次运⾏程序的时候,程序将会在这个ASCII⽂件中读取数据,⽽不⽤重新加载程序代码以修改物品数据,这就是游戏脚本编程的概念。这个例⼦告诉我们所有类型的脚本编程背后的基本准则——如何避免硬编码
3.简单来说,硬编码是指当你想把物品直接写⼊到游戏引擎中时所做的⼯作。也就是⼀种以⼀种严格的、固定的和难以编写的⽅式来编写程序和数据
4.第②种⽅法已经可以满⾜⼤部分的需求了,但是却⽆法从根本上对这些问题加以解决,是因为我们迟早要⽤到⼀些独特⽽⼜复杂的物品,这样的系统所能实现的功能是⾮常有限的。但是如果对单个物品进⾏编码,⽐如加⼊if条件判断写⼊引擎,那么⼜陷⼊了前⾯硬编码的误区。于是,脚本就⽤到了。脚本可以使你真正在游戏引擎之外编码,然后再载⼊游戏引擎中执⾏
5.那么脚本是如何运⾏的呢?脚本和传统变成⾮常相似,唯⼀的区别在于运⾏时它们是怎样被加载和执⾏的。在了解脚本运⾏过程之前,先了解⼀下普通程序是如何运⾏的。
⽤⾼级语⾔编写的代码最终都会转换为低级的,可被机器识别的形式。原因是机器并不能识别这种⾼级语⾔,需要编译器将C/C++这种语⾔转化成为最低级的、字节流形式的纯代码,即转化成为机器码。但机器码难以理解,故⼀般被写成更加容易理解的汇编语⾔形式。
⼀旦代码被编译了,⼀切都会变得更加迅速。编译器将所有编译的代码交给⼀个称为linker(链接器)的程序,它将输⼊的⼤量的指令集封装成⼀个带有⼀定头信息的、简洁紧凑的可执⾏⽂件,并最终⽣成⼀个.EXE(或是其他操作系统使⽤的扩展名)⽂件。当你运⾏这个可执⾏⽂件时,操作系统将调⽤程序装载器program loader(通常简写为loader),它负责将代码.EXE⽂件中抽取出来并将其装载到内存中。然后程序装载器将通知中央处理器内存中第⼀条需要处理的指令的地址,也称为程序⼊⼝点(如C/C++主函数main()的⼊⼝地址)。接着,程序就可以执⾏了。
简单来说,这基本上就是计算机科学背后的哲学体系:将问题和算法转化成为⾼级语⾔代码,将⾼级语⾔代码转换成为低级语⾔代码,让低级语⾔代码通过CPU加以执⾏,从⽽(有望)解决问题。
那么理解脚本的运⾏过程就简单了不少。与上述过程不同的是,脚本编译器不能将源码转化为任何类型CPU的机器码,因为这些代码不会直接运⾏在CPU上,⽽是通过虚拟机运⾏的。虽然虚拟机和CPU⾮常相似,但它们⼆者仍有⼀些不同——虚拟机是软件⽽CPU是硬件。它们的基本⼯作是获取下⼀条将要执⾏的指令,分析指令将要完成的功能并执⾏该条执⾏。不同的是虚拟机只能识别它特定的那种汇编语⾔(字节码)。
虚拟机的另⼀个特性是,⾄少在游戏脚本编程的内部,它通常不是孤⽴的。相反,它是⼀个特殊的“模型”,可产⽣其他程序或与之集成。与CPU很相似,CPU也需要和主板、RAM等东西集成,单纯的CP
U是没有什么⽤处的。与虚拟机集成的程序被称为主应⽤程序,我们最终也是为这个程序编写脚本。
因此,⼀个脚本系统并不仅仅只是为⾃⼰设计⼀个⾼级的、C/C++形式的语⾔,它还需要创⽴⼀种低级的汇编语⾔,即虚拟机器码。
最容易上手的编程语言除了⼀套运⾏环境,虚拟机还为运⾏的脚本和主应⽤程序提供⼀个通信通道,即交互界⾯
主应⽤程序会提供具有⼀组功能函数的运⾏脚本,这些功能函数被称为API
6.脚本系统的基本类型:
时刻牢记:⼤型⽽⼜复杂的特征列表看起来的确很好,但是当你不需要它们的时候,它们就只会使你的程序结构凌乱,运⾏缓慢
①⾯向过程的语⾔系统和⾯向对象的语⾔系统:
这些系统使⽤⾼级的、结构化的或者是⾯向对象的语⾔来编写脚本,这些脚本随后被编译成能够在虚拟机内部运⾏的虚拟机器码,或者不加编译,直接由解释器解释执⾏。系统使⽤的虚拟机或解释器将会与主应⽤程序相集成,使得主应⽤程序可以调⽤脚本并和脚本进⾏交互。特点是⾮常灵活、⾃由,事实上可以适⽤于任何⼀种主要的计算任务
②基于命令的语⾔系统:
通常会像LOGO语⾔⼀样,⾮常具体,它们全部由接受⼀个到两个参数的针对具体程序的命令组成。如下⾯⼀段代码:
MovePlayer 10, 20
PlayerTalk "Something is hidden in "
PlayAnim SEARCH_BUSHES
PlayerTalk "It's the red sword!"
GetItem RED_SWORD
形成这个虚拟语⾔的命令都是⾮常明确的,它们都针对于⾮常具体的某⼀种RPG游戏,都针对于⾮常具体的某⼀种RPG游戏,很少甚⾄没有什么灵活性。
③动态链接的模块系统:
当⼀个复杂的脚本在⼀个虚拟机上运⾏时,它的运⾏速度明显要⽐纯粹的机器码直接在CPU上运⾏的
速度慢得多。为了避免这个问题,许多游戏采⽤动态链接脚本模块。即⼀些C/C++程序段,这些程序段像游戏本⾝⼀样被编译成纯粹的机器码,并且在运⾏时被链接、载⼊。由于使⽤常见的C/C++语⾔编写,运⾏速度特别快,⽽且功能强⼤。
动态链接模块通过游戏向它们提供的API接⼝和游戏进⾏通信。通过使⽤这种API接⼝,模块可以检索和修改游戏的状态信息,从⽽从外部控制游戏。通常被称为mods
④编译型代码和解释型代码:
编译型代码就是那些称为机器码的⼀系列指令,它们就是通过将那些⼈类可以识别的代码转化⽽成的机器可以识别的代码。
解释性代码是通过解释器的程序来运⾏的。解释器是很难实现的,⼀⽅⾯,它们⼏乎要具有编译器所有的复杂语⾔分解功能函数;另⼀⽅⾯,它们⼜要⾜够迅速地解决这些问题从⽽能够达到实时的效果
⑤现有的脚本编程⽅法:
(1)Ruby:
是⼀种完全⾯向对象的脚本语⾔,侧重于系统管理⽅⾯的⼯作。具有⼀系列很好的⾼级特性,如垃圾收集、动态库装载,以及多线程。解释型语⾔
(2)Lua:
Lua是轻量级的强⼤的扩展编程语⾔,⾯向过程的脚本设计系统。最明显的特征是可以⽤它编写的程序来对它⾃⾝进⾏拓展。因此,它的核⼼代码很少,通常是⽤户来实现附加的特征。也能很好地和C/C++进⾏交互
(3)Java:
Java虚拟机,JVM,可以很容易地调⽤本地接⼝JNL和C/C++程序进⾏结合,因为它⼴泛应⽤于专业级的电⼦商务中,所以JVM对于编译脚本来说是最优的多线程运⾏环境,且这门语⾔本⾝也很灵活⽽且⾼度的⾯向对象
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论