撰写了文章 更新于 2018-04-18 16:49:48
GML 学习手记(GML概况二)
变量和变量范围
这次这篇手记,继续接上一篇。本篇手记主要讲的是GML中的变量。就像别的编译器一样,GML也是使用变量来作为最基本的单元来进行之后一系列的编译过程。变量用于存储设备内存中的信息,以供之后(或现在)使用。这些变量将会被赋予一系列的名称,方便我们在函数和程序中引用他们。还有就是上一篇所说的变量可以存储一个值,也可以是一个字符串。我们使用变量来存储一个值,并把他们用在一个或多个的程序或是函数中。
现在,我们来思考一个变量"pi",这是一个现实世界就存在的一个变量,并且它的值就是3.1415926(etc...)。当大家提起"pi"的时候,很容易就会让人想起3.1415926(etc...)。所以,在编程中,把一个变量命名会方便很多,如果变量的值发生了变化,我们不需要在程序中逐个进行修改,因为变量的名称是不会改变的。还有需要注意的是,在命名的过程中需要遵守一定的规则,在GML中变量的名称必须要以字母开头,变量名称只能包含字母、数字和下划线"_",并且变量名称的最大长度为64个符号。在编译的过程当中,我们需要先“声明”一个变量,我们才能在后边的编译过程中使用它。简单的来说,就是我们事先告诉计算机我们想要用这个名称,让计算机在内存中为我们分配一个地方,在这个地方我们可以存储我们想要的值。
在GML中,有四种主要的变量类别,每个类别都有自己的适用范围(可以理解为它的操作的范围或是定义域),下面就是这些变量类别以及它们的范围:
- instance(实例变量):这是最常见的变量,并在实例中定义。这是实例所特有的,并且可以用于任何event(事件)和该实例中的审核函数。(感觉这一段我有点翻译错误。。。。。。)
- local(局部变量):这类变量在定义时,必须使用"var"函数来声明这些变量。局部变量只对创建它的event(事件)和script(脚本)有效。所以,GMS在创建这类变量之后,会在event(事件)持续的时间范围内使用这个变量,但是当这个event(事件)结束之后,GMS将会“忘记”这个变量。因此,在之后你再次使用这个变量时,将会出现一个"unknown variable"(位置变量)的错误。
- global(全局变量):全局变量是属于游戏世界的一种变量,并不是实例。它必须优先设置为全局变量。但在此之后,任何实例都可以检查或修改它的变量,并且无论哪一个实例或是程序对其进行操作,它的值都将反映对这个变量的最后操作。
- built in variables(内置变量):这类变量十分特殊,它们是游戏世界中“内置”room(场景)和object(对象)的一类变量。他们可以是实例,也可以是全局变量(但不是局部变量)。
需要说明的是我在变量范围中加粗的room(场景)和object(对象)和event(事件)和script(脚本),这些东西是GMS中的各项操作界面。
接下来,就按照上面的顺序来讲一下这几类变量。
1、Instance Variables(实例变量)
一个实例变量的范围取决于创建它的实例。实例变量由object(对象)中的实例所创建。实例变量在该实例中被认为是唯一的,即在同一个object(对象)中,许多不同的实例可以拥有相同的一个变量,但是这些变量可以拥有不同的值,因为这些变量对于他们各自的实例来说都是唯一的。下面就是创建实例变量的例子:
potions = 12;
life = 100;
name = "Jock MacSweeney";
strength = 5.5;
armour = -2;
我们只需要给出一个名称和一个值(可以是一个数,也可以是字符串)就可以来设置一个变量。接下来,我们就可以在需要用到它的object(对象)的实例中使用它。而且,在之后我们可以用多种方法修正这个变量的值。比如,在一些event(事件)中让变量"life"(生命)减去一定的值:
life -= 5 + armour;
现在变量"life"(生命)就等于97。(接下来的一段话我翻译了好久,有好多修饰词,我的天,废话贼多,看得我好累,我就说一下重点)设置一个变量的好处是当我们需要修改其中的值时,只需要在一个地方修改即可,也容易我们纠错,让编译的过程变得更加灵活。
需要注意的是,GMS内置了许多实例变量名称,所以当我们在命名变量的名称的时候,我们需要避免与这些内置的变量名称相冲突。但是,这也很容易发现,因为在编译器中他们会显示不同的颜色,并且在自动完成栏中也会显示出来。
2、Local Variables(局部变量)
局部变量是我们为特定的事件所创建的一个变量,当这个事件结束时,这个局部变量将会被丢弃。这可以使得我们的代码库保持干净整洁,保持内存空间的优化,以最优的方式处理问题。且我们在命名局部变量的时候,要注意变量名称是否与对象中的实例变量的名称有冲突,同时还要确保不与事件之外的其他变量名称相冲突。下面是声明局部变量的例子:
var i = 0;
repeat (10)
{
inventory[i] = 0;
i+=1;
上面的代码用"i"这个变量来初始化一个数组。
下面还有一个例子:
var xx,yy;
xx = x - 32 +irandom(64);
yy = y - 32 +irandom(64);
instance_create(xx, yy, obj_blood);
上面的代码使用了局部变量来存储随机坐标,之后又使用这些坐标来创建实例。在这个例子中,我们使用的一些变量不是完全必要的,但是为了方便阅读和使用,还是使用了他们。下面的例子中,我们将做的更详细:
instance_create(x - 32 + irandom(64), y - 32 + irandom(64), obj_guts);
还有需要注意的是,局部变量对于使用它们的event(事件)来说是唯一的,所以我们可以用"with()"函数让这些变量来改变或设置其他的实例。
var num = instance_number(obj_Enemy);
with (obj_Enemy)
{
if num>10 instance_destroy();
}
上面的变量告诉我们,只要在同一个代码块当中,局部变量就可以在任何object(对象)中使用。
3、Global Variables(全局变量)
当一个变量被声明为全局变量时,它便不属于任何的实例,但是可以被访问。与局部变量一样的是全局变量需要声明,但不相同的是,全局变量将被以一直保存在内存中,直到游戏结束。举个例子,我们可以创建一个全局变量来记录玩家的子弹拥有数量,然后在游戏的不同时候改变这个变量。全局变量不属于任何一个特定的实例,但是它可以访问、修改和使用所有实例。 并且,对这类变量的任何修改都是“全局的”,即使用该变量的所有实例都将受到改变。下面举个栗子:
global.food = 5;
我们用global.来声明变量"food",并且告诉GameMaker这是一个全局变量。现在,任何实例都可以任意使用和改变这个变量,并且所有其他实例都将“看到”这个变量。例如,我们可以有这样一个event(事件):
global.food +=1;
或者还有这样:
draw_text(32, 32, "food = " + string(global.food));
需要注意的是不要将全局变量命名为任何实例变量,因为这样会出现许多难以调试的BUG!一般来说,我们需要一个脚本在游戏的一开始就声明所有的全局变量。这样方便我们去参考和检查这些变量。
我们也可以通过globavar来声明全局变量,就像使用var来声明局部变量一样。但是,它只包含先后兼容性,所以不建议在新项目中使用,以后的GMS可能不再支持它。
同样的,GMS内置了许多全局变量,这也是我们需要注意的,识别方法与上面的实例变量一样。这些内置的全局变量大多是十分具体的,只在少数情况下会使用到他们。具体例子如下:
(1)health(血量)
这个内置的全局变量通常用于玩家的血量,但是仅仅只是通常,你也可以把它用做别的用途。下面是一个例子:
if place_meeting(x, y, obj_Enemy)
{
health -= 10;
if health <= 0 instance_destroy();
}
上述的代码用于检查当前的实例是否与对象"obj_Enemy"有碰撞,如果有的话health将减去10,如果health的值小于或等于0的话,破坏当前实例。
(2)lives(生命值)
这个内置变量通常用于玩家的生命值(就是血量减到0了就会扣1生命值),嗯,也是通常,所以还是可以拿来做其他用途。下面还是例子:
if place_meeting(x, y, obj_Enemy_Bullet)
{
health -= 10;
if health <= 0 lives -=1;
}
上述代码当检测到health小于等于0的时候,lives减去1。
(3)score(分数)
这个内置变量通常用于分数,还是通常,仍然可以用作他用。下面是最后一个例子:
if place_meeting(x, y, obj_Bullet)
{
score += 10;
instance_destroy();
}
上述代码先是检查当前实例是否与对象obj_Bullet是否有碰撞,如果有的话,分数加10并且自行销毁当前实例。Bullet是子弹的意思。
专有名词中英互译
Devices 设备
Refer 参考,引用
Valid 有效的
Scope 范围
Categories 种类,类别
Reach 范围
Defined 定义
Script 脚本
Reflect 反映
Objects 对象
Numeric 数值的
Modified 修正的
Description 类型
Accessed 访问
Initialize 初始化
Array 数组
Coordinates 协调
小结
额,之前期末考试所以拖了好久,都在复习大学专业知识。放假后,迅速开始继续学习!不过还是拖了挺久。
这一篇手记讲述了GML的变量以及它的不同的类型,因为篇幅的问题和一些编程方面的知识还不是特别了解,所以,有两三点我准备放到下一篇里继续讲。嗯,就是这样了。
