使用GameMakerStudio2 制作《功夫》小游戏学习总结

注
[注] 教程地址: GameMakerStudio2 YOYOGAME制作的游戏引擎,接下来的文档中简称GMS2
导入资源
由于红激教程教的是gamemaker8,导入资源包为.gmres文件,这个旧版本的资源包无法直接导入到GMS2,需要经过一些列版本转换才可以转换成可导入GMS2的资源包
将*.gmres文件导入到gamemaker8中,我用的是gm8.1,将*.gmres文件拖入gm8中,选择导出项目*.gm81,接着将*.gm81文件拖入到gamemakerstudio1.4,再选择导出项目*.gmz文件,不要以为到这就结束了,然后要把*.gmz文件导入到GMS2,其实这时候是新建了一个包含资源的新项目,如果只是想要资源包,那还需要再GMS2中导出资源包,最终导出的*.yymps文件就是可以直接导入到GMS2中的资源包啦。 *gamemaker8.1资源: https://wwr.lanzoui.com/b02i7m49i密码:2bgy
gamemakerstudio1.4资源
https://www.zy990.com/ziyuan/soft/56.html
游戏制作流程
创建玩家,设置基本属性,血量,y值
创建对象(object)obj_player,精灵为spr_player_walk
添加创建事件(create),添加以下代码
face=1;//方向1右 -1左
jump=0;//跳跃0 1
jumpface=0;//跳跃方向-1 0 1
state=0;//状态0移动 1出招 2收招
timer=0;//状态计时器
hp=9;//血
//***固有
image_speed=0;//动画速度=0
y=191;//地平线
创建房间,设置宽高,背景,放入玩家
创建room,宽256,高240,帧率60,加入背景贴图和玩家,修改缩放比为400%,在gm8中需要修改全局变量,但在GMS2中会发现找不到全局变量窗口了,那么在GMS2中如何调整缩放比呢?
打开房间设置propertices-Room1,打开视口和相机(viewports and Cameras)下拉单,将启用视口(Enable Viewports)打勾,选择一个视口(viewport),比如viewport1,将可见(visible)打勾,下面相机属性(Camera Properties)的宽高就是room的宽高,视口属性(Viewport Properties)的宽高就是最终游戏窗口的宽高,如果要调整缩放比为400%,那么就将宽和高分别设置为1024和960即可。
玩家的左右移动,坐标限制
在obj_player中创建步事件(step),添加以下代码
var dx,dy;//临时变量
dy=0;//上下按键状态-1上 0 1下
dx=0;//左右按键状态-1左 0 1右
psb=1;//玩家移动速度
//***按键功能
if(jump==0&&state==0)//可相应按键
{
if(keyboard_check(ord("A")))//左 注意这里是是双引号,gm8中是单引号
{
dx=-1;
image_index+=0.1;
}
if(keyboard_check(ord("D")))//右
{
dx=1;
image_index+=0.1;
}
}
//***坐标变化
x+=dx*psb;
x+=jumpface*psb*2;
//***坐标限制
if(x<24)
{
x=24;
jumpface=-jumpface;
}
if(x>room_width-24)
{
x=room_width-24;
jumpface=-jumpface;
}
玩家上下按键检测
将以下代码添加到上面按键功能区块中
if(keyboard_check(ord("W")))//上
{
dy=-1;
jump=1;
if(dx!=0)jumpface=dx;
direction=90;
speed=5;
gravity=0.25;
sprite_index=spr_player_jump;
}
else//注意,不要漏掉
if(keyboard_check(ord("S")))
{
dy=1;
sprite_index=spr_player_jump;
}
玩家状态新定义,出招设计
将以下出招设计代码添加到上述按键区块中,其中scr_state_set()为接下来会编写的脚本
if(keyboard_check(ord("J")))&&jump==0//出腿
{
if(dx!=0)//左右腿
scr_state_set(3,1,16);
else
if(dy==1)//蹲腿
scr_state_set(2,1,16);
else//原地腿
scr_state_set(2,1,16);
}
if(keyboard_check(ord("K"))&&state==0)//出拳
{
if(dy==1)//蹲拳
scr_state_set(1,1,16);
else
if(dy!=-1)//原地拳
scr_state_set(0,1,16);
}
飞踢出招放在按键区块下面,不放在里面
//***飞踢
if(jump==1&&keyboard_check(ord("J"))&&state==0)
{
scr_state_set(5,1,16);
}
重复使用的脚本
创建脚本(Scripts),将以下代码添加到脚本中
function scr_state_set(){
sprite_index=spr_player_atk;
image_index=argument0;
state=argument1;
timer=argument2;//出招定格帧数
var dx,dy;
dx=x+26*image_xscale;
dy=y-16;
audio_play_sound(snd_atk1)//注意gm8里是sound_play
if(collision_point(dx,dy,Obj_enemy,0,0))
{
if(Obj_enemy.hp>0)
{
audio_play_sound(snd_hit1)
timer+=16;
instance_create_depth(dx,dy,0,Obj_fx);//obj_fx为攻击效果对象,具体创建可看下面攻击效果的实现
Obj_enemy.hp-=1;
Obj_enemy.hited=16;
}
}
}
脚本中涉及到了一个未创建的对象(obj_enemy),因此可以先创建一个obj_enemy对象,精灵为spr_enemy_walk
动作控制逻辑
以下为出招、收招、下落状态下需要执行的代码,放在按键区块下面即可
//***出招
if(state==1)
{
timer-=1;//计时器自减
if(timer<=0)//出招结束,变换状态
{
state=2;//收招
timer=8;//收招计时器
if(image_index==1||image_index==4||image_index==5)//下蹲类出招的收招动作
{
if(image_index==5)
{timer=100;}//飞腿再空中只能一次
sprite_index=spr_player_jump;//变换动作
}
else//其他动作类收招动作
{
sprite_index=spr_player_walk;
}
image_index=0;//子图像序号归零,写这句话其实没什么用,因为给sprite_index赋值后会自动执行这行代码
}
}
//***收招
if(state==2)
{
timer-=1;//计时器
if(timer<=0)
{
state=0;//变为可移动状态
sprite_index=spr_player_walk;//变为站立动画
if(jump==1)sprite_index=spr_player_jump;//变为跳跃动画
image_index=0;
timer=0;
}
}
//***下落
if(direction==270&&jump==1)
{
if(y+speed>191)
{
y=191;
speed=0;
gravity=0;
jump=0;
state=0;
timer=0;
jumpface=0;
sprite_index=spr_player_walk;
}
}
绘制像素效果失真修复
为obj_player添加绘制事件(draw):
//***绘制自己
draw_sprite_ext(sprite_index,image_index,floor(x),floor(y),image_xscale,image_yscale,0,c_white,1);
//***绘制血槽
draw_sprite_ext(spr_blood,hp<6,112,210,-hp,1,0,c_white,1);
为obj_enemy添加绘制事件(draw):
//***绘制自己
draw_sprite_ext(sprite_index,image_index,floor(x),floor(y),image_xscale,image_yscale,0,c_white,1);
//***绘制血槽
draw_sprite_ext(spr_blood,hp<6,112,210,hp,1,0,c_white,1);
人物转向判断
在obj_player步事件中添加:
//***方向变化
if(jump==0)
{
if(x<=obj_enemy.x)face=1;//朝右
else face=-1;//朝左
}
image_xscale=face;
敌人创建
为obj_enemy添加创建事件:
face=-1;//方向1右 -1左
jump=0;//跳跃0 1
jumpface=0;//跳跃方向-1 0 1
state=0;//状态0移动 1出招 2收招
timer=0;//状态计时器
hp=9;//血
hited=0;//是否被击中
//***固有
image_speed=0;//动画速度=0
y=191;//地平线
绘制血槽
查看上方绘制像素效果失真修复
打击效果实现
创建对象obj-fx,添加创建事件,书写以下代码:
image_speed=0;
alarm[0]=24;//计时器启动
创建计时器0(Alarm0),添加以下代码:
instance_destroy(Obj_fx);//24帧后销毁
敌人死亡判断
在obj_enemy中添加创建事件,添加死亡判断代码:
if(hp<=0)
{
if(timer==0)//死亡第一帧
{
audio_stop_all();
audio_play_sound(snd_fall1,0,false);
sprite_index=spr_enemy_dead;
}
timer+=1;//计时器自加
if(timer>180)game_restart();//重启游戏
exit;
}
简单的敌人逻辑
在创建事件中死亡判断下面添加移动逻辑:
//***简单的移动逻辑
if(hited==0)//未被打击
{
if(x>=Obj_player.x+12)//在右边
{
x-=0.25//左移
image_index+=0.1;
}
else
if(x<=Obj_player.x-12)//在左边
{
x+=0.25;//右移
image_index+=0.1;
}
}
else hited-=1;//静止,等待打击效果结束
if(x<=Obj_player.x&&jump==0)face=1;
else face=-1;
image_xscale=face;
背景音乐加入
创建对象obj_ctrl,添加创建事件:
audio_stop_all();
audio_play_sound(snd_music,1,true);
结束
至此,红激教程视频内容结束,但我看到素材包里有敌人的攻击精灵,我想实现下,我没有设计出招、收招动作,只是简单的设计了下自动攻击。
敌人攻击分支
在obj_enemy的创建事件中添加攻击逻辑:
//膝击
if((x-Obj_player.x)<20&&(x-Obj_player.x>-20))
scr_state_set2(spr_enemy_atk0,0,1,32,x+12*image_xscale,y-13);
else
if((x-Obj_player.x)<27&&(x-Obj_player.x>-27))
{
scr_state_set2(spr_enemy_atk1,1,1,32,x+26*image_xscale,y-29);
}
}
在创建计时器alarm[0]
state=0;
sprite_index=spr_enemy_walk;
hited+=32;
新建一个敌人攻击脚本:
function scr_state_set2(argument0,argument1,argument2,argument3,argument4,argument5){
sprite_index=argument0;
image_index=argument1;
state=argument2;
alarm[0]=argument3;//出招定格帧数
var dx,dy;
dx=argument4;//x+26*image_xscale;
dy=argument5;//y-16;
audio_play_sound(snd_atk1,0,false)//(索引,优先级,循环)
if(collision_point(dx,dy,Obj_player,0,0))
{
if(Obj_player.hp>0)
{
audio_play_sound(snd_hit1,0,false)
instance_create_depth(dx,dy,-1,Obj_fx);
Obj_player.hp-=1;
}
}
}

还以为B站专栏可以识别md文档的代码块,竟然不可以。
岂可修