This section of the manual contains all the information required to understand and use the GameMaker Studio 2 scripting language GML. The code in this language can be used to create your games and is added into objects from the [Object Editor](, normally when you've chosen to make a new [GameMaker Language Project](, although it can also be used along with [DnD™]( (Drag and Drop). Below you can see a typical image of an object with the code editor open on an event: 本手册的这一部分包含了解和使用 GameMaker Studio 2 脚本语言 GML 所需的全部信息。 该语言用于创建你的游戏,该语言所写代码可以从对象编辑器中添加到对象,一般用于GML项目,也可以和DnD™混合使用(拖拽模式)。 下面是一个在对象中添加事件所打开的代码编辑器的图像: ![]( Each event has its own tab in the editor and you can add, edit, or remove code from them at any time (for more information on events see [Object Events]( The code itself must have a basic structure and can contain resource indices, variables, functions, expressions, keywords... etc... all of which are explained in the sections below. If you are a novice to programming or making the switch from DnD™, it is recommended that you start with the page on Basic Code Structure and then read through them all, testing code from each of the sections within GameMaker Studio 2 itself. 每个事件在编辑器中都有自己的选项卡,您可以随时从中添加,编辑或删除代码(有关事件的更多信息,请参阅对象事件)。 代码本身必须有一个基本的结构,可以包含资源索引,变量,函数,表达式,关键字等...所有这些都会在后面说明。 如果您是编程新手或从 DnD™ 切换过来,建议您从基本代码结构开始全部阅读,在 GameMaker Studio 2 的每个部分测试代码。 * * * * * [基本代码结构 ](代码.md) [(Basic Code Structrue)]( A code block consists of a set of instructions, called statements, that are then interpreted by GameMaker Studio 2 and used to make something happen within your game. That "something" can be as simple as adding 2 and 2 to get 4, or as complex as making an enemy run away when their health gets below a certain value. The actual structure of the program can vary greatly, depending on the functions it uses, but broken down to basics it just looks like this: ~~~ <statement>; <statement>; ... ~~~ Statements should be separated with a ';' symbol to prevent errors with variable declarations and to keep your code clean and tidy, and can consist of variable declarations, expressions and calls to specific functions or scripts. Here is a more visual representation of how a code block can look, this time created as a script in the GameMaker Studio 2 Script Editor: 一个代码块是由几个单句组成的,每个单句之间需要适用“;”做分割。 单句的数量可多可少,取决于模块的功能作用大小,或者说在游戏里面产生的效果大小。例如: ![]( There are a number of different types of statements and functions, which are discussed at length in subsequent sections of the manual. 以上几种不同类型的代码和函数,将在本手册的后续章节中详细讨论。 * * * * * [函数](函数.md) [(Functions)]( The general definition of a function in GML is something like this: 在GML语言中函数的一般定义是 > A function has an input and an output, and the output is related somehow to the input. > 函数具有输入和输出,并且输入以某种方式影响输出。 In GameMaker Studio 2 you use functions as part of the code structure to make things happen in your game and there are a great number of GML functions available to you, all of which are explained in the [Language Reference ]( of the manual. In GML a function has the form of a function name, followed by the input arguments between brackets and separated by commas (if the function has no input arguments then just brackets are used). Here is an outline of the structure of a function: 在GameMaker Studio 2中,您可以使用函数作为代码结构的一部分,以便在游戏中实现一些效果,并且有大量的GML函数供你使用,所有这些函数都在本手册的“**语言参考**”章节中进行了解释。 在GML中,函数有特殊的命名规则,在名称后跟括号,在括号之间的输入参数,并用逗号分隔(如果函数没有任何参数,则只需要使用1个空的括号即可)。 以下是函数命名的1个实例: ~~~ <function>(<arg0>, <arg1> ,... <arg15>); ~~~ Generally there are two types of functions - first, there is the huge collection of built-in functions which are used to control all aspects of your game, and, second, any scripts you define in your game can also be used as a function (but not always). Some functions return values and can be used in expressions, while others simply execute commands, as illustrated in the following two examples: 通常有两种类型的函数。 - 第1种,大量用于控制游戏各个方面的的内置函数(GameMaker Studio 2自带的函数) - 第2种,用户自定义的任何脚本也可以用作函数( 但不全是???)。 某些函数会返回值,并且返还的值可以在表达式中使用;还有些函数只是单纯执行命令并不返还任何值,如以下两个示例所示: ~~~ instance_destroy(); // 销毁正在调用的实例,这个函数不需要任何输入参数,也不返回任何值 Destroy the calling instance - this requires no arguments and returns nothing dist = point_distance(x, y, mouse_x, mouse_y; // 获得当前实例与鼠标焦点的距离,它需要4个参数,返回1个实值(在数学上也称“实数”) Get the distance from the current instance position to the mouse position - takes four arguments and returns a real value ~~~ You should note that it is impossible to use a function by itself as the left-hand side of an assignment. For example, the following code would give you an error: 您应该注意,不可以将函数单独用作**赋值表达式的左侧**。 例如以下代码就是错误的用法: ~~~ instance_nearest(x, y, obj).speed = 0; ~~~ The return value for the expression in that code example is a real number (the unique ID value for the nearest instance) and so it must be enclosed in brackets to be used in this way and properly address the instance required (see Addressing Variables In Other Instances for more information). The above code would be correctly written as: 上面的代码示例中的表达式,返回一个实数(距离最近实例的唯一ID值),因此必须将其(*即instance_nearest()*)括在括号内,以便正确地处理函数的返回的实例(更多信息请参阅在[寻址变量]( 章节)。 所以上面的代码正确写法为: ~~~ (instance_nearest(x, y, obj)).speed = 0; //or或者另外一种写法 var inst = instance_nearest(x, y, obj); inst.speed = 0; ~~~ * * * * * [脚本](脚本.md) [(Scripts)]( Scripts are essentially functions that you write yourself as short snippets of code that can resolve expressions, return values or anything else that the language permits. Basically if you have a block of code that you use in more than one place or object, then it's probably better off in a script, as it means that you can change it once when required and the change will be "picked up" by every object that has a call to the script. They can also be very handy from an organisational point of view, even if the code they hold is called only once by a single object, since it permits you to break large code blocks into more easily managed "chunks" at logical points. 脚本本质上是您自己编写的函数,它们可以是语法允许的任何代码片段,如表达式,返回值等等。 一般来讲,如果你有一个在多个地方、多个对象中调用的相同代码块,那么将这个代码块作为脚本使用可能会更好。因为这意味着你可以在有需要更改它时,只需要在脚本内更改一次,那么所有原先调用这个脚本的对象,都会“更换为”这个已经改变了的脚本。 从文件组织的角度来看,即使脚本的代码只被1个对象调用了1次,它们也非常便捷。因为它允许您将大型代码块分解为更容易管理的1个个包含逻辑代码块的小脚本。 When you create a script the values that you choose to pass into it are called arguments and you'll want to access these arguments - either when using the script action, or when calling the script as a function from a program or from another script. These arguments are stored in the built in variables: 创建脚本时,您选择传入其中的值称为**参数**。 当执行脚本时 ,或者从程序或其他脚本调用该脚本作为函数时,您将需要访问这些参数,而这些参数存储在内置变量中: ~~~ argument0, argument1, ..., etc... up to argument15 ~~~ So there can be at most 16 arguments passed through to a script when called from code using the argument variables, and when using the argument0...15 variables for a script, you must ensure that the script uses all the supplied arguments. For example if you have a script that takes two arguments and you only supply one then you will get an error for that script. The same goes if you supply more arguments than you require. 当调用脚本或者创建脚本时,最多可以有16个参数传递给脚本,这些参数依次命名为*argument0,argument1 ... argument15*,必须确保给脚本提供所有需要的参数,个数不能少也不能多。 例如,如果您创建带有两个参数的脚本,但在调用脚本只提供一个参数,那么您将收到调用脚本发生错误的信息。 如果您提供的参数个数多于脚本需要的参数个数,同样会报错。 However you can supply a variable number of arguments to a script using the built in argument array, and you are not limited to a maximum of 16 arguments either when using this array, but instead can have as many as you require (although, again, you must ensure that all arguments are referenced within the script): 不过您可以使用**数组**做为脚本参数,而数组的元素个数是可变的,这样变相的会得到1个参数数量可变的脚本。而且数组的元素个数可以超过16个,这样你可以根据所需自由使用多个参数(尽管如此, 您必须确保在调用脚本中传入了所有的参数): ~~~ argument[0 ... max_num] ~~~ When passing in a variable number of arguments as an array of values you can use the following function: 将可变数量的参数作为值数组传递时,可以使用以下函数: > [argument_count]( This can be used to find out how many arguments have been passed and adapt the script to use only those arguments supplied. NOTE: You cannot mix the two types of argument variables when calling a script. You must use either argument0...15 or argument[n]. Scripts can also return a value, so that they can be used in expressions. For this you would use the return statement: 这可用于找出已传递的参数数量,并使脚本仅使用提供的参数。 注意:调用脚本时,不能混合使用两种类型的参数变量。 您必须使用argument0 ... 15或argument [n]。 脚本还可以返回一个值,以便可以在表达式中使用它们。 为此,您将使用return语句: ~~~ return <expression> ~~~ It should be noted that the execution of the script ends at the return statement, meaning that any code which comes after the return has been called will not be run. Here is a short example script called "scr_sqr" which calculates the square of whatever value is passed to it, and it includes error catching in case the argument that it is passed is not a real number: 注意:脚本在return语句末尾处结束,这意味着在return语句后所有的代码都不会被执行。 下面是1个简短的名为"spr_sqr"的脚本代码,这个脚本 ~~~ { if !is_real(argument0) { return 0; } else { return (argument0 * argument0); } } ~~~ To call a script from within a piece of code, just act the same way as when calling functions - that is, write the script name with the argument values in parentheses. So, the above script would be called like this: 要从一段代码中调用脚本,只需采用和调用函数时相同的方式 - 也就是说,"脚本名称(参数值)"这样的形式。 所以,上面的脚本调用将变成如下形式: ~~~ if keyboard_check_pressed(vk_enter) { val = scr_sqr(amount); } ~~~ It is worth noting that when writing your own scripts they can also have certain JSDoc style comments added so that when you use them in your code they show up in auto-complete along with their arguments and other details. you can find out more about this from the section [JSDoc Script Comments]( for more information. Further note that when you are typing out your scripts in the code editor, you can click or use the middle mouse button on the script name to open it for editing directly. 值得注意的是,在编写自己的脚本时,也可以为脚本添加某些JSDoc样式注释,这样当您在代码中使用它们时,它们会自动补全,并显示参数和其他详细信息。 您可以从**[JSDoc脚本注释]**章节中了解更多信息,以获取更多信息。 另请注意,在代码编辑器中键入脚本时,可以单击或使用脚本名称上的鼠标中键将其打开以进行直接编辑。 ***** [注释](注释.md)[(Comments)]( When working in collaboration with other people, when dealing with a large project, or even just for your own reference and debugging, leaving comments in your codes and scripts is very important. In GameMaker Studio 2 you have various mechanisms to help you leave notes and comments about code sections and even whole blocks of code that can be seen in the event list of the object that you are currently editing, and in this way you can leave notes to yourself and to your colleagues, or to explain a particularly tricky piece of code, or even just leave a reminder about what something does. 为你的代码和脚本写注释,这对团队协作、处理大型项目、为你自己留下参考信息都是非常重要。 在与其他人合作时,在处理大型项目时,甚至只是为了您自己的参考和调试时,在代码和脚本中留下注释非常重要。在GameMaker Studio 2中,您有各种方法可以帮助您留下关于代码部分的注释,甚至可以在您当前正在编辑的对象的事件列表中看到的整个代码块,这样您就可以留下注释你自己和你的同事,或解释一个特别棘手的代码,或者只是提醒一些代码的作用。 The first thing you can do is leave a short comment using // before the text. For example: ``` //initialize variables sr = 10; hp = 100; ``` You may also leave multi-line comments, to give credit, to omit a complete section of code for debugging, or even to explain the arguments of a script. For that you can use /* ... */ like this: ``` /* usage: diff = angle_difference(angle1,angle2); angle1 first direction in degrees, real angle2 second direction in degrees, real returns: difference of the given angles in degrees, -180 to 180 */ { return ((((argument0 - argument1) mod 360) + 540) mod 360) - 180; } ``` Finally, if you are writing custom scripts and want to have some control over how they are treated by the IDE (ie: have auto-complete or show the script arguments) then you should be writing your comments using JSDoc notation as explained here. ***** [保留关键字](关键词.md) ***** [变量及作用域](变量及作用域.md) ***** [在其他实例中寻址变量](寻址变量.md) ***** [评估顺序](评估顺序.md) ***** [数据类型](数据类型.md) ***** [数组](数组.md) ***** [赋值](赋值.md) ***** [表达式](表达式.md) ***** [访问器](数据存取.md) ***** [功能性语法](功能性语法.md)