关注公众号“码农帮派”,查看更多系列技术文章:
本节源码下载:
链接: http://pan.baidu.com/s/1jIPYHOM 密码: 5zae
触控科技开发的CocosCreator开发工具是的Cocos2d开发和Unity开发更加相似,使用CocosCreator开发2d游戏变得更加便捷快速,之后半年利用做毕业设计的闲暇之余学习使用Cocos Creator开发2d的游戏,主要是看触控科技官方提供的ExampleProject的源码来大致的模仿实现:
Cocos Creator官方文档: http://www.cocos.com/
Cocos Creator开发文档: http://www.cocos.com/docs/creator/
Cocos Creator的ExampleProject项目下载文档:https://github.com/cocos-creator/example-cases (也可以直接在Cocos Creator新建项目那选择 新建范例工程)
Cocos2d-JS开发的第一弹中,首先开发一个下面的界面:
[说明]
点击Menu的按键(绿色按键)会有事件相应,点击List的某一Item会有相应的事件相应。
项目的结构:
(一)绘制背景Sprite([层级管理器]中的background组件)
background为一个Sprite,在[层级管理器]中 创建Sprite精灵,选中该Sprite精灵之后,在[属性检查器]中修改Sprite的属性:
(1)将选中的背景图片(e.g. singleColor.png)从[资源管理器]中通过拖拽的方式添加到Sprite的[Sprite Frame]属性框中;
(2)在[添加组件]处为Sprite添加Widget属性(添加组件-添加UI组件-Widget):
[说明]Widget的作用是为了使得组件更好的适配父节点的大小,其中的Left,Top,Right和Bottom分别为该组件相对于父节点左边缘,上边缘,右边缘和下边缘的距离,可以使用px直接指定,也可以使用10%这样来制定是父节点长/宽度的百分比,这四项中打勾的表示该项起作用,下边的Horizontal Center和Vertical Center将会相对于父节点的横向置中,和垂直置中。
经过上面的步骤,就完成了背景Sprite的绘制。
(二)绘制选项节点([层级管理器]中的Menu组件)
(1)在Canvas节点中建立Menu组件(为Sprite组件,并设置Widget属性,让其铺满父节点Canvas),并在[属性管理器]中Sprite的Sprite Frame属性框中设置为None:
这样Menu铺满父节点Canvas,但不会覆盖父节点的背景。
(2)在Menu节点中新建两个Button节点([层级管理器]中的btnBack和btnInfo),Button组件默认带一个Label子节点,选中Label组件,可以在[属性检查器]中Label-String属性处修改 按键上文字内容:
选中Button组件之后,在[属性检查器]中可以看到一个Button组件默认有Sprite属性和Button属性,那么可以通过从[资源管理器]中拖拽图片的方式,添加到Button组件的Sprite属性的Sprite Frame属性框中,从而改变Button组件的背景图片:
拖拽图片到Button的Sprite属性的Sprite Frame框后,可以看到Button的背景图片改变了,但是Button的边框出现模糊,这是因为Button的尺寸大于图片的尺寸,从而出现了模糊现象,此时我们展开[资源管理器]中Texture文件夹中对应的图片文件,双击可以打开[Editor Window]对话框处理图片:
拖拽[Editor Window]中图片上的四条绿色的线,来设置图片的属性,{完成这一修改之后,一定要点击[Editor Window右上角绿色的对号进行属性保存]},至于为什么要这么修改,其实就和Android开发中的9patch图片的原理一直,当组件的尺寸大于图片尺寸的时候,要对图片进行拉伸,这四条线表示只拉伸四条线围成矩形框内的像素点,矩形框外部的像素点不会被拉伸,只会保持原来图片的像素。
完成上面的操作之后,还需要将Button组件的Sprite属性的Type属性选项修改为SLICED:
这样,我们的按键的效果看起来就舒服多了:
(3)完成上述操作之后,分别为两个Button节点在[属性检查器]中添加Widget属性(添加组件-添加UI组件-Widget),将两个Button组件放置在界面的左上角 和 右上角,以[查看说明]Button为例(在界面的左上角):
(4)为Button添加点击效果
完成上面所有的操作之后,运行,在网页上点击发现按键并没有点击效果,如何做到点击的时候会有点击效果,选中Button组件,在[属性检查器]中Button属性下面可以看到:
上图一中,Button属性的Transition属性选择框,有None,SPRITE,COLOR,SCALE四个选项,可以设置Button被点击的效果,None表示没有点击效果(默认),SPRITE表示点击效果使用Sprite精灵来展示,COLOR表示点击效果使用颜色变化来展示,SCALE表示Button被点击的时候改变其大小,下面以COLOR为例:
上图中,Normal表示常态Button的颜色,Pressed表示Button被按下的颜色,Hover表示鼠标移动到该Button上之后Button的显示状态,按需求点击颜色选择条进行颜色设定。
(5)为Button添加点击相应事件_需要js脚本
首先在[资源管理器]中assets/Script文件下新建一个名为Menu.js的脚本文件,新建完成之后,打开脚本文件会发现,文件根是一个cc.Class,这是cocosJS中的类的声明方式,内部有:
extends: cc.Component,
properties: {
}
其中,extends表示该类即成自cc.Component组件,properties中声明该类的本地变量,以后可以通过this.propertyName来进行引用。除此之外,一个重要的函数为onLoad方法,当该类被加载的时候,就会调用此方法,可以在其中做一些初始化的操作,我们在Menu.js中添加如下的代码:
cc.Class({
extends: cc.Component,
properties: {
btnInfo: {
default: null,
type: cc.Button
},
btnBack: {
default: null,
type: cc.Button
}
},
backToList: function(){
cc.log("backToList Button Clicked!")
},
showReadme: function(){
cc.log("showReadme Button Clicked!")
}
});
添加完上面的代码之后,我们将该脚本文件添加给Menu节点:
[方法一]:在[层次管理器]中点选中Menu节点,此时[属性检查器]中显示Menu节点的属性,从[资源管理器]中拖拽Menu.js脚本到[属性管理器]进行脚本添加;
[方法二]:在[层次管理器]中点选中Menu节点,此时[属性检查器]中显示Menu节点的属性,点击 添加组件-添加用户脚本组件,便可以看到 已经在[资源管理器]中添加的所有的脚本文件,点选需要添加的Menu.js文件:
从[层级管理器]中拖拽对应的组件到上图中的 Btn Info属性框和Btn Back属性框中进行数据添加:
接下来,在[层级管理器]中点选中btnBack组件,在[属性检查器]中修改按键的属性,在Button属性栏中,首先将Click Events属性框修改为1,表示为Button绑定一个Click事件,此时就会出现 [0]事件编号,将[层级管理器]中的Menu节点拖拽添加到第一个属性框中(cc.Node),点击后面第一个下拉菜单,可以看到Menu节点上绑定的所有脚本,选中Menu.js的脚本,再继续点选后面的下拉框,可以看到Mneu.js脚本文件中已经添加的函数,选择事先写好的Btn Back的Click相应函数,这样就为[层级管理器]中的btnBack按键绑定了Click事件:
(三)绘制MenuList节点
首先给Canvas节点添加一个ScrollView组件,可以看到,ScrollView包含两部分,一个scrollbar,另一个是content,即为List内容显示部分,为了让ScrollView组件能够更好的适配父节点的大小,通过为ScrollView,子节点view以及content设置Widget属性控制其大小,让组件铺满整个父节点:
需要说明,view节点是ScrollView显示区域,一般的要和ScrollView的大小一致,或比ScrollView稍小,以便能够看到List中的全部内容,view的字节点content是ScrollView将要显示的全部内容,其大小可以大于ScrollView和view,也可以小于,大于父节点大小之后,便可以通过拖拽来查看view之外的部分,所以一般不勾选content的Widget属性中Bottom属性项。
(1)首先绘制ListItem,并制作Item-Prefabs
在[场景绘制器]中绘制MenuList中单个Item,在content添加一个Sprite字节点,通过拖拽修改Sprite的Sprite Frame中的背景图片,为了让图片不出现失真的情况,需要对图片进行Editor:
为了让Item可以显示 文字信息,可以为其 添加一个Label字节点,并在[属性检查器]中修改 Label的Color,修改文字颜色,为Label添加Widget属性,让Label适配父节点,需要注意的是,要修改Label的的Overflow属性为CLAMP,Label才能够铺满父节点:
完成上面的步骤之后,在[层级管理器]中可以看到Item的结构:
将上面的mainMenuItem拖拽到[资源管理器]中assets/Prefabs文件夹下,同时删除[层级管理器]中mainMenuItem节点:
这样就完成了Prefab的制作,下面再为Prefab添加一个控制脚本,为不同index的Item设置不同的内容(mainMenuItem.js):
cc.Class({
extends: cc.Component,
properties: {
label: {
default: null,
type: cc.Label
},
index: -1
},
updateItem(index, name){
this.index = index;
this.label.string = name
},
itemClickedEvent: function(){
cc.log(this.index)
}
});
上面的代码中,为每一个Prefab设置了两个property属性,一个是显示内容的Label组件,另外一个是该Prefab-Item的index,实例化Prefab-Item之后,调用对象的updateItem方法来显示内容,并定义了Item被点击的响应事件,在[资源管理器]中双击选中assets/Prefabs/mainMenuItem,并将上面的脚本文件mainMenuItem.js拖拽添加到mainMenuItem-Prefab的属性管理器中,并将mainMainItem的字节点labelContent拖拽到脚本文件的Label属性框中:
为了让每一个Item有点击事件,还需要给每个Item-Sprite添加一个Button属性,并修改Click Events属性设置,在[资源管理器]中双击选中assets/Prefabs/mainMenuItem,在[资源管理器]中通过 添加组件-添加UI组件-Button 来添加:
(2)为ScrollView动态的添加Item
ScrollView中显示的Item都是添加到其content节点中的,所以需要编写js脚本文件,进行动态添加(SceneList.js):
cc.Class({
extends: cc.Component,
properties: {
itemPrefab: {
default: null,
type: cc.Prefab
},
initItemCount: 0,
scrollView: {
default: null,
type: cc.ScrollView
},
bufferZone: 0,
itemContents: []
},
init(menu) {
this.menu = menu;
this.itemContents = this.getMainMenuContent();
this.initList();
},
initList(){
var count = this.itemContents.length
for (let i = 0; i < count; i++){
// 通过cc.instantiate方法生成了一个Prefab节点
let item = cc.instantiate(this.itemPrefab);
// 获得节点上的名称为mainMenuItem的属性,这里就是该Prefab对象的脚本熟悉
// 因为脚本文件中包含了 Prefab 内容显示的组件,所以可以通过该脚本属性完成很多事情
var itemComp = item.getComponent('mainMenuItem')
// 直接调用脚本属性的动态方法,来操作Prefab对象
itemComp.updateItem(i, this.itemContents[i])
// 下面是通过脚本属性获得 显示内容的组件,
// 从而改变组件显示的内容
// var label = itemComp.label
// label.string = this.itemContents[i]
this.scrollView.content.addChild(item)
}
},
// 自定义的脚本文件,获取 场景Scene的列表,
// cc.game.__sceneInfos可以获取得到
getMainMenuContent(){
var array = ["第一个场景", "第二个场景", "第三个场景", "第四个场景", "第五个场景", "第六个场景"]
return array
},
// called every frame, uncomment this function to activate update callback
// update: function (dt) {
// },
});
上面的代码中,我们可以看到,当要显示ScrollView中内容的时候,需要实例化该cc.Component组件,并调用自定义的init方法来初始化列表,在initList方法中,使用了cc.instantiate方法实例话一个item-Prefab对象,并通过addChild方法将这个实例化之后的item添加给ScrollView的content节点中。
接下来,将上面的脚本SceneList.js添加到ScrollView的content上,并从[层级管理器]中通过拖拽添加相应的属性项:
(3)在Menu中初始化List数据:
我们想在Menu被初始化的过程中同时初始化MenuList数据,就需要在Menu的onLoad函数中实例化SceneList,并调用对象的自定义方法init来初始化List,修改Menu.js脚本文件:
Menu.js 代码:
cc.Class({
extends: cc.Component,
properties: {
btnInfo: {
default: null,
type: cc.Button
},
btnBack: {
default: null,
type: cc.Button
},
menuList: {
default: null,
type: cc.ScrollView
}
},
// use this for initialization
onLoad: function () {
// 通常只会加载一个场景,当场景发生切换的时候,默认会将原来场景中所有的节点和实例销毁,
// 如果我们需要某个组建进行其他场景的加载,或者在场景之间加载数据,那么就需要将该组件
// 标记为[常驻节点],使其不被自动销毁,就需要调用cc.game.addPersistRootNode(node)
// this.node 会获得组建所在的节点对象
cc.game.addPersistRootNode(this.node);
this.node.zIndex = 999
if (this.menuList && this.menuList.content){
this.sceneList = this.menuList.content.getComponent("SceneList");
this.sceneList.init(this);
cc.log("加载完成....")
}
},
backToList: function(){
cc.log("backToList Button Clicked!")
},
showReadme: function(){
cc.log("showReadme Button Clicked!")
}
});
并将ScrollView拖拽到脚本文件的属性框中:
运行项目,可以看到的效果:
发现所有的List-Item全部都叠加到了一起,因为Item都是添加到ScrollView的content子节点中的,所以需要为content子节点设置Layout属性,在[层级管理器]中选中content节点,[属性管理器]中通过 添加组件-添加UI组件-Layout 来添加布局属性,并进行修改:
添加Layout属性之后的效果: