简介接后文,嗯=-=。。。目前游戏的DEMO还在开发中所以就没有贴出来,然后只有我和美攻两个人做,所以也没什么时间去想宣传的策划,本教程说实在其实也没有特别多的东西,一方面是我自己目前所做的一些UI方面的经验,另一个就是为一些苦于UI的萌新们提供一些参考
不过,这篇教程就当作宣传出来好了。
附上女儿美照:
首先从UI这个东西说起,讲道理GMS作为2D游戏开发也是比较功能齐全而且挺强大的,开发上也比较简易,减少很多的麻烦!不过,划重点,GMS对UI的集成可以说几乎就是没有啊=-=。。。包括拖动条啊,点击事件啊之类的,可以说几乎这一片都是空白。
嗯,然后因为对应的战斗系统需要用到一些UI的开发,所以说还是挺麻烦的,怎么做到拖动,怎么做到点击道具,或者键盘选择道具,我这边做法还是比较粗暴的,单纯的把UI当作游戏来做就好了。
嗯,先简单介绍一下这个本UI的功能
嗯=-=。。。美攻小姐因为还有很多其他的东西要画,所以只画了水晶道具,其他的大概都是我瞎画的,这些撇开不谈,首先这个UI实现了一个拖拽的功能,一个道具选择的功能,以及合成的功能。
我们先从最初的生成说起,道具因为是随机生成的东西,所以我们没办法使用简单的拖动放置这样的方法去实现道具的生成,而是使用了GMS自带的数据结构去进行存储,我们先将精灵导入OBJ后,导入OBJ而不是使用draw直接绘制精灵,原因是我们可能后期会因为每个道具的效果不同而产生一些新的东西,这些独立的东西可能会需要一个OBJ去实现, 在脚本下创建一个create_item的脚本。因为道具需要存放在数据结构中,我们需要先生成一个链表
globalval list_item; global.list_item = ds_list_create();
链表这东西多快好省!目前也没有什么特别的业务需要用到其他数据结构,但是如果小伙伴们需要做一些特别的东西,可以自行选择所需要的载体。globalval 的意思是设定成全局变量,当然这些全局容器初始化应该是游戏刚开始的时候做的,你也不应该希望自己的道具在使用一次之后就丢失了吧。
刚创建的时候道具列表当然还是空的,我为了需要会去手动添加,你们也可以设定成打败怪物之后自动获取或者触碰捡到。
ds_list_add(global.list_item,object);
这行代码是在链表中插入一个新的节点,object就是我们之前做的道具,当然我比较不推荐这么做,object存储毕竟只是一个未实例化的对象,里面的数据一切都还没有初始化,我们可能会需要道具数量,是否绑定这种状态的东西。
这个我刚做的时候比较头疼,就是我需要一个怎样的数据结构去对,GMS是不支持结构体和类这种自定义的数据结构,不过挺好,GMS有个我们经常使用的东西,那就是object,我们可以创建一个不带sprite的object,纯粹作为存储我们需要的数据。
创建一个结构体在object内,在create动作内添加我们所需要的数据。
目前我们所需要的一个是道具OBJECT,和num,当然这些都是初始化的数据,这只是一个载体,因为女巫镇的道具是叫做水晶的东西,因此我定义了一个叫做my_crysal的东西来作为载体,初始化的时候你可以让他等于任何东西。
返回到之前的方法内,添加两行代码
fire = instance_create_depth(0,0,0,object9); fire.my_crysyal = object0; fire.num = 1; ds_list_add(global.item_list,fire);
这些可以对应情况对应使用,可以在怪内添加一个掉落道具的类,然后怪物死亡时使用
isExsist = false; var tmpInstance for(i=0;i<ds_list_size(global.item_list);i++) { tmpInstance = ds_list_find(global.item_list,i) if(tmpInstance.my_object==enemy.item) { isExsist=true; break; } } if(isExsist) { tmpInstance.num++; } else { item = instance_create_depth(0,0,0,object); item.my_object = enemy.item; item.num = 1; ds_list_add(global.item_list,item); }
=-=其实还挺简单的这样,做一些比较大型点的游戏道具系统与游戏数据还是比较麻烦的,当然有其他方法的小伙伴也可以告知我。
不过使用这种方法的请谨记,object没有实例所以没有数据,你需要先把他初始化成实例
现在我们已经把道具存进了数据结构中,接下来我们就是要呈现这些道具
我们专门创建一个展示的object,在object中的create方法写如下几点:
create_with = 96; create_heigth = 128; create_interval = 64; crystal_map = ds_map_create(); crystal_list =ds_list_create(); magic_list = ds_list_create(); ds_list_copy(crystal_list,global.item_list); for(i=0;i<ds_list_size(crystal_list);i++) { objTemp = ds_list_find_value(crystal_list,i); instance = instance_create_depth(create_with,create_heigth+create_interval*i,"instance",objTemp.my_crysyal); ds_map_add(crystal_map,i,instance); }
这边我的道具是显示在最左边,需要的话也可以改动with heigth这些值,无伤大雅。
做完这一点我们已经可以实现道具的显示了,当然也只是单纯的显示,没办法拖动也没办法选择。
我们先说键盘操作的选择,主要就是上下键的使用切换目标锁定的道具,嗯=-=首先你需要画一个选择框,刚好盖住道具就好了,在create内添加一行
select_crystal_index = 0;
用来记录你目前所选择的道具下标,在draw内添加
select_crystal = ds_map_find_value(crystal_map,select_crystal_index); draw_sprite(spr_select_box,0,self.select_crystal.x,self.select_crystal.y);
这样就可以让选择框覆盖你的道具,哦忘记说了,以上所有spr的质点都设置成middle centre
然后实现选择框变更的动画
if(keyboard_check_pressed(vk_down)) { if(self.select_crystal_index < ds_list_size(self.crystal_list)-1) self.select_crystal_index ++; } if(keyboard_check_pressed(vk_up)) { if(self.select_crystal_index >0 ) { self.select_crystal_index --; } }
选择框内添加如上,选择框设置双重判断,这个还挺好理解的,主要是用来限制不能选出界面,而后使用上下键就可以看到你的光标会随着上下改变而改变。
接下来说一说鼠标拖动,其实我还挺不喜欢gms的鼠标拖动的做法,gms没有按钮这种东西,因此做点击判断需要做两个判断,
- 鼠标是否进入碰撞体
- 鼠标是否点击
当然一种挺暴力的方式可以直接这么做判断,然后让item随着鼠标移动
if(collision_point(mouse_x,mouse_y,self,false,false) and mouse_check_button(mb_left)) { x = mouse.x; y= mouse.y; }
你这么做了会看到两种情况,一种是你拖动一个道具到另一个道具上的时候,另一个道具也会被你拖起来;当你鼠标移动速度快过游戏刷新频率的时候,道具会脱离你鼠标的控制。
所以我们需要实现拖动,就需要解决这两种办法,我这边做了一个双重的锁定,第一个锁定是锁定鼠标进入的物体唯一,也就是当你拖动一个道具的时候,无法去拖动另一个道具,解决了会同时拖动两个道具的问题,另一个是点击锁定,当你鼠标进入一个物体并点击之后,会锁定这个物体随着鼠标而移动,这样就不用担心鼠标移动太快导致道具脱离鼠标控制的情况。
先贴代码:
if(collision_point(mouse_x,mouse_y,self,false,false) and !global.chose_one) { self.chose_this = true; global.chose_one = true; } if(self.chose_this and !mouse_check_button(mb_left) and !collision_point(mouse_x,mouse_y,self,false,false)) { self.chose_this = false; global.chose_one = false; } if(self.chose_this and mouse_check_button(mb_left)) { x = mouse_x; y = mouse_y; } if(self.chose_this and mouse_check_button_released(mb_left)) { self.chose_this = false; global.chose_one = false; instance_destroy(); }
其中一些变量需要在其他obj中进行初始化,不然系统会无法读取。
嗯。。头有点晕,。。。还有一些下次再说吧。。。然后,我也是个gms新手,可能会有一些bug或者说的不清楚的地方,还请多指出错误,本文不算做教程,单纯就是我的一些想法和学习,能够给您带来一些参考当然更好啦。
最后附上我亲女儿
玩法可以借鉴下韩国独立游戏魔女之泉系列,也是魔法和合成为核心,GMS2可以去市场找ZUI的插件,集成了常用的控件,欢迎将文章分享到Gms2小组。
@Linpean:感谢你QAQ。。。差点出了大错子
宽度是width 高度是height,反了...到时候引用变量估计会懵