我想成为创造者IC编辑器_从入门到精通_第五章如下:
第五章:触发器
————————————————————
此章中,你将接触到IC编辑器中最核心的区域:触发器,IC的核心是编辑器,而编辑器的核心是触发器,所以四舍五入来看,触发器就是IC的灵魂。如果说场景中的单位是地图的四肢,那么触发器就是地图的大脑,它指挥着单位的运行,这是编辑器最最最厉害的功能,正是触发器,可以使得IC拥有“2D游戏微引擎”的美誉,使得IC可以制作平台跳跃类型游戏之外的2D游戏。这是一个令人兴奋的东西(同时也令人头秃),几乎在所有所谓“高级”的地图里,都会有触发器的影子。
本章知识点如下:
· 触发器的运行机制
· 触发器的操作
· 常用事件
· 常用条件
· 单位目标类型
· 数据类型及其转换
· 高阶常用动作解释
· 函数中的常见陷阱
· bug的检查与调试
· 触发器的学习方法
触发器在哪?
学习触发器之前,咱们得先会找到触发器在哪,如下图所示,位于数据编辑器中
其中会默认有一个触发器:
意思是当游戏开始,就创建玩家角色,注意,不要随便删除这个触发器,否则游戏开始将会没有玩家单位,即你操控的人物。
触发器的认识
触发器可以被认为是一个写伪代码的工具,当然这里的代码是中文的自然描述,字面意思比较好理解,不用担心学不明白(Konux入坑时也是小白哦)。对于游戏中特定事件,只要写好具有对应事件的触发器,若满足触发器条件,便有可执行一系列包含在触发器中设定好的动作。
举个生草的实际例子:
你在学习的时候,突然肚子一阵捣腾,很明显你要上厕所了(事件触发)
这个时候,你可不能直接跑去厕所,你需要先看看自己有没有带纸,如果没带纸就匆匆跑去厕所是非常危险的(条件判断)
你发现你带纸了,于是你拿起手机一路火花带闪电的就冲进了厕所(动作执行)
触发器的三大件
事件、条件和动作共同组成触发器
事件:
只有事件发生,相应触发器才会被触发(就像触发器接收到了信号),若无事件,则不会自行触发。
条件:
当事件发生时,若条件满足,才能运行触发器里相应的动作,否则不运行动作,就像筛子的作用一样。
动作:
触发器触发后具体要执行的函数组,相信这个你们并不陌生,在坑向教程中我们使用的最多的就是动作。
触发器的操作:
我们对触发器的操作类似于关卡,我们可以对触发器进行新建、克隆(复制粘贴)、删除、改名、添加类别(用于分类),长按一个触发器或右击(电脑端)即可显示这些操作。
值得注意的是触发器有一个[关闭/开启]操作,和动作类似的,这个操作可以使触发器开启或关闭,处于关闭状态时,触发器名会变成灰色,此时触发器将不会自行触发,所以其中的动作(函数组)也不会执行。
什?你这都关闭了那还写这触发器干啥?其实这是大有所用的,就像写代码一样,我们的触发器如果使用不当就容易出bug,有时候这些bug的位置我们都找不到,所以在检查哪里出问题的时候,就可以暂时将一些触发器关闭,以排查出bug的位置,如果为了排查一个小bug而把整个触发器都删除,那就太蛋疼了。总而言之,当触发器后续还需要用到,但目前不想让它触发时,就可以关闭触发器。
左边看完了,咱们再看看右边,也就是触发器的编辑区域了
相信右边的7个按钮大家相当熟悉,和我们做坑向时对函数的操作的按钮是一样的,从上到下依次为新建、修改、复制、剪切、粘贴、设置开启或关闭、删除。
这几个按钮可以对事件、条件、动作里的函数做操作。此处注意,事件、条件和动作里装的都是函数,但它们属于不同类别,比如事件里的函数我们叫它”事件函数”,同理还有”条件函数”和”动作函数”。
实操入门:
OK!现在我们可以开玩编辑器了!
我们游戏默认的一个触发器如下,目的是当游戏开始时,把主机玩家单位(散人)创建出来,这里没有写条件函数,条件中,无条件函数就默认条件是满足的。
若不小心将“[系统函数]为所有玩家创建角色”函数给删掉了,可在触发器的动作中手动添加回去,注意函数编辑器左上角的类型为默认时,是看不到系统函数的,所以我们需要改成全部,这样我们能用的函数会多一些(函数编辑器里的函数有重复的,这是教程版本的游戏小bug,在新版里已经修复,不用在意)。
一般来说,默认的这个触发器是不允许瞎改动的(对于新手),只允许在动作-为所有玩家创建角色函数后面写函数。
好,经典的第一步,开局输出一段文本。
首先点击函数[为所有玩家创建角色],点击添加函数
我们找到“[信息面板]-添加信息”函数,点击第一个参数,点击常量,输入:Hello World
这样就写完了,我们运行游戏试试看
成功了!当游戏刚开始时,左下角的信息面板便显示出了“Hello World”,这个信息面板可用于显示你想显示的信息,你可能会说这有啥用?先收起你的好奇心,咱们后文会再次提及。
制作碰撞伤害技能
什?你没听错,咱们要使用触发器,模拟制作一个碰撞伤害技能的效果
这个效果用触发器可解释为:
事件:当玩家碰撞
条件:判断碰撞了谁
动作:杀死主机玩家单位
由于我们需要的事件不是默认触发器里的游戏开始了,而默认触发器不允许改事件,所以这时,我们应该新建一个触发器,实际上,良好的触发器习惯是一个触发器只做一种功能,这在我们后期制作逻辑复杂的庞大触发器时,会有非常多的优点。
添加触发器后给它命名为“碰撞伤害”就可以了,触发器的名字可以任取,但还是建议取一个自己能看的懂的、对触发器功能能进行准确描述的名字,这样在触发器较多时,才不会乱。
接下来开始写事件,点击事件,点击新建函数按钮,找到“单位-玩家单位事件”函数,选择碰撞开始,
碰撞事件如下所示,碰撞开始即刚撞上,碰撞持续即“亲密接触”,碰撞结束即离开
好了,事件搞定,接着写条件,这里我希望当碰到刺的时候,就运行动作,条件当然是判断我们碰撞到的单位是个什么东西了,点击条件,添加函数
找到单位数据类型比较函数
还记得咱们之前提过的单位数据和单位的区别吗?单位数据是“图纸”,单位是依据对应图纸造出来的个体,个体之间是不同的(就像人和人都不同),我们这个条件函数是对单位数据类型进行比较,也就是说判断这个单位是用哪个“图纸”生产出来的,而不是直接判断单位,好了,根据这个条件函数,我们很显然要设置第三个参数为刺的单位数据,点击常量即可。
中间的参数“==”是用来设置判断等于(==)或不等于(!=)的,这里我们需要判断等于,所以不用更改。
第一个参数是设置需要判定的对象的,此处需要选择玩家碰撞到的单位,那么这玩意怎么选择呢?
一般来说,碰撞事件发生时,双方单位其中一个是触发单位(发起方),一个是目标单位(接受方),根据牛顿第三定律,力的作用是相互的,同理碰撞也是相互的,所以一个单位既是触发单位也是目标单位,但是当其中的一个单位被确定时,另一个单位也就被确定了。比如咱们这个触发器中,事件为玩家碰撞开始,那么作为碰撞发起方的玩家,就作为了触发单位,那么它碰撞到的单位,就只能是目标单位了!所以咱们条件的第一个参数,就填目标单位即可。
现在事件和条件咱们已经写好了,就只差动作了,我们添加一个杀死主机玩家单位的函数即可。
这样我们的触发器功能就做完啦!
我们把刺的碰撞伤害技能给去掉,然后运行游戏试试!
成功了!如果我们需要控制多种类型的单位有伤害,又该怎么做呢?如下所示可以吗?
运行后发现我们刺的伤害都没了,咱甚至可以用铁菊站上去(
这是为啥呢?实际上,如果条件里放了多个函数,那么默认表示为所有条件都满足的情况下才运行动作,但是很显然,目标单位是确定的一个单位,它只有一个确定的单位数据类型,它不可能同时满足以上两个条件,所以此触发器永远不会执行动作。要解决这个问题,我们需要使用一个常用的条件函数“任意条件成立”,表示只要满足其中的一个条件即可运行动作,把想要的条件放入此函数中即可。
这样,我们的函数就能正常工作了!
大概一个触发器就是这样写出来的,可以看成是拼积木,而此处的积木是由代码构成的,我们不需要关注代码上的细节,只需要会把积木拼成大厦就可以了,由于触发器里涉及到大量的函数,咱们不可能一一讲解用法,但是后文会给出常用的一些函数以及触发器的学习方法给大家指路。
常用事件:
[游戏]
游戏开始:当游戏开始时触发(注:死亡重新载入也会触发此事件,因为死亡重载实质上就相当于退出地图再重进地图,而进入地图就可以认为是游戏开始)
游戏开始(延迟):在游戏开始事件之后紧接着触发,注意此处的延迟极短,游戏开始和游戏开始(延迟)都是在同一帧(1帧时间不固定,比如60帧时,就相当于1/60 = 0.0167秒)内运行,只不过是分先后顺序罢了。
游戏帧数更新:当游戏每次帧数更新时触发,时间不稳定,若玩家设备帧数设置为60帧时,则此事件大概每过0.0167秒触发一次,但是帧数是在不断上下变化的,所以这个时间也没有固定值,有意思的是,当游戏暂停时,此触发器会继续触发,因为游戏暂停时,帧数是不会暂停的,依据这种特性,我们可以在游戏暂停时搞些操作。
游戏物理帧更新:每过固定时间0.02秒会触发一次,因为物理帧固定为0.02秒。
游戏暂停、游戏恢复:顾名思义,当你按下返回键时游戏暂停事件触发,当由暂停状态回到游戏里时,恢复事件触发。
[单位]
单位事件、玩家单位事件和任意单位事件,比如咱们都是判断单位碰撞开始,单位事件是指定一个在场景中的单位(常量)碰撞开始,玩家单位事件是指定主机玩家单位碰撞开始,任意事件是只要有单位碰撞开始了就触发。
有同学可能喜欢举一反三,立刻想到,这个玩家单位事件有啥必要呢?咱们用单位事件也能做呀!如下
然后咱们运行试试看!
游戏直接报错了,这是为啥呢?咱明明很对嘛?其实呀,所有事件函数都有个特性,就是不能使用变量或函数作为参数,其中的参数只能使用常量,咱们由于使用主机玩家单位函数作为了参数,所以这里就会报空,所以我们如果要判断玩家单位的事件,就需要使用玩家单位事件函数。
我们可以看看单位事件可选的有哪些
好像还挺多的,这里讲几个不好理解的,其他的可以自行尝试即可
初始化:即单位刚被创建时触发,一个单位在其生命周期内只会触发一次初始化事件(就像人一生只能出生一次一样,什?你说你是龙王转世?那没事了噢...),不仅仅是用函数创建的单位会触发初始化,摆放在场景中的单位也同样会触发,其实当关卡一开始时,是没有单位的,你摆在场景中的单位也没有加载,只有单位加载完后,你的单位才会被创建到场景中,所以在刚进入关卡时,我们摆放的单位才会“出生”,也就会触发初始化。
交互:需要按[O]键的地方就有交互,比如进传送门、存存档,这些时候按[O]键即可触发交互。
控制键输入:咱们按[A][D]键左右移动,按[O]键交互,按[R]键重生,按[K]键使用道具等,都叫控制键输入,如果改键了,也成立,比如将[A][D]改成了[←][→],那么相应的控制键就是[←][→],手机端触屏按键也可同样触发控制键。和碰撞类似,控制键按下时叫输入开始,持续按住控制键时叫输入中,松开控制键时叫输入结束。需要注意的是,控制键是位于玩家单位上的,所以如果没有创建角色,那么控制键将不会被触发,即使你按了控制键。
[关卡]
当进入关卡(新):当玩家刚进入关卡时就触发,游戏开始时可触发
当进入关卡:当玩家被传送进入关卡时触发,游戏开始时不触发
当离开关卡:当玩家从该关卡被传送走时触发
[计时器]
时间消逝:触发器被开启后过给定秒数触发,触发器若默认开启,表示游戏开始后经过指定秒数触发。
时间消逝_循环:每过指定的秒数触发一次,有点像内部计时器的功能
[输入]
任意按键按下:字面意思,键盘上的任意按键按下时触发
任意按键弹起:字面意思,键盘上任意按键松开时触发
注意,如果是想要玩家左或右移动、使用道具、交互时触发,不可使用按键事件,因为电脑玩家如果改了按键,输入的按键将会判定错误,应该使用上面讲的“玩家单位控制键输入开始”事件,一般来说此事件用于地图的电脑端操作。
[聊天输入]
聊天信息输入也分为输入开始、输入中和输入结束,聊天信息指的是我们按[Enter]键或输入键(手机端)时弹出的聊天输入框里的信息输入,一般来说,用的最多的是输入结束,即信息写完之后再次按[Enter]键或输入键发出信息时,此时我们可以通过一些函数来获取到玩家聊天里的内容,这就是有些地图在聊天中输入一些指令就可以执行一些操作的方法。
常用条件:
条件函数的返回值为布尔值,它是一种数据类型,数据类型是啥?目前暂且不做解释,后面讲动作时会详细写明。布尔值其实你可以认为它只能是0或1两种值,其中1表示真(True),0表示假(False),对于条件的判断只有条件成立或者条件不成立,不可能产生一种成立但又不完全成立的条件。布尔值为真时就表示条件成立,为假时表示条件不成立。
现在我们为了方便,引入两个逻辑运算符(就像+ - * /一样的东西)来表示条件之间的关系
与运算符:&&
A && B 表示A与B,意思是只有A和B都为真时,A && B才为真,否则为假
真 && 真 == 真
真 && 假 == 假
假 && 真 == 假
假 && 假 == 假
或运算符:||
A || B 表示A或B,意思是A和B中只要有一个为真,那么A || B为真,否则为假
真 || 真 == 真
真 || 假 == 真
假 || 真 == 真
假 || 假 == 假
上面的等于号是双等于“==”,这个用于表示等式两边的值是相等的,而如果表示两边的值是不等的,就需要用不等于号“!=”,条件等式左右两边的值可以互换,并不会影响结果。
那么单等于号“=”呢?我们称其为赋值号,赋值号的左边放需要被赋值的变量(称为左值),右边放赋的值(称为右值),比如a = 1,就表示将1这个值给变量a,那么a就会被赋值为1,而1 = a这种说法是没有的,因为1是常量,是个确切的数,不可变,所以我们是无法给常量赋值的。
[表达式]
所有条件成立:
字面意思,即此函数中包含的所有条件必须都满足才能成立
可表示为A && B && C && … ,所有条件成立就是“与”运算
任意条件成立:
字面意思,即此函数中包含的所有条件只要任意一个满足就成立
可表示为A || B || C || … ,任意条件成立就是“或”运算
布尔表达式:
此表达式用于判断等式两边的布尔值是否相等,若相等,则此表达式为真,否则为假,表达式为 A == B,虽然第二个参数“==”可以改为“!=”,但是咱们不需要改变第二个参数,因为“!=真”就是“==假”,“!=假”就是“==真”,我们只需要改第三个参数的真假即可。
此条件函数常用于“条件取反”,比如我们需要判定“当玩家是活着的”,但是咱们只有判断玩家是死亡的函数,所以我们可以利用表达式写为“当主机玩家单位是死亡的 == 否”,玩家不是死的,那不就可以表示玩家是活的吗?
[关卡]
关卡条件函数只有一个关卡比较,很显然,此条件用于判断等式两边的关卡是否相等,通常我们可以使用当前关卡 == ***来判断玩家所在当前的关卡,如果要使用触发的关卡 == ***,就需要配合进入关卡事件才能起效。
[字符串]
常用的是字符串比较和字符串包含。
字符串比较即对等式两边的字符信息进行比较,若完全相同则为真,否则为假。
字符串包含即判断一个字符串中是否包含有一个字符串,比如字符串“Konux真帅”中包含“真帅”字符串,不包含“真丑”字符串。
还记得我们在事件中提到的聊天输入结束函数吗?咱们可以和此条件配合使用,来做判断聊天输入的字符串是什么,从而完成类似于输入指令一样的操作效果。
啊对,上面触发器的效果是当你输入“Konux我好爱你啊!!!”那么游戏就能通关,不过咱不建议你利用这个东西来通关自己制作的自己过不去的难图并发布,如果你的地图是无解的,那么管理会进行扣分!我们应该制作自己能通关的地图,而不是为难而难,为了迫害别人而制作的地图,因为往往这些地图都是低下载低点赞低关注。
[数学]
概率成立:分为实数和整数,实数概率函数的参数可以是小数,而整数概率函数只能是以整数作为参数,一般来说实数就够用了。此条件以一定的概率成立,比如50%的概率成立,就是指此条件为真或假的概率都为1/2,此条件常用于制作概率性的动作函数。
整数比较:判断两个整数间的大小关系,可选的关系为“==”、“!=”、“>”、“>=”、“<”、“<=”。
实数比较:和整数比较类似,判断实数(也就是小数)之间的大小关系。
需要注意的一点是,实数之间不能进行“==”或“!=”比较。
因为实数在计算机(手机也一样)中不能被精确表示,咱们的内存空间是有限的,而有些实数是无限小数,内存中不可能存放这个数字的每一位,所以就会对实数进行舍入,这就会造成舍入误差,又因为计算机中的数字是以二进制的形式储存的,所以对于大多数十进制实数来说,转换为二进制后基本上都是无限循环小数,这个误差不可忽略。
如果我们需要判断两个实数a和b是否相等,就必须要规定一个误差来判断,比如Konux习惯用|a - b| < 0.005来判断两个实数是否相等,左边表示a和b的数值差,右边表示自己规定的精确度。
剩下的四个函数用的非常非常非常少,几乎没有什么作用,所以这里不讲。不过这里需要提一嘴二维向量比较函数为啥没用,因为此函数只能进行“==”或“!=”比较,而二维向量就是由两个实数构成的量,我们知道,实数不能直接比较,所以这个函数也没有用。如果需要比较两个二维向量的大小,就需要用实数比较,当二维向量a与b之间的距离 < 0.005时,就表示a和b之间非常接近,就可以认为两二维向量相等了。
[输入]
输入条件函数用的最多的是按键比较2,由于此函数是比较“触发的按键”与期待按键是否相等,有带“触发”字样的条件,一般都需要配合相应的事件才能生效,因为只有事件才能触发,所以此条件需要搭配[输入]事件使用,注意按键输入是电脑端玩家才能用的,虽然手机端也勉强可以用,但是不推荐。
可能这里有人又要开始杠了,触发区域里也是可以用触发单位作为条件的,这咋没看见事件呢?
上图右边蓝字是触发单位函数的官方解释:相应事件的触发单位。很明白了是需要事件的,但是触发区域的技能“运行动作”里只能写动作,不存在事件的说法。
这里Konux告诉你,其实“运行动作”技能可理解为是一个隐藏了事件和条件的触发器,这个事件是默认已经写好的,而条件则表现为了技能的属性,那么这个技能用触发器该怎么表示呢?如下
目标单位就是装有此技能的单位,而触发单位类型可在技能里设置,Player就表示玩家
明白了吗?触发区域为啥名字中带触发,就是因为本质相当于是个触发器。
[单位]
对单位的条件判断都是字面意思,某些用的很少的函数和一些一看就知道是啥的函数这里不讲,下面将一些比较难懂的函数来解释一下
是边界墙:判断单位是否是边界墙,边界墙就是包围关卡的墙,如下所示,边界墙分上下左右四块
这些黑色的障碍物就是边界墙了,它们是一种很特殊的单位,当然其实边界墙是白色的,但游戏中设置了此单位的颜色为黑色。
单位目标类型比较:我们之前讲过单位数据类型比较,单位数据是“图纸”,单位是图纸造的零件。而这个目标类型比较是个啥呢?目标类型也是单位的一个属性,来看:
咱们打个简单的比方,一个个不同的单位就像学校里的一个个学生一样,每个学生都有他们的班级,而单位的目标类型就可以认为是单位所属的班级班名,单位默认的目标类型是没有的(也就是空:Null),单位可以没有班级,而有些编辑器自带的默认单位有目标类型,默认的障碍物(墙、隐藏砖块、淤泥、反弹砖块等)的目标类型为Obstacle (注意大小写要正确),中文意思是障碍,玩家发射的子弹的目标类型为PB (Player’s Bullet),中文意思就是玩家的子弹。
那么这个目标类型有什么用呢?我们先打开玩家子弹的技能看看。
子弹拥有三个技能,碰撞伤害用来给目标单位造成伤害,碰撞死亡用来使子弹碰到目标单位时删掉自身,重置死亡使玩家在重置游戏时让子弹删除。打开碰撞伤害技能看看
这个技能的影响目标类型为Monster,这是个啥?好像从来没见过,中文直译过来就是怪物的意思,也就是说,只有玩家子弹碰撞到目标类型为Monster的单位才会对它造成伤害,技能中的影响目标类型(或目标类型)是用来设置技能对谁生效用的,还记得咱们砖的目标类型为Obstacle吗?如果将砖的目标类型改成Monster,那么玩家子弹就能将砖块给射死。
同样的,你也可以将玩家子弹的碰撞伤害技能的影响目标类型改成Obstacle,也能达到这个目的:
但由于Obstacle目标类型太常见,容易使子弹“误杀”,所以不太适合这么做。我们如果希望对单独一个单位造成伤害,而不对其他单位造成影响,就可以自己定义一个目标类型,比如我自己在单位上定义一个目标类型为Konux
如果要对这个砖块造成伤害,只需要将玩家子弹的碰撞伤害技能的影响目标类型改成Monster,Konux即可,表示该技能对目标类型为Monster或Konux的单位都起效,注意,写多个目标类型时,需要用英文逗号连接,中文逗号不行哦。
另一个例子,我们的存档点(IW)的保存复活点技能里,设置了碰撞保存目标类型为PB,所以咱们玩家的子弹才能存档。
还有我们的射击型按钮也是如此,其技能里影响目标类型为PB,所以子弹可以触发此按钮。
向量在单位内:向量这里指的就是二维向量,而此处你可以理解为坐标,虽然向量和坐标不是一个概念,但在编辑器中你仍然可这么理解它,因为坐标就是起点位于原点(0,0)的向量。所以此函数用来判断一个坐标点是否在单位内。
如上图,白点的坐标就位于单位内,而红点的坐标则在单位外。
单位在单位内:用于判断单位和单位是否相交,如下这两个单位就相交了,这就是单位在单位内。
是水平反转的:用于判断一个单位是否是水平反转的,常常用于判断玩家,如下,左边的Kid是初始状态的方向,右边的Kid就是水平反转的,所以检测玩家的左右朝向时,就可以使用此条件判断,垂直反转也是同理。
最后按下的控制键比较:用于判断玩家最后操作了什么控制键,比如玩家使用道具、左移、右移等等操作,由于此条件是判断最后按下的控制键,而我们前面讲最后创建的单位时讲过,“最后单位”的获取是不能加等待的,否则就可能出现问题,这里也同理,最后按下的控制键一定是即时即用的,所以也要搭配控制键事件使用,如下:
控制键比较是手机、电脑端都能用的,所以一般做地图如果希望手机电脑端都能玩,就得使用控制键判断,而不采用按键输入判断,按键输入判断仅用于给电脑端除控制键按键以外的按键做处理,比如电脑端玩家按[Z]键(没有改键),而游戏内对此键无定义,咱们可以写按键输入触发器给[Z]键写一个功能,此功能只有电脑端玩家能用,因为手机端玩家可没有实体键盘。
数据类型及其转换:
太好了!终于进入到了数据类型的教学,这里可能会涉及到一点点编程方面的知识,当然这些东西是帮助你理解,而并非需要去掌握的,所以如果看不懂也可以接着看下去,直接看结论就可,接下来咱们先从最基础的数据类型开始讲解。
众所周知,任意一款软件,都是以二进制(满2进1,十进制是满10进1)的形式跑在机器上的,游戏里的数据,在底层里也是被翻译成了二进制的0和1,比如整数,在内存中是以二进制形式储存的,整数8,二进制就是1000,整数5,就是0101,由于我们的数据存在内存中,每个数据会给定一个空间用来存放,所以这就造成了数据空间是有限的,就像一个房子空间有限一样,里面能容纳的人也是有限的,所以数值型数据会有一个范围,并不是可以无限大的,下面介绍几种数值数据类型。
整数(int):
整数就是-1、0、1、2这种数,相信在座的各位大聪明应该在上辈子就学过了,在我们的编辑器中,整数在内存中占用4*8 = 32个比特(bit)位,啥是bit?其实就是二进制位的意思,就像十进制里114514是6位数一样,bit用来表示二进制的位数,32个bit位就像下面这样:
00000000 00000000 00000000 00000000
表示十进制的1023,二进制可写为:
00000000 00000000 00000011 11111111
所以什么情况下,此二进制值最大呢?就像固定三位数空间内999是最大值一样,在二进制整数中,最大的数字就是全1:
01111111 11111111 11111111 11111111
咦?为啥左边第一位是0?因为这里的整数分正负,而最左边第一位我们称为符号位,为0时表示正数,为1时表示负数,它只表示值的正负,不表示数值大小,所以整数最小值就是:
11111111 11111111 11111111 11111111
可能这样不太直观,我们将这个最小值和最大值换成十进制:
整数范围为-2^31 到 (2^31)-1,其中31次方就是因为数值位是32-1位,计算一下这个数值就是-2147483648到2147483647,如果整数超出这个范围,就叫做数值溢出。那么数值溢出会咋样呢?如下图所示,其实整数数值结构是个圆,沿着逆时针方向增大。
由图可知:
0 + 1 = 1
1 + 1 = 2
…
2147483647 + 1 = -2147483648(数值溢出)
-2147483648 + 1 = -2147483647
…
-1 + 1 = 0
好了接下来做个总结:
1.整数的值的范围是-2147483648到2147483647
2.在写触发器时要尽量避免超出整数范围,否则会造成数值溢出。
实数(float):
实数就是小数,有小数点的那种,比如3.1415926就是个实数,实数可以直接表示,也可以使用E记法(科学计数法)表示,比如实数114500000.0等于1.145*10^8,那么其E记法表示为1.145E+8,这里的E就是代表以10为底,+8表示10的指数,1.145为小数部分,注意E记法不能出现空格!
下面给出一些E记法在编辑器中的正确例子:
0.123e3 == 1.23E+2 == 123.0
0.123e-3 == 1.23E-2 == 0.000123
.123e3 == 1.23E+2 == 123
10.123e3 == 1.0123E+4 == 10123
当然了,实数也有它的范围,由于解释起来不容易理解,所以就不给推导过程了,对实数类型的内存结构有兴趣的同学可以自行搜索:float 结构。
实数的取值范围如下:
[-3.4028235E+38, 3.4028235E+38]
更精确的范围应该是:±340282346638528859811704183484516925440之间
实数的储存大小也是4*8 = 32bit,虽然和整数占用的空间一样,但是实数的储存结构比整数的要复杂,它们是完全不同的,你会发现虽然实数占用的空间和整数相同,却能表示比整数多得多的值,这不科学,同一房间里怎么会因为装人的方式不同而容纳更多的人呢?根据信息论来说,实数能表示这么大范围的数值,那么一定是舍弃了什么,这里Konux告诉你,其实是舍弃了精度,各位想想,不就是装人吗?这人的胳膊、腿、肚子等等咱都不要了,就剩个头来表示人,这样有限的空间装的人就会变多(这个比喻好像挺精污)。这下知道为啥实数不能直接“==”比较了吧,因为实数是“残缺不全”的,或者是不精确的!
好了接下来做总结:
1.实数可以直接表示,也可以用E记法表示
2.实数的取值范围是:[-3.4028235E+38, 3.4028235E+38]。
3.实数并不精确。
4.实数的精度能保证至少6-7位有效数字是准确的。
5.若实数超出范围,则会显示±Infinity(无穷),所以应控制实数不超此范围
字符串(string):
在介绍字符串之前,我们先介绍一下字符(char):字符指类字形单位或符号,包括字母、数字、运算符号、标点符号和其他符号,以及一些功能性符号(这是百度上粘贴下来的)。
这啥?真是不讲人话!通俗一点,像‘a’、‘5’、‘我’、‘%’、‘ ’(这是空格) 、‘+’等等就叫字符,字符是单个的,而且需要打上单引号,比如‘5’是字符,而5是数字,这两个是不同的数据类型。
认识完字符,那么字符串也就好说了,就是把字符连成一串嘛,我们这个教程中说的每个句子,都是字符串,比如“这个教程真棒! 学废了学废了(”就是一个字符串,字符串需要用双引号表示。
如果我们需要获取字符串中的某个字符该怎么办呢?
其实啊,字符串就像字符排成的长队一样,字符都是有下标的,下标是啥?简单来说就是咱们去某些饭店里拿的排号,我们是第几号,就表示我们是第几个吃,字符串里的字符手里拿的号码就是它们的下标:
字符串的下标从左到右,从0开始依次递增,上图字符串中,下标0的字符是‘这’,下标14的字符是‘(’,下标7的字符是‘ ’(空格也是字符哦)。
布尔(bool):
布尔数据类型应该大家已经不陌生了,条件判断函数的输出类型就是布尔,布尔只有两种值:True或False,编辑器中中文化为真和假,布尔类型用于判断一个条件是成立的还是不成立的,如果成立,则为真(True),如果不成立则为假(False)。
二维向量(Vector2):
因为咱们游戏是2D的,三维向量几乎用不到,所以以后说到向量一般就是指二维向量。
二维向量,又称平面向量,平面向量是在二维平面内既有方向又有大小的量,物理学中也称作矢量,比如力就是个矢量,应该初二物理就学过了。
在数学上,向量在x - y坐标系上表示为这样:
如图就是一个起点为(1,1),终点为(4,2)的向量,向量的模(大小)为:
就是勾股定理,当然这种方式不太直观,另一种直观的说法是,向量的大小的值等于向量的长度(虽然这个说法并不科学)。看起来有点麻烦,是吗?但好消息是,编辑器中的向量的起点都位于坐标原点(0,0),所以用向量的终点(x,y)就可以表示一个向量,所以正好向量的值就等于坐标的值:
所以在编辑器中,向量就可以理解为坐标(坐标其实也是向量),以下将部分函数的描述做解释
向量之间的角度:坐标之间的角度
向量之间的距离:坐标之间的距离
向量计算:坐标计算
比如向量(a, b) ± (c, d) == (a±c, b±d)
向量网格化:坐标网格化
将坐标“吸附”到规则的0.64网格坐标上
如图所示,红点坐标网格化后会变成绿点坐标。
当然了,数据类型远远不止上面这几个,找到全局变量函数,就可以找到所有的数据类型了。
以上讲的数据类型是最基础的且最难的数值数据类型,其他的大多数数据类型属于复合数据类型,我们使用时仅用于指代而不涉及计算,所以很简单。
数值数据类型之间的转化:
数值数据类型之间为啥要转化呢?其实就像多头充电线一样,函数的参数只接收一种数据类型的数据,不同的函数的参数能接收的数据类型是不同的,所以原始的数据类型只有经过转换之后才能用。
比如血量、游戏资源、游戏时间都是实数,而我们希望用一个整数来设置这些量时,就必须进行转换,比如有一个名为time的整数变量,想让游戏时间等于这个变量,就需要设置游戏时间 = 转换time为实数,一般对数字进行转换相关的函数都位于数学类。
整数转化为实数:
此转换很简单,比如整数9,转化为实数就是9.0。
实数转化为整数:
实数转化为整数有点东西,比如实数9.0转化为整数就是9,如果8.9转化为整数呢?其实会转换为8,实数转换为整数时,整数只取实数的整数位,不关心小数位,不是四舍五入,四舍五入有另外相关的函数,比如-3.99,取整之后为-3,我们称此种取整方式为“向零取整”,实数取整符为[],比如[-3.99] == -3。
布尔转化为字符串:
布尔的值为True或False,所以转换为字符串之后就是“True”和“False”,不是“真”和“假”哦,真和假只是编辑器中文化过的。
整数转化为字符串:
很简单,比如整数10,转化为字符串后就是“10”,包含‘1’和‘0’两个字符,下标从左到右依次为0和1。
实数转化为字符串:
和整数转化为字符串类似,比如实数3.1415,转化为字符串之后就是“3.1415”,这是一个含有6个字符的字符串。
二维向量转化为字符串:
二维向量一般表示为(x,y),所以字符串也是这样表示的,比如向量(0.64,1.28),转化为字符串后就是“(0.64,1.28)”,11个字符的字符串。
高阶常用动作:
变量:
经过上面对于数据类型的“熏陶”,你应该能懂,变量可以指代某个数据类型的某个数据,变量分为两个部分,变量类型和变量名,变量类型用来表示变量里存放的数据类型,变量名则是变量的“外号”,方便我们以后要用这个变量时,可以叫它。变量名中可以写英文、中文、日文、数字字符、各种符号,不过为了变量名字的可读性,建议使用纯英文写法,若不会英文,可使用纯中文写法,比如咱们要设置一个实数变量表示最小时间,英文可写为minTime,这里的变量命名采用的是“小驼峰”法,即第一个单词开头小写,后面的单词开头大写,如果用纯中文,命名为“最小时间”也可以。
正是因为全局变量可以指代数据并可进行计算,所以变量是极其重要的,变量是触发器各功能模块之间的“信使”,触发器A中得出的数据,通过全局变量传送给触发器B,这样触发器之间才能相互协同配合。
对于变量的学习,可以看官方文档教程:
看教程时,要着重了解全局变量,单位变量,变量的自身运算,数组和二维数组。
咱们这里做一下补充,由于之前一直讲的是全局变量,所以就不讲了。
单位变量:
单位变量比全局变量多了一个参数,那就是要选定一个单位,单位变量就像是单位身上的属性一样,只在此单位上才能用,在其他单位上不能访问此变量。
要获取单位变量的值,就需要点击变量,找到[从单位变量中获取]函数,填入需要获取的单位,然后填入对应单位上的单位变量名即可。
数组:
数组的概念其实你应该不陌生,字符串就类似于数组,字符串里有很多个字符,这些字符组合而成的字符串就是字符数组,而广义上的数组是里面装有同一数据类型的多个变量所组成的东西,所以数组也有下标,和字符串类似。
如上所示的二维向量类型的数组的函数写法如下:
此数组名为var,那么数组有什么好处呢?因为我们设置全局变量也能达到同样的效果,比如下面这样:
用变量名来表示下标,其实这是四个独立的变量,而不像数组那样把变量装进一个组里,数组中的元素之间彼此相连,数组的优点是里面的元素之间可以相互访问,比如我们想从数组下标0的变量访问下标1的变量,直接将下标+1即可,而不用手动选择变量,因为数组元素之间是有关联的。
二维数组:
同数组(一维数组)类似,二维数组只是在一维数组的上面加了一层维度而已,所以其需要用两个下标表示:
其中横向的下标记为下标i,纵向的下标记为j,红色部分数字就是数组里装的变量的值。
二维数组下标表示为arr[j],其中arr是数组名,表示数组的横向下标,[j]表示数组的纵向下标。所以比如图中整数10可以表示为arr[0][0],47表示为arr[3][1]。一维数组是线性结构,所以用一个下标就可以表示它里面的每个变量,二维数组是平面结构,所以需要两个下标确定一个变量。
注释:
注释是个很重要的函数,虽然它对触发器一点都不重要。注释函数里可以写一些东西,此函数在地图运行时不会执行,它就是给作者自己看的,有时候我们的触发器会写很多内容,写到甚至自己都记不清楚自己写这个是用来干啥的了,这个时候,合理的注释可以让我们知道自己写的东西是用来干什么的,使触发器具有“可读性”,比如给大家看看Konux写的触发器(这是斗地主的触发器):
如图所示,红框部分都是注释,用于给我自己看的,因为此地图有53个触发器,内容非常庞杂,所以一定要在写一个功能时做注释,不然可能就看不懂自己写的什么东西了。
For和while循环:
for循环和while循环函数也是常用函数,一般来说while循环用的少(而且不太安全),只使用for循环就足够。
for循环在官方文档教程里有我写的非常详细的介绍:
这里就不详细讲解了,for循环主要应用于要循环做一部分函数组时使用。
比如我们上面的定义数组var的函数就明显都是相同的步骤:
所以用for循环可写为:
此操作和上面的等效,如果要定义114514个元素的数组,要用第一种方法一个个手写可能需要写到头发掉完,而用for循环,就只是改个参数的事,相当方便:
单位组:
单位组,和数组仅仅只差两个字(???),所以他们有共同点,数组绝对不是只能放数字,任何已有的数据类型都是可以装的,比如单位。
这差不多就算是单位组了,你看,装的都是单位,而且是个数组,那不是单位组那是啥?实际上,单位组的底层结构就是这样,只不过,单位组相关函数对数组进行了“封装”,单位组帮你管理这些数组,我们不需要亲自动手去操控数组,只需要用单位组函数下命令,单位组函数就会自动帮我们完成装有单位的数组的操作。
在使用单位组之前,我们需要先创建一个单位组,并用一个变量表示它:
因为我们获取单位组的方式只有用“最后创建的单位组”函数获取,和之前最后创建的单位类似,如果刚创建不用变量记着它,那么很可能以后想用的时候就用不了了!
Ok,既然我们创建了单位组,那么就要想给它加单位进去了:
一般来说,单位组添加单位使用上图所示的“添加关卡内所有单位(指定条件)”函数最好, 在条件里,我们就需要描述我们选取的单位到底是什么,在单位组中,其中的单位都叫选取单位(既不是自身单位,也不是触发单位),所以这里判断选取单位的数据类型为墙1,那么关卡内的所有墙1都会被选进单位组。
接着,我们get到了想要的单位进入单位组后,就需要对这里面的单位进行操作了:
如图所示,使用“选取单位组内所有单位做动作”函数即可使这些单位同时做动作,这里写一个删除选取单位,那么关卡中所有的墙1就会被删除。
需要注意,不能在“选取单位组内所有单位做动作”函数中的动作里使用等待或计时器等具有延时的函数,否则会出bug,如果需要等待,那么请将延时放外边写: