Expressions And Operators

表达式

表达式是一个数学短语,可以包含普通数字、变量、字符串或函数以及一个或多个运算符(例如加、减、乘等)。表达式中使用的值可以是实数(例如3.4 * 6)、以$符号开头的十六进制数(例如$00FFAA | $88FFAA)、双引号之间的字符串(例如"hello"+"world") 或更复杂的使用多个运算符和值的表达式。

运算符

以下是提供给表达式使用的运算符。

Assigning (=)Assigning (=) 赋值

=用于给变量赋值。请注意,这可用于比较GameMaker中的变量,您可能会在示例和其他人的代码中看到这一点。不过,这是旧的GameMaker版本的遗留问题,您应该使用==运算符进行比较,使用=进行分配,如以下示例所示:

a = 12;
speed = 5;
val = (old_val + 5);

 

Combining (&&, ||, ^^)Combining (&&, ||, ^^) 组合

&&||^^(andorxor)用于组合布尔值给出truefalse的值。如果以下任何示例解析为true,则代码将运行:

if (a == b && c == d) { do something... }  // and
if (a == b || c == d) { do something... }   // or
if (a == b ^^ c == d) { do something... }  // xor

 

Nullish (??, ??=)Nullish (??, ??=) 空值合并

注意"空值"只是指等于undefinedpointer_null的一个值。

?? 是一个空值合并运算符,如果给定值是 undefinedpointer_null,则返回指定的表达式。该运算符希望使用以下语法:

(input ?? null_output)

如果input(输入)是undefinedpointer_null,该表达式将返回null_output(输出)值;但是在其他情况下,它将仅仅返回input值。这可以用来定义一个变量的 "默认 "值,以防止该变量本身不包含一个有效的值。

请考虑以下例子:

username = data.username ?? "INVALID USERNAME";

在这里,username变量将获得存储在data.username中的值,但是如果data.username恰好是undefinedpointer_null,该变量将获得字符串"INVALID USERNAME"代替。这个例子确保了任何使用username变量的函数调用不会因为被赋予一个空值而导致错误,并且用户知道他们的用户名没有被返回。

注意只有当输入值为空值时,空值合并运算符右侧的表达式才会被执行,这意味着只有当输入值为空值时,RHS表达式中包含的任何函数调用才会被执行。


??=与上述的空值合并运算符类似,但专门用于变量赋值。这个运算符希望使用以下语法。

variable ??= null_value

如果variableundefinedpointer_nullnull_value值将被分配给它;否则变量将保持不变。这可以用来在变量持有空值时为其分配一个自定义的 "默认 "值。

 

Comparing (<, <=, ==, !=, >, >=)Comparing (<, <=, ==, !=, >, >=) 比较

<<===!=>>=是比较,只能给出truefalse结果(其中true也可解释为 1,false也可解释为 0)。使用示例:

if (a < b) {do something...}
if (a != b) {do something...}

NOTE 

Bitwise (|, &, ^, <<, >>)Bitwise (|, &, ^, <<, >>)

|&^<<>>用于执行按位运算,其中|= 按位或,&= 按位与,^= 按位异或,<<= 左移,>>= 右移。使用示例:

x = (x & $ffffffe0) + 32;
if (y ^ $1f) > 0 {do something...};

您可以从按位运算符部分找到有关如何使用按位运算符及其用途的更多信息。

 

Arithmetical (+, -, *, /)Arithmetical (+, -, *, /) 算术

+, -, *, / 分别是加、减、乘、除。使用示例:

c = a * b;
str = a + "world";

注意浮点数不会在除以零时停止,因为它们将得到无穷大作为答案。如果 A 和 B 是整数(int32 或 int64),则除法将作为整数进行(并且除以 0 将被检查并出错)。否则,它将作为浮点除法完成(不进行除以 0 的检查)。

 

Increment/Decrement (++, --)Increment/Decrement (++, --) 递增递减

++, -- 用来从一个值中加减(1)。值得注意的是,将其放在要加减的数值之前或之后,会有稍微不同的结果。例如。

因此,如果你有这样的东西:

var a = 1;
show_debug_message(string(a++));
show_debug_message(string(++a));

调试输出将是1和3。下面是一些使用的例子:

for (var i = 0; i < 10; i++;)
{
    do something...
}

if (hit == true)
{
    --score;
}

注意在YoYo编译器目标平台(标记为(YYC)的平台)上,这些表达式从左到右计算,而在所有其他目标平台上,它们从右到左计算,这意味着:

val = max(num, ++num, num++);

将根据平台的不同给出不同的结果。

 

Division and Modulo (div, %, mod)Division and Modulo (div, %, mod) 除法和模

divmod(或%)是除法和取模,其中div给出了一个值可以被划分为仅产生的数量整数商,而mod(或%)仅提供除法的余数。使用示例:

secs = time mod 60;
secs = time % 60;    // Identical to the above line
time_str = string(time div 60);

 

Unary (!, -, ~)Unary (!, -, ~) 一元

提供了以下一元运算符。

 

表达式组

作为所有表达式中的值,您可以使用返回值的数字、变量或函数,子表达式也可以放置在括号之间。所有运算符都适用于实数值,但比较也适用于字符串,并且"+"运算符可用于连接字符串。

在一个表达式中进行多个操作时,使用括号()来区分操作顺序是非常重要的,因为如果没有明确说明,不同的平台可能会有不同的执行方式。例如,考虑下面的代码:

a = b == c || d;

不同的目标编译器将以不同的顺序执行操作,因为它们没有明确显示,引起 "奇怪 "的结果,当你玩你的游戏时,你可能没有想到。为了避免这种情况,使用()来分离出部分,像这样:

a = (b == c || d);   //better
a = ((b == c) || d); //best

语句分组

当在单个代码块中使用各种操作和表达式时,它们也应该分开。例如,以下看起来是有效代码:

if my_var == your_var ++their_var;

然而,编译器可以用两种方式之一来解释这一点:

if my_var == your_var++ then their_var;

// or

if my_var == your_var then ++their_var;

现在,你看了这段代码就知道,其中一个有点愚蠢,但那是因为我们知道我们想要实现什么,我们想要发生什么,但编译器不知道。它所看到的是两个变量和它们之间的++运算符,所以它必须选择哪一个来应用它。因此,你应该总是明确地将表达式、运算和语句括起来。上述代码的正确版本应该是。

if (my_var == your_var)
{
    ++their_var;
}

这样做可能会显得比较啰嗦,但对所执行的操作没有任何歧义,而且它在所有平台上的编译和行为也是一致的。还要注意的是,虽然你现在可以不使用方括号来链接表达式和语句,但这是一个遗留函数,今后可能会被废弃并从GML中删除,所以现在适当地使用方括号将 "证明 "你的代码(而且通常是好的做法)。

下面是各种不同表达方式的一些最终例子。

{
    x = 23 div 2;
    colour = $FFAA00 + $00BB12;
    str = "hello" + "world";
    y += 5;
    x *= y;
    x = y << 2;
    x = 23 * ((2 + 4) / sin(y));
    b = (x < 5) && !((x == 2) || (x == 4));
}

最后要注意的是,还有一些表达式的 "捷径",称为访问器,用于某些数据结构数据结构。数据结构和数组。这使你能够在这些格式中快速、轻松地添加或替换数据,而无需使用任何函数调用。完整的细节,请参见以下页面