[新手向教程]小玉米图文教程No.2 - 关键字var的大用处
gamemaker吧
全部回复
仅看楼主
level 14
原帖地址:gamemake[酷]r.c[酷]n/thread-729-1-1.html
搬运过程中请大家不要插楼,可以直接打开原帖地址查看。
2014年12月09日 17点12分 1
level 14
近来偷摸的观察这几个GM群的东西,绝大多数同学认为,var这个东西,就是局部变量,加不加影响不大,跟直接定义变量定义值是一个效果的,比如我举个例子。
-------------------------
fuck = "franniss";
-------------------------
var fuck;
fuck = "franniss";
某些人会觉得,这两个代码的效果完全是一样的,var的那一行,加不加都可以。
你要这么认为你就错了
我们不妨来这么试一下。
启动GM8.0,GMS也行= = 。。。 为了保证大家在实验的时候与本教程完全同步,推荐大家使用论坛的超强汉化破解版GM8.0
新建一个工程,创建物体和房间,并把这个物体放入到房间里。
这里我给object0放了个精灵,目的是让大家知道已经把这货添加进了房间里(我这么做貌似没啥必要,防误解还是扔进去吧。)
之后,就要往物体里面写代码了,在object0的创建事件中,写下如下代码
fuck = "franniss";
这是在物体上简单的定义了一个变量
接下来,在物体的空格键按下事件中,写下如下代码。
show_message(fuck);
效果可想而知,在敲击空格键的时候,屏幕上会弹出一个消息提示框,那我我们来试一下。
敲击空格键,弹出消息框:
一切看上去很正常,嗯。接下来,稍微改动一下代码,将创建事件中的代码改写成如下代码。
var fuck;
fuck = "franniss";
这段代码,就用到了var关键字,定义了一个临时变量。
运行游戏,敲击空格键。
这时我们就发现,在敲完空格键之后,并没有弹出信息框,而是报了错。错误的原因是一个未知的变量fuck,
我们已经在创建事件中定义了fuck变量,为什么在按下空格事件中,这个变量不起作用呢?
实验证明,在创建事件中,已经成功的定义出了fuck变量,但是在敲击空格键的时候,这个变量就不存在了,所以,我们得出以下结论:
使用var关键字定义过的变量,只影响于当前事件,并不作用于整个实例,当事件结束的时候,这个变量会自动的从内存中删除掉。
这个结果只是当前得出的,并不是最标准的,下面,将在这个实验的基础上增加更多的动作来得到更准确的定义。
删除掉刚刚物体中的“按下空格”事件,并对创建事件进行改动。向创建事件中拖入两个代码按钮,如下图所示。
在第一个代码块中,写下如下代码:
var sb;
sb = "franniss";
在第二个代码块中,写下如下代码:
show_message(sb);
接下来,运行游戏。查看效果
根据运行结果我们会发现,程序依然报错,那么问题来了,我的var定义的变量明明和show_message时的变量在同一个事件里面,为什么还会报错。
这时我们再对程序进行修改,删除创建事件的一个代码按钮,留下一个,并改写成如下代码:
var sb;
sb = "franniss";
show_message(sb);
运行后你会发现,程序正常运行,弹出了灰色的信息提示框。
实验证明,在创建事件中,已经成功的定义出了sb变量,但是想让这个变量有效,所有使用到这个变量的语句都要和该变量的var定义处在同一代码段内,因此,我们得出以下结论:
使用var关键字定义过的变量,只影响于当前代码段,并不作用于整个实例,当该代码段结束的时候,这个变量会自动的从内存中删除掉。
我们大家所说的临时变量,其实就是就是以前直接定义的一些变量,并不加var和global关键词的修饰,其实这种说法是不对的,我们可以认为,在GM中存在于四种类型的变量:
1.使用关键词
globalvar定义的
全局变量;
2.不使用任何关键词所定义在实例上的
成员变量;
3.在变量名前加上
global.的
特殊的,定义在global上的
成员变量;
4.使用关键词
var定义的,
只作用于当前代码段上的
临时变量。
所谓的成员变量,只得就是该变量是影响整个实例的,在变量名使用global.这个比较特殊,可以称之其为成员变量,但是我认为,在这里为了让大家不要和globalvar发生无解,还是将它当作定义在global实例上的成员变量比较好,而且这个实例会全程存在于游戏中,它是一个比较特殊的实例。
2014年12月09日 17点12分 2
fuck='franniss'[滑稽]尼玛这可是人身公鸡啊
2014年12月12日 05点12分
回复 qza7474741 :谁说的,我就是设定了一个变量,里面的字符串是我瞎敲键盘敲出来的,
2014年12月12日 06点12分
回复 Mage松仁玉米 :那sb='franniss'怎么解释[滑稽]
2014年12月12日 10点12分
回复 qza7474741 :我复制粘贴的~别在意细节~
2014年12月12日 10点12分
level 14
既然我们已经得出了var的使用定义,那么这里就说一些关于var妙用。var是一个非常好用的东西,它会让你的代码逻辑更加清晰,而且在代码执行完毕后会马上释放掉内存,且不会与其他的成员变量冲突。因为它只作用于代码段上,所以要比全局变量和成员变量的运行效率快很多。
1.在脚本中使用var:
有的时候,为了实现一些必要的功能,而且这个功能我们会反复的用到,而并不想重复的写代码,我们就会使用到脚本,在脚本中使用var会让脚本内所用到的变量不与调用脚本的实例中的成员变量发生冲突,下面就来举个例子:
创建一个脚本,命名为draw_rectangle_red,用来实现绘制一个红色的矩形,在脚本中写入如下代码:
var x1,x2,y1,y2,color;
x1 = argument0;
y1 = argument1;
x2 = argument2;
y2 = argument3;
color = draw_get_color();
draw_set_color(c_red);
draw_rectangle(x1,y1,x2,y2,false);
draw_set_color(color);
这样,在用var定义好局部变量后,可以使x1,x2,y1,y2,color这些变量不和调用实例的成员变量发生冲突,如果说实例中存在一个color成员变量,如果这个脚本并没有使用var来定义color,则该实例在运行完此脚本后,成员变量color就很有可能被改变,游戏就容易引发BUG。而且如果在脚本中如果使用了一个实例中没有的变量名称,在运行完该脚本后,变量就会残留在当前的实例中,这样就会导致游戏占据很大的内存,在优化方面,一个小小的细节也不要放过,哪怕这个变量只是一个占8字节的double型变量。
2.*在with结构中使用var:
我们已经得出了结论,var所定义的变量只是作用于代码,在with结构中,with后面的东西很容易导致你的思路混乱,让你误认为一个实例上的变量是另一个实例上的,这就造成了游戏的BUG,而且对于某些入门者来说,这都是不容易察觉的出来的问题,这里如果使用了var,思路就会变得相当清晰,而且也不会引发BUG,下面我就做出一个例子:
在这里我先声明一下,有两个实例,分别为obj1和obj2,在obj1上存在一个数据结构列表,这个列表的索引值被存放在该实例的list成员变量中。而obj2没有list这个变量。我希望敲击空格键的时候,创建一个obj2物体,将新创建的obj2实例的id值添加到列表内。
有些人在写的时候可能会这么写:
ins = instance_create(0,0,obj2);
with(ins) {
ds_list_add(list,id);
}
逻辑上,这种写法是
正确的
,但是在with结构代码块中,里面的所有变量都是要在被with的实例中应当存在的,这里在运行之后就会报错,错误为“不存在list变量”。
这里我们可以使用var定义一个临时变量,来实现跨实例变量传递,这个听起来比较神,但是确实就这么神,下面我就给出这样的一段代码:
var L;
L = list
ins = instance_create(0,0,obj2);
with(ins) {
ds_list_add(L,id);
}
这次再运行,游戏就不会报错了,而且会成功的将obj2的id添加到列表中,因为使用var定义的变量,只作用于代码,与实例毫无关系。所以说,这种语句是正确的。
有的孩子特么的抠字眼,就说了,其实我有种写法更好,就像下面这样:
ins = instance_create(0,0,obj2);
ds_list_add(list,ins);
哥,别在意细节= = 我只不过是演示一下var在with结构中的妙用= =在你处理的数据足够多的时候,你会发现这么用要方便的多。
总而言之,var是个不错的东西,灵活的去运用一定会帮助你让你的游戏更加高端。让你的代码思路和逻辑更加清晰。
2014年12月09日 17点12分 3
level 14
别着急,还没完,下面说两个关于var的使用注意事项:
1.在使用var定义变量的时候,千万别忘了在定义完成之后加上半角的分号,否则程序会出错的。
GML语言在语句结束的分号上没有要求的这么严厉,在语句末尾不加分号也会正常运行,但是用var和globalvar定义变量的时候一定要记得加分号,否则会引发程序出错。有的时候,还是严厉点比较好呢。
2.如果我的实例上已经有了一个跟var定义的重名的变量,那我要怎么在写代码的时候区分这两个变量?
这个我不多说,依然举出一个代码:
str = "test";
var str;
str = "123";
这里,就定义了一个成员变量str,和一个临时变量str,想要在接下来的代码中区分这两个变量很容易,只要用self就可以了。
show_message(str + self.str);
运行一下看看结果。
这个我想应该是重要的一个问题,因为变量名冲突什么的确实会引发不少的BUG,其实有一个更好的方案就是在编写程序的时候尽量避免变量重名,这样就把发生BUG的概率降了很多。可见,有一个良好的代码编写习惯也是尤为重要的。
以上,就是本次教程的所有内容,特么的写了这么长时间累死哥了。
最后我来说几句,有些朋友很关心大苞米视频教程的更新,在QQ上私聊我来问我视频什么时候更新呀?很想继续学习什么的,看看也是,很长时间一直都在断更的状态,其实自己懒是一方面原因,而且在上了大学以后,做语音教程什么的也不是很方便,毕竟有室友在搞基。所以就先拿图文教程来说事吧,虽说操作上没有视频直观,不过也能把思路讲清晰也是很好的事情,在此感谢大家对玉米的支持。
2014年12月09日 17点12分 4
level 12
我就想听解说时后面有人在搞基[滑稽]
2014年12月10日 01点12分 5
level 8
受益了
2014年12月10日 07点12分 7
level 11
受益无穷
2014年12月10日 13点12分 8
level 8
此fuck值大快人心
2014年12月12日 10点12分 9
level 11
我更想知道frannis的完整罪行
2014年12月12日 11点12分 10
level 11
有用 但是我想问个问题:
由于这是第二次打字(之前的打了好多字结果都不见了... _ fuck)
好了,进入正题:
1.想做像MC一样的背包
(其实已经做好了,只是想简化一下)
怎么使用数组?或者全局的也行
之前的方法太乱了,连我手把手地教别人都不能理解,甚至连我新加一个物品都要改好多的代码,简直烦死了
之前用global声明变量,首先是格子的变量(就是值为几这个框的物品ID就为几)
global.beibao[0]=0
global.beibao[1]=0
global.beibao[2]=0
...
都是框的变量
还有各个框相同的物品数量变量:
global.number[0]=0
global.number[1]=0
global.number[2]=0
...
都是相同物品数量的变量
但是在捡东西时总要检测每个框的物品ID是否不同或没有物品(没有就是为0,数量也为0)
比如一个物品ID是5那么捡这个物体的代码就如下:
if(global.beibao[0]=0 or global.beibao[0]=5 and global.number[0]<64/*最后的是检测物品上限是否小于64*/)
{global.beibao[0]=5;global.number[0] =1}//为这个框的物品数量加1
else//否则换下个框检测
if(global.beibao[1]=0 or global.beibao[1]=5 and global.number[1]<64/*最后的是检测物品上限是否小于64*/)
{global.beibao[1]=5;global.number[1] =1}//为这个框的物品数量加1
else//否则换下个框检测
if(global.beibao[2]=0 or global.beibao[2]=5 and global.number[2]<64/*最后的是检测物品上限是否小于64*/)
{global.beibao[2]=5;global.number[2] =1}//为这个框的物品数量加1
else//否则换下个框检测
...
真的很麻烦,能用数组简化吗?
但是使用东西时就要检测指定的框的物品,根据情况减少该框的东西了,这样能用数组吗?
制作无限地图时总要定义区块,用数组又不知道能不能为字符串,所以用的时候怎样用数组来代表区块的情况,比如:
chunk[-2]='sb sb'
chunk[-1]='sbsb'
chunk[0]='94sb'
chunk[1]='fucksb'
chunk[2]='就是sb'
像这样,可以吗?
我知道内容有点多,但请楼主帮忙,谢谢
2014年12月12日 11点12分 11
@q糖豆p 来个物品栏例子~
2014年12月12日 12点12分
@q糖豆p 尼玛为啥艾特不上。
2014年12月12日 12点12分
@Mage松仁玉米 。。。
2014年12月12日 12点12分
回复 Mage松仁玉米 :没做过……好的既然需要我去做一个。
2014年12月13日 00点12分
吧务
level 13
@Mage松仁玉米 @z123k5
嗯,说好的物品栏……[无效] http://pan.baidu.com/s/1gd1mOaJ
那么……WASD或者方向键都可以控制,Z或者空格或者J都可以扔东西。鼠标滚轮切换物品,鼠标左键放置物品(可拾取)。注意物品如果没有在10秒内拾取是会消失的,每次拾取增加对应物品5个。
那么,这次就开源好了。虽说后边的一些代码忘了加注释,应该不影响理解吧……哪里看不出来再说。
2014年12月13日 01点12分 12
嗯。谢谢~
2014年12月13日 01点12分
level 7
2016年06月14日 05点06分 13
1