GameMaker8.0 新手教程 Part 9 -数组-

分类栏目:gamemaker教程

572

GameMaker8.0 新手教程 Part 9 -运动初步-

1、概述

所谓数组(Array),是有序的元素序列。说的通俗一点,“数组”和高中数学的“数列”基本是一回事。一个数组内包含多个元素(GML内指实数和字符串,GML外还有更多类型),且这些元素是有排列顺序的。
来回忆一下高中数学的数列:
一个数列{Xn},它所含的不同元素用下标来区分,即以X1,X2,X3来表示数列{Xn}的第一项,第二项,第三项元素。在解题中,我们可能不会直接使用数字下标,如:X(m+2) = 2 * Xm,通过未知数m来表示下标,以便于求解m。如果我们解出m = 6,那么很显然,在这里X8 = 2 * X6,即:X(m+2)和X8都表示数列{Xn}的第八项元素。
数组也是相同的道理。
数组元素的表达形式是:数组名[表达式]。即,若存在一个数组num,那么它的元素用num[5],num[12]这样来表示。因此,[]被称为下标运算符。
注意:数组的第一个元素是num[0]不是num[1]。不仅是数组,任何索引都是从0开始,而不是从1开始。从零开始的索引并不是GM的特点,而是几乎所有语言的通性。习惯这一点对你学习更高等的语言有很大的帮助。
与数列相同的,数组元素的下标也可以用未知数和表达式表示。
如:
num[8-3*2]和num[2]是同一个元素,
若m = 6,则num[m-3]和num[3]是同一个元素。
也可以将返回值是整数的函数作为下标:
num[irandom(8)]会随机挑选num[0]到num[8]之间的某个元素。

2、数组元素的一般性

数组元素在代码中的地位与普通变量完全相同。即,普通变量能做的,数组元素都能做。
①赋值:

num[0] = 5;
num[1] = num[0] + 2;
num[2] = num[1] * num[0];

②运算:

a = 3;
num[0] = irandom(6);
b = a + num[0] * 6;

③逻辑判断:

num[0] = 12;
num[1] = 14;
if(num[0] > num[1] && num[0] > 0)
num[0] -= num[1];

④作为函数参数:

xx[0] = 100;
xx[1] = 200;
instance_create(xx[0], 100, objBullet);
instance_create(xx[1], 100, objBullet);

⑤作为脚本的返回值:

//这是一个脚本
{
var _array; //声明临时的数组,只需要声明数组名
_array[0] = argument0;
_array[1] = argument1;
_array[2] = _array[0] + _array[1];
return _array[2];
}

⑥作为全局数组:

global.BOSS[0] = 1;
globalvar BOSS; //同样只需要声明数组名
BOSS[0] = 0; //global.BOSS[0]和BOSS[0]是同一个数组元素
show_message(string(global.BOSS[0]));//此时输出0而不是1

3、数组元素的特殊性

说到数组元素的特殊性,毫无疑问就是数组的下标可以用表达式表示。这个特性可以方便我们做很多事。
例如:

for(i = 0;i < 10;i += 1)
inst[i] = instance_create(400,400,objBullet);

根据for语句的效果,将在房间中创建10个objBullet的实例,并且这十个实例的索引(ID)分别被储存在inst[0]到inst[9]中,这样就可以分别控制十个实例。
例如:

for(j = 0;j < 3;j +=1)
inst[j+2].speed = 6;

这样,inst[2],inst[3],inst[4]所表示的三个实例,就会以速度6开始运动。

4、计时器事件(Alarm Event)

现在我们可以来重新审视一下计时器事件(Alarm Event)。
GameMaker8.0 新手教程 Part 9 -数组-
计时器事件在GM中也是以数组的形式表现的。

alarm[0] = 50;

表示在50步之后执行alarm0号事件。
注意:alarm事件的调用代码也可以写在alarm事件,比如在alarm0号事件写alarm[0] = 10;,那么就会循环每隔十步执行一次alarm0号事件。

在我们学习完数组之后,我们就可以让alarm事件变得更骚:

alarm[irandom(4)] = 10;

10步之后随机执行alarm0~4号事件。

for(i = 0;i < 3;i += 1)
alarm[i] = i * 10;

10步之后执行alarm0号事件,20步之后执行alarm1号事件,30步之后执行alarm2号事件。
即,每隔10步执行一个事件。

5、二维数组

所谓二维数组,就是通过两个值来确定一个数据,比如a[5, 6],在方括号内用逗号隔开。二维数组可以当做是一个书架,a[5, 6]指第五行,第六列的书(数据)。二维数组的使用等同于一维数组,但是使用二维数组能更好的控制平面的内容。比如在房间内均匀创建6x6一共36个objBullet,那么就可以用二维数组来分别储存控制这36个实例:

for(i = 0;i < 6;i += 1)
for(j = 0;j < 6;j 6= 1)
inst[i, j] = instance_create(i * 100, j * 100, objBullet);

注意inst数组的取值范围是inst[0~5, 0~5]。

6、扩展:GM数组的特殊性

在GM8中,务必记住一个特点:数组名等效于零号元素。
即,对于任意的一个变量名而言,a和a[0]代表同一个变量。即使a本身并不是一个数组,你仍然可以用a[0]来表示它。不仅是自定义的变量,GM8内置变量也是如此,如view_xview和view_xview[0]完全等效(该变量参见“视野”一章)。因此,GM8的脚本并不能传递数组,即使将数组名作为参数或者返回值,实际上只是传递了零号元素的值罢了。
而在GMS2中,存在“重定义”(或覆盖定义)的概念,即在已经定义a的情况下,定义a[]会重定义a为数组,那么原本变量a会被删除,之后a就只能作为数组名来使用了,反过来说,定义a也会覆盖定义a[]。在GMS2中脚本可以传递数组,但是必须在脚本中使用访问器来访问,例如:

{
var a = argument0; //假设argument0传递的是一个数组
a[@ 0] = 5;
a[@ 1] = 6;
}

如上所示,[@ x]就是数组的访问器了。由于这里是GM8的教程,所以不再详讲访问器。

注意,这是GM数组的特殊性,在绝大部分别的语言中并非如此。