SQF入门经典.docx_第1页
SQF入门经典.docx_第2页
SQF入门经典.docx_第3页
SQF入门经典.docx_第4页
SQF入门经典.docx_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

中国虚拟军事网SQF脚本入门经典(第二版)原文名称:Basic SQF scripting v.2作者:Taurus翻译:胡皓(Alex.XP)教程介绍这个教程将会使您对SQF语法拥有一个基本的理解。我看到许许多多的人们需要一个通俗易懂的文章来告诉他们如何在搞定一大堆游戏以外的琐事之后编写出小小的扩展内容。但是,我并没有发现有这样的文章,所以我决定自己来写一个。脚本编写准备工作 根据您的习惯选择使用Windows自带的记事本程序或者一个专门的文本编辑器。 将武装突袭2:脚本命令索引的链接保存到您的浏览器收藏夹中。 关闭Windows的“隐藏已知文件类型的扩展名”功能,该选项位于:Windows资源管理器 工具 文件夹选项 “查看”选项卡 在您的武装突袭2游戏快捷方式中添加 -showScriptErrors 启动参数,比如:Bohemia InteractiveArmA 2arma2.exe -showScriptErrors 学习一些基本的任务编辑器知识,您可以参考/wiki/ArmA:_Mission_Editor武装突袭:任务编辑指南。 明确您想要在脚本中实现什么样的功能,最好能够做一个脚本开发计划而不是随意乱写。 持之以恒。任务文件的位置Windows 7%appdata%DocumentsArmA 2 missions. 比如.TaurusmissionsMyMission.utes 脚本编写的基本概念武装突袭2里拥有两种类型的脚本: 函数(Functions) 程序(Procedures)在这篇教程里将会出现很多这两种类型的脚本。函数和程序通过以下语句进行编译:compile preProcessfile filename.sqfcompile preprocessFileLineNumbers filename.sqfpreprocessFileLineNumbers会返回脚本中产生编译错误或者命令错误的代码所在的行号。当您使用execVM命令时,您不需要刻意去编译这些文件,游戏引擎将会自动利用preprocessFileLineNumbers命令进行处理。传递进来的参数由“魔术般的”局部变量_this来表示,比如:_this select 0;这段代码将会获得传递进函数或者程序中的参数数组中的第一个元素。参数总是通过数组进行传递,你将会在后面的学习中对此有进一步了解。如果您决定将脚本文件放置到单独的文件夹里,那么以后可以通过 mission.sqm 文件的相对路径来定位它们,比如:MyFunction = compile preProcessfile MyFunctionsMyFunction.sqf;脚本文件通过以上提到的两种编译选项进行编译:preProcessfile,preprocessFileLineNumbers它们可以包含注释类型的代码段(就像C+、Java、Javascript那样),比如:/单行注释/* 可以拥有一行、两或者更多的多行注释 */通过使用注释代码段,您可以方便的对代码进行注释性的操作,比如这是干什么的、为什么要这样、需要用那些参数,甚至可以包含作者信息等等。有关变量(Variables)的使用,请查看有关变量的专题部分。我的第一个程序(Procedure)运行武装突袭2,在编辑器中打开一个新任务,在这里推荐使用Utes岛屿。在地图上放置一个您所喜欢的阵营的士兵,然后在这个单位的Initialization(初始化)栏中输入以下内容:MyProcedureHandler = this execVM MyProcedure.sqf输入完毕后点击确定(OK)按钮。在紧挨着这个士兵的地方放置一辆空的悍马(Hmmwv)车,然后将这个任务保存成名为 MyMission 的任务。现在,请从先前所介绍过的任务文件位置打开您的任务文件目录,然后打开名为 MyMission.utes 的文件夹,在这个文件夹中你将会看见一个名为 mission.sqm 的文件。在这个文件夹中新建一个文本文件,然后将其重命名为 MyProcedure.sqf,然后用鼠标右键单击并打开这个文件,您可以选择使用Windows的记事本工具或者其他文本编辑工具作为这个文件的默认运行程序。然后输入以下内容:_myGuy = _this select 0;/This is a while loop which will run until _myGuy dieswhile alive _myGuy do /HintSilent will show the text in the upper right cornerhintSilent format Current speed: %1, round(speed (vehicle _myGuy);/And update the value every second.sleep 1;保存(快捷键:Ctrl + S)并关闭这个文件。现在回到武装突袭2的编辑器中预览(Preview)这个任务,控制您的角色在周围跑一跑并进入你放置的那辆悍马车,自此期间请注意画面右上角所显示的当前速度(km/h),然后开动车辆。你会注意到右上角所显示的速度与游戏界面默认显示的车辆速度是一样的,只不过它比默认速度更新的更慢一些,你可以将代码中的 sleep 1 改成 sleep 0.125 以使得数值更新频率更快一些。最后退出任务预览。我的第一个函数(Function)现在请在您的任务中放置一个Radio Alpha触发器(Trigger),然后在 On Act. 栏中输入以下内容:player sideChat format %1,player call MyFunction点击确定(OK)按钮并保存任务。现在请回到您的任务文件夹,新建一个名为 init.sqf 的脚本文件,这个脚本文件是您的任务的初始化文件,并且将会在游戏单位的Initialization(初始化)栏内容加载之后运行。用和前面一样的方法打开 init.sqf 脚本文件并且输入以下内容:MyFunction = compile preProcessfile MyFunction.sqf保存(快捷键:Ctrl + S)并关闭这个文件。新建另一个脚本文件并命名为 MyFunction.sqf,并输入以下内容:_myGuy = _this select 0;/Variable to hold the out value_myOutStr = Im not in a vehicle!;/Checks whether or not the unit is in a vehicleif(_myGuy != (vehicle _myGuy) then _myOutStr = Im in a vehicle!;/Return value_myOutStr保存(快捷键:Ctrl + S)并关闭这个文件。现在,请再次回到游戏编辑器并且预览这个任务。利用游戏中的无线电呼叫Radio Alpha然后观察您都说了些什么,然后退出并重新执行任务预览,这次请进入悍马车并再一次呼叫Radio Alpha,您将会立刻向您的当前阵营频道说出您现在是否在一辆载具内。最后请退出任务预览。程序(Procedures)程序按照游戏的执行顺序,通过spawn或者execVM命令来执行。在游戏单位的Initialization(初始化)栏中的执行方法:MyProcedureHandler = this execVM MyProcedure.sqf;程序无法从游戏单位的Initialization栏中spawn(重生),除非程序在spawn之前被初始化,关于这方面的内容将不涵盖在此教程中。在 init.sqf 初始化脚本文件中的执行方法:MyProcedureHandler = this execVM MyProcedure.sqf;_myProcedureHandle = MyVariable spawn MyProcedure;在触发器(Triggers)的 onAct, onDeAct 栏中的执行方法:MyProcedureHandle = MyVariable spawn MyProcedure;所有的脚本都需要拥有一个如上方所显示的脚本处理(Script Handle)命令来执行,这些脚本处理命令并不需要是唯一的,除非您打算在后期阶段使用它们,接下来我们就来介绍这一方面。脚本处理命令能够用来检查一个脚本是否已被编译,比如:_myProcedureHandle = MyVariable spawn MyProcedure;waitUntilscriptDone _myProcedureHandle;另外,脚本处理命令还能够用来结束脚本。例如如果您想要在10秒之后结束脚本,而不管它现在是否已经执行完毕:_myProcedureHandle = MyVariable spawn MyProcedure;sleep 10;terminate _MyProcedureHandle;所有的代码段都必须以 ; 来关闭,比如:hint Hello;程序能够被如下代码停止执行:sleep X;X 代表需要停止(暂停/休眠)执行脚本的时间(单位:秒),比如:sleep 10;程序将在脚本最开始的时候被执行。函数(Functions)函数按照游戏的执行顺序,通过call命令来执行。在游戏单位的Initialization(初始化)栏中的执行方法:函数无法从游戏单位的Initialization栏中直接call(调用),除非函数在call之前被初始化,关于这方面的内容将不涵盖在此教程中。在 init.sqf 初始化脚本文件中的执行方法:MyFunction = compile prePreprocessfile MyFunction.sqf;_myFunctionRetVal = MyVariable call MyFunction;或者MyVariable call MyFunction;在触发器(Triggers)的 condition 栏中的执行方法(必须拥有返回值):(MyVariable call MyFunction) = 0)在触发器(Triggers)的 onAct, onDeAct 栏中的执行方法:MyVariable call MyFunction;或者MyFunctionRetVal = MyVariable call MyFunction;函数可以(或者不可以)拥有返回值,比如:MyFunctionRetVal = MyVariable call MyFunction;这段代码拥有返回值,而MyVariable call MyFunction;则没有返回值。所有的代码段都必须以 ; 来关闭,除了从函数中返回值的代码段,比如:_myVariable = Returns Hello;/Return value_myVariable函数无法像程序那样被暂停或者休眠。函数将会暂停脚本的执行,直到函数执行完毕。变量(Variables)变量必须通过设置默认值来进行定义和初始化,比如:_myString = “”;_myArray = ;_myNumber = 0;_myBoolean = false;_myObject = objNull;或者直接通过别的值来初始化,例如:_myString = format %1,name player;_myArray = _someOtherArray;_myNumber = (1 + 1);_myBoolean = (side player) = west);_myObject = player;这些变量必须放置在一个范围(scope)内,比如代码块(Block)或者控制结构(Control Structure)。代码块就是 标记之间的部分。使用下划线 _ 定义的变量为脚本中的局部变量,而不使用下划线定义的变量为全局变量,全局变量能够被其他的脚本读取或者赋值,例如:MyProcedure.sqfMyVariable = Will be overwritten; /Can be read or set from other scripts_myFunction = compile preProcessfile MyFunction.sqf;_fromOther = call _myFunction;/Shows “Returns Hello, Global Hello” on the screenhint format %1, %2, _fromOther, MyVariable;MyFunction.sqf_myVariable = Returns Hello; /Local to this script onlyMyVariable = Global Hello; /Can be read or set from other scripts/Return value_myVariable全局变量也可以被定义为公共变量,比如:publicVariable MyVariable;这将在多人游戏环境下利用网络把 MyVariable 变量的值广播到其它计算机。关于本地及多人游戏环境的内容将不涵盖在此教程中。有关变量的更多内容变量所能使用的不同类型的值叫做“数据类型”(Data Types),有关数据类型的更多信息请查看附录中的数据类型部分。如何对这些数据类型进行相互比较的操作被称为“运算符”(Operators),有关运算符的更多星系请查看附录。我在什么情况下需要编写脚本?注意:编写脚本并不能解决所遇到的全部问题。首先您必须自己问自己:“我是否能够完全确定仅仅依靠游戏编辑器已无法解决我所遇到的问题?”编写脚本的目的在于创建某种过程来解决其它任何方式都无法解决的问题。脚本将会占用系统资源,恶劣的脚本将会严重影响游戏的进行和性能。所以,请确定您已经尽可能多的了解了游戏编辑器的工作方式以及它的优缺点。第二件事是当您开始编写脚本的时候需要自己问自己:“我所想要实现的东西是否能够得到玩家的普遍关注、认同或者使用呢?”这个问题看起来比较愚蠢,但是请记住:能够去做并不代表应该去做。第三步(经过先前两步之后这将是最为艰难的一步,尤其是对脚本编辑一窍不通的新人来说)是去尝试并下定决心利用来实现您想要实现的东西(这一段来自BI官方维基)。脚本能够帮助您完成在游戏编辑器里不可能完成的事情,例如,在任意一个制定的时间将一个单位重生或者移动到一个动态的位置、进行距离计算、获取当前飞机的飞行高度、批量为单位命名等等。如果您想要将脚本代码写得通用和规范,那么您应当将每一个任务写成一个脚本。在您将一个单位(您作为玩家)作为参数传递到脚本的时候,请牢记在“我的第一个函数”教程中所学习到的东西。那么如果您想要检查一个由AI控制的单位是否在载具里的时候需要怎么做呢?您应该将这个AI单位命名为 MyGI_1,在“我的第一个函数”教程的案例中您只需简单的改变玩家参数:player sideChat format %1,MyGI_1 call MyFunction如果您想要检查全部单位的话则需要在触发器的onAct.栏中写入脚本代码:player sideChat format %1,player call MyFunction; player sideChat format %1,MyGI_1 call MyFunction请注意两端代码之间的 ; 标记,; 用来分割这两端代码,就好在脚本中像重起一行那样。最优方法变量(Variables)应当通过private命令进行设置,这样是为了避免变量在脚本执行之后被其它的脚本执行过程所意外覆盖。有关private命令的使用方法请参看下方的示例,代码块的作用已做了相应注释:private _myVariable,_myString;/*_myHandler = spawn MyProcedure*/_myVariable = _this select 0;/*defined here, and set by either result from the if-else statement.If not defined here, the last line would failed with variable notdefined*/_myString = ;if(_myVariable = Hello) then/Block 1_myString = He said hello!;_myBlockNumber = 0; /this variable cannot be read from codeoutside this block or scope.else/Block 2/*i.e. this wouldnt workhint format %1,_myBlockNumber;*/_myString = He didnt say hello, what manners!;/Will show He said hello or He didnt say. hint format %1, _myString;在先前的“我的第一个”示例中,我们故意忽略了private命令的使用。全局变量(Global Variables)、程序(Procedures )以及函数(functions)应当像先前“我的第一个函数”示例中那样在初始化脚本 init.sqf 文件中被提前定义,除非您确定该程序只被使用一次。当您在程序中使用循环语句时,应在循环代码块中加入sleep X;语句,这样是为了防止游戏变得越来越慢直到卡死,同样这也是为了让CPU在处理您的循环语句时能够有足够的能力来应付其它的工作,比如:whilealive _myGuy do /My code here and here and etcsleep 0.125;如果您想要sleep一个waitUntil命令来实现“等待并直到脚本完成”时,比如:waitUntilsleep 0.125;(myCondition);这段代码中的最后一行用来返回一个值,所以就好像函数中返回值那样,不能使用 ; 来作为结束。当需要在游戏运行时处理复杂的脚本,或者包含有各种各样的循环操作时,比如跟踪某个单位的移动,检查某个值是否为true等等,应当使用程序(Procedures)。当需要处理某个返回值,或者您需要在某个条件出现时停止脚本运行的情况下,应当使用函数(Functions)。当您想要建立一

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论