编程语言
首页 > 编程语言> > 极速入门Gamemaker编程语言

极速入门Gamemaker编程语言

作者:互联网

极速入门Gamemaker编程语言

开篇废话

这文档适合已经会使用其他编程语言(C#、C\C++、java、python等)的游戏开发爱好者学习 (逛CSDN怎么会有不会编程的人呢) ,如果不会其他语言也可以看个大概,毕竟字不多,已经入门 GML 的新人也可以看看这个文档,或许能发现一些有趣的东西。

不建议元老巨佬等详细研究此文档,可能会看成《GML 急速出门》。

这份文档主要基于 GM 8.0,理论上大部分适用于GMS、GMS2,还请GMS、GMS2用户以实践为准。

文档写的略急促,如果发现有问题或讲错了敬请指出。

如果这文档反响不错,我打算完善好这个《GML极速入门》后再写些其他的极速入门系列,例如《Unity 急速转战 GM》或者反过来转。

作者联系方式:QQ 2293840045

目录

文章目录

GM软件的基本の基本

软件的左边一列(GMS2默认在右边)的文件夹是游戏的资源,例如游戏的图片(sprites)、声音(Sounds)、脚本(Scripts)等,把准备好的素材导入到这里即可。

每一项资源可以再细分文件夹,这点随开发者喜好随意整就行。

资源经常要在代码中调用,所以资源的名称要符合标识符命名规则(例如数字不能开头不能包含特殊符号等)。

初学 GML 的时候可以建立一个游戏物体,添加 create (创建)事件,在这里面写代码(GM8和GMS要在右边找到代码小方块,拖到左边空白区域才行),然后创建一个房间,把这个物体放到房间里面。

觉得上面那个麻烦也可以新建房间,然后进房间设置,有个“房间创建代码”的按钮点开可以写代码,这里就像程序的 main 方法一样,一运行就执行。

GM中的面向对象

上面介绍的资源中,有一个 Objects ( GMS2 中文翻译可能叫“物体”)最为重要。

Object 可以直接理解为其他语言的 class ,而游戏中每生成一个物体,就是 new 了一次这个 class 的实例。

继承

GML 没有封装和多态(也可以说到处都是多态),但可以使用继承,在 object 物体编辑的面板上指定父物体即可。

这里的继承父物体是 class 继承父类的意思,而不是 Unity 中的物体父子级关系。

要注意,GML的继承和传统继承区别很大。

继承可以使子物体拥有父物体的变量,可以使子物体没有实现的事件由父物体实现。

很特殊的一点,传统的继承中,每 new 一个子类都会产生一个父类,而GM当中的父类可以永远不被实例化,但这并不影响子类继承父类成员。

重写

例如父物体在 step 事件中有x += 1代码,他的子物体如果没有自己的 step 事件,则这个子物体也会在 step 事件触发时运行x += 1

但如果这个子物体存在自己的 step 事件,则不会再运行x += 1了,如果想运行子物体的某个事件后(或前)再运行父物体的相同事件,则可以在子物体中需要运行父物体事件的位置调用event_inherited()方法,就等同于 java 的super.xxx()或者 C# 的 base.xxx()

即便子物体的 step 事件代码为一行注释,那么它也算作“子物体存在自己的 step 事件”。

至于为什么是一行注释而不是空代码呢,因为GM会自动删除没有代码(或注释)的事件,所以如果想“顶掉”父物体事件,写一行注释即可 //

基本的语法

GML的基础语法和C\C++、C#、Java这类语言极度相似,且作为一个专为游戏而生的语言,有相当多的特性用起来非常简单、舒服。

GML语言使用花括号{}表示代码块,语句结尾可以加分号;表示结束也可以直接换行。

和大部分语言一样使用点.引用成员,例如Player.hp=0就可以干掉玩家。

变量

GML是弱类型的语言,就是说使用变量无需指定数据类型。

本地变量

可以向下面这样直接使用变量

name = "黎明"
show_message("这是" + name) // 显示 这是黎明

show_message() 是gm内置方法,可以让游戏弹出一个窗口并显示内容

直接赋值产生的变量我习惯叫做本地变量,这个变量作用在当前实例上,就类似在 java、C# 的 class 中直接定义的 public String name;,所以这个方法一般用来定义属性,例如血量、名字等等。

临时变量

如果是为了临时计算而使用变量,一般会在声明变量时加个var前缀:

// GM8
var a,b,c; // 这是 GM8 语法的一大缺陷,这里的 var 语句结束必须要加分号
a = 233 // 并且不能边声明变赋值,只能单独写一行
   
// GMS2
var a,b = 123,c // GMS 就没有上面的问题了

var 的变量我习惯叫做临时变量,这个变量仅仅作用于当前的事件或脚本中,这就和在其他语言的方法中int a = 123;一样,方法结束变量就会消失(忽略闭包啥的)

全局对象变量

除此之外,还有个全局对象变量,用起来大概这样:

// 用起来就像给一个叫做 global 的对象属性赋值一样,所以我叫它“全局对象变量”
global.a = 123 

这种变量就和他名字一样,在全局任意位置都可以使用,作用于贯穿整个游戏程序的生命周期,从声明,也就是第一次赋值,持续作用到游戏程序关闭。

global 可以理解成 GM 帮咱实现好的一个单例,用就完事了。

为啥不直接叫“全局变量”呢,因为GM8中已经有这个东西了,语法格式和 var 一样,需要把 var 替换成 globalvar ,然而这东西缺点挺多,最新的GMS2中已经移除了这个语法,所以不再说明。

数据类型

就两种类型

GM的数据类型不去深挖,其实就两种:数字、字符串。

数字就是数字,不分整数小数,字符串就不用说了。

不过有个不太舒服的地方就是 GM 没有隐式类型转换,就是说"Hello " + 233会报错,因为字符串不能和数字相加,需要调用string()方法转换一下:"Hello" + string(233)

字符串定界符使用双引号或单引号都行

true和false

如果运行show_message(true)会直接显示一个数字 1 出来,所以可以猜到换成 false 就是显示数字 0,这里和 C 语言处理 bool 值好像挺像的。

目前我们知道了 true => 1,false => 0,但有意思的是 GM 处理逻辑运算时,会把所有的正整数当做 true,其他整数当做 false 处理,所以show_message(123 and 111)结果显示 1 ,show_message(-1 and 0) 显示一个 0。

上面只说了整数情况,小数情况比较奇怪,我在GM8中的测试结果显示,>= 0.5的小数当做 true,< 0.5 是 false,我也不清楚为什么 0.5 是分界线

noone

GM 中使用 noone 关键字来表示空,就像其他语言的 null 关键字一样。

实际上 noone == -4

id与资源

那问题来了哈,如果说GM只有数字和字符串两种类型,那么引用的资源是什么类型呢?引用的实例呢?

GM 中每个实例都有一个 id,这个 id 类似其他语言中一个实例的内存地址,是一个实例的引用。可以show_message(id)看到当前实例的id

不卖关子了,估计都能猜到,id与资源都是数字,并且都是正整数。

利用正整数 => true 的特点可以直接判断某个id或资源是否存在:

// 假设 target 是个实例引用
if (target){ // 如果没有这个if,那么下面那句可能报错
    target.y -= 100 // 如果target存在,就让它向上移动
}

数据结构

GM本身也有一个数组,但是很难用,甚至都不能获取数组长度:

arr[0] = 1
arr[1] = 11
arr[2] = 111
arr[3] = 1111
var i;
for(i = 0 ; i < 4 ; i += 1){ 
    show_message("这是第" + string(i+1) + "个元素,值是" + string(arr[i]))
}

不过好在 GML 提供了列表、字典等经典数据结构,操纵它们的函数都是ds_开头,具体可以查阅官方文档,我只是在这里提醒一下有这些东西。

这些数据结构还都自带序列化方法,可以方便的做网络传输或者数据保存。

结构语法

IF

if 语法和 java 啥的一模一样:

if(xxx){
    
}else if(xxx){
    // 可以很多else if
}else
    show_message("可以省略花括号只写一句代码")

python来的同学一定注意,没有 elif 语法,并且所谓的"可以省略花括号只写一句代码",也不是python的那种省略花括号

这里 if 后面的圆括号可以省略,像 python 一样,但是个人感觉怪怪的。

WHILE

while 也和 java 啥的一模一样:

while(true){
    show_message("你的弹窗永远也点不完")
}

python来的同学又要注意,没有while … else … 语法

FOR

for 也也和 java 啥的一模一样:

var i; // 难受,GM8 不能把这句话写到 for 那一行
for(i = 0 ; i < 10 ; i += 1){ // 难受*2,GM8 没有++,不过 GMS 有
    show_message(i) // 只显示数字不用 string 转换
}

python来的同学可能一脸懵逼(应该没),这段代码翻译成python是:

for i in range(10):
       print(i)

REPEAT

这个东西是为了方便开发游戏 GM 自己造出来的,语法大概这样:

repeat(3){
    show_message("重要的事情说三遍 ! ")
}

python同学猛地站起来说:这个我熟啊!

for i in range(3):
       print("重要的事情说三遍 ! ")

… 可惜这个语句不怎么实用 …

总结

基本上语法和java、C#那些差不多,还有个 switch 游戏机语法也一样,不过因为用得不多我就不列举了。

并且breakcontinue语句也一样用

运算符

数学运算符就是 + - * / 不用说,还有个 mod 求余和 div 整除,没了。

a = 10 mod 3 // 结果是1,mod等同于其他语言的%
b = 10 div 3 // 结果是3,div等同于某些语言的\

比较关系用> < >= <= !=不等于 ==等于,应该也不用说

比较有意思的是在进行逻辑运算时,等于写成单等号也行,不会变成赋值,但比较奇怪,个人不喜欢。

逻辑运行可以用常见的! && || 形式,也可以用not and or形式。

个人喜欢字母形式,因为有代码着色,看起来舒服一些

赋值运算有= += -= *= /=没什么好说的

连接字符串用加号就行+,记得把数字转换成字符串,用string()方法

脚本

脚本是GML中定义方法的方式,在GML的面向对象当中方法不属于某个实例,而是直接放在全局资源里面了,谁调用都可以。

脚本编写

新建脚本就是在资源那一栏的Scripts直接创建脚本就行,然后起个名字,这个名字就是调用时用的方法名了。

参数定义在哪里呢,,,,没有,对。不用定义参数,GML 的脚本是可以随意接受任何参数的,但最多不能超过16个。

因为参数问题,GML显然不支持重载,并且GM8没有文档注释写法,所以调用函数的时候一般比较蒙蔽,建议养成在脚本开头用注释写文档的好习惯。

GMS2支持文档注释,可以给方法加参数提示了。

在脚本中引用参数要使用argument内置变量,这是一个数组,里面每个位置存了一个参数。例如写个脚本实现计算加法

// 这是脚本里面
return argument[0] + argument[1]
// 假设那是Add脚本,调用它就是
res = Add(1,2) // 返回一个3

奇特的脚本调用机制

在脚本中调用本地变量时,调用的变量是执行脚本的那个实例的变量。

例如写了一个控制移动的脚本:

x += 1 // 碰壁移动,永不回头

那么谁调用了这个脚本,谁就会向右移动。

这点还是挺有意思的,好像弥补了 GML 的残废继承和没有多态的缺点。

比如写了一个“敌人死亡”的脚本,脚本里面实现了死亡动画、玩家加分、掉落物品等功能,那么每个敌人死亡时都可以直接调用这个脚本,脚本中也可以很方便地读取到敌人实例的属性。

在脚本中疯狂用 var !

估计刚才看脚本参数的时候各位都吐槽了一句:“这么麻烦?”,然后聪明的各位一定想到了这种写法:

name = argument[0]
level = argument[1]
show_message("你就是"+name+"啊,只有"+string(lvevl)+"级呢")

这样写相当 nice,但是一定不要忘了第一行加上一行:

var name,level;

因为不写 var 的话,这个 name 和 level 是会当做本地变量永远存储在调用者实例上面的,吃点内存还好说,万一变量名冲突了就麻烦了,所以脚本中产生的变量一定要var var var。

标签:脚本,Gamemaker,变量,编程语言,GML,物体,var,GM,极速
来源: https://blog.csdn.net/Reimenn/article/details/113787091