https://www.udemy.com/make-an-action-rpg-in-gamemaker-studio-2/
在udemy上找到了一个这个比较好玩的教程,近期跟着这个做一个arpg游戏,我且称它为飞天小狐。
键盘检测
if keyboard_check(ord("A"))//如果不加ord,人物将会一直移动,只会在按下A的时候停止移动
暂不知这是个什么情况?????keyboard_check(vk_right)直接就可以同样效果,keyboard_check_pressed(),keyboard_check_released()同样是这种情况?????
窗口视角
图1 图2 图3
Camera Properties是你在room中可见的一个视觉范围,长x宽是320x180,而下面的Vieport Properties是你在桌面显示的窗口的属性,它的范围是1024x768,由于两者的长宽比不相等,于是乎就在加载后的窗口(图2)出现这样的人物被拉长的效果,这时候只要调整好长宽比,把Vieport Properties的Width:Height调为640x360就好了,出现图3的最终效果。
碰撞检测
if keyboard_check(ord("S"))&&!place_meeting(x,y+2,obj_solid){
y += 2;
}
这里的代码区别于前面在indienova的教程上的方法,用到了一个函数place_meeting这里用于检测当前object 在x,y+2的位置是否与obj_solid发生冲突,之前我们用的方法是给这个obj开启物理属性,给它一个碰撞形状。
两者还是有些不同的,用函数的话,现在还不知内部怎么判定的,这个十分好用,无论你在sprite中设置的原点在哪,都不会影响它的判定,因为一般obj的x,y都是由原点所决定的,而这个函数却无影响。再就是呢,这个一个函数只能判定一个obj的碰撞,所以不如设置物理碰撞形状来的简便
手残把Room Editor给关了,然后找了半天,终于在帮助文档中找到了这几个视图的快捷键
Collision Mask
这个spr的属性让我明白了上次的疑惑place_meeting是如何检测碰撞的,这个默认类型是矩形,也就是player和solid的碰撞检测范围都是矩形阴影,当然我们在这里可以随意的改动其轮廓,让它更为真实。我们的obj_player通常会有多个sprite的转换,而每个sprite你都要设置,所以呢,这样很麻烦,而且很容易忘记,对于像我这样的新手来说,我们可以在object里的Collision Mask里设置好碰撞阴影,但是这样有些粗糙,因为每个的sprite对碰撞判定可能大不相同,而这样就会可能产生一些碰撞判定误差
Variables
instance variables 和 local variables以及global variables的区别,对于一个object来说,它会拥有多个event,instance variables是实例变量,在object所有的event里都可以直接调用这个变量,同时,父类也能调用子类的 instance variables。而且它是直接用,不需要什么申明,一般在Creat里初始化变量,而local variables则需要 var 关键字定义,但作用域只在一个代码块中,就是一个event中。而global variable就比较厉害了,对于整个game,不同的地方都可以调用它。
Enums
枚举变量在之前用的不是很多,因为确实不是很习惯这类,觉得很麻烦,但是这次视频倒是给了我些一些新的思想,对于一项工程的整体构思,这点十分重要,贴几行代码来
Create
image_speed = 0;
player_speed_ = 1.5;
direction_facing_ = dir.right;
global.player_health = 4;
enum player{
move
}
enum dir{
right,
up,
left,
down
}
//Sprite move lookup table
sprite_player[player.move,dir.right] = spr_player_run_right;
sprite_player[player.move,dir.up] = spr_player_run_up;
sprite_player[player.move,dir.left] = spr_player_run_right;
sprite_player[player.move,dir.down] = spr_player_run_down;
Step
image_speed = 0;
var _animantion_speed = 0.6;
if keyboard_check(ord("A"))&&!place_meeting(x-player_speed__,y,obj_solid){
x -= player_speed_;
//sprite_index = spr_player_run_right;
direction_facing_ = dir.right;
image_speed = _animantion_speed;
image_xscale = -1;
}
if keyboard_check(ord("D"))&&!place_meeting(x+player_speed_,y,obj_solid){
,,,
}
if keyboard_check(ord("W"))&&!place_meeting(x,y-player_speed_,obj_solid){
,,,
}
if keyboard_check(ord("S"))&&!place_meeting(x,y+player_speed_,obj_solid){
,,,
}
sprite_index = sprite_player[player.move,direction_facing_];
我们在初始化的Create里声明了player玩家状态变量,以及一个sprite_player枚举变量,还有一个用来存储玩家状态的二维数组[攻击/移动/闪避,向左/向右/成功]。这样一方面提高了代码的可读性,同时我们可以在Step中看到,我们声明的instance variable :direction_facing在每次键盘状态检测语句中都记录好当前Object的状态,然后在事件的最后sprite_index更新当前操作后Object的状态。这样对于大型软件的维护十分的有帮助,以后软件开发和游戏开发要多练习掌握这种思想,毕竟是面向对象的设计。