CocosCreator零基础制作游戏《极限跳跃》
制作游戏开始场景
我们刚刚分析了《极限跳跃》这款游戏,下面我们开始制作第一个游戏场景,也就是游戏的开始场景。
首先,打开CocosCreator,新建HelloWorld项目。选择项目路径,输入项目名称“jxty”,点击新建项目。
新建好项目,项目会自动打开。这里大家可以看下官方的文档,了解 下编辑器的功能和用法。
资源管理器里显示了项目资源文件夹(assets)中的所有资源。这里会以树状结构显示文件夹并自动同步在操作系统中对项目资源文件夹内容的修改。您可以将文件从项目外面直接拖拽进来,或使用菜单导入资源。
场景编辑器是用来展示和编辑场景中可视内容的工作区域。所见即所得的场景搭建工作都依靠场景编辑器中的显示来完成。
层级管理器用树状列表的形式展示场景中的所有节点和他们的层级关系,所有在场景编辑器中看到的内容都可以在层级管理器中找到对应的节点条目,在编辑场景时这两个面板的内容会同步显示,一般我们也会同时使用这两个面板来搭建场景。
属性检查器是我们查看并编辑当前选中节点和组件属性的工作区域,这个面板会以最适合的形式展示和编辑来自脚本定义的属性数据
工具栏上包括了场景编辑工具和预览游戏时的操作按钮,最右边显示了远程测试和调试时使用访问地址,以及连接中的设备数。
首先我们点击工具栏上的预览按钮来查看当前场景的显示。
简单的熟悉下编辑器怎么用的,下面开始我们的主题。。
一、创建场景
在资源管理器中,我们选中Scene文件夹,点击鼠标右键,选择[新建]=》[Scene],就会创建一个新的场景,New Scene。我们右键对它重命名为WelcomeScene。如图。
下面我们把游戏用到的资源全部放倒资源管理器中的Texture文件夹中。双击 WelcomeScene打开场景界面。新建的场景默认都是空的,这里我们调整场景大小为480x800像素大小的竖屏游戏。
二、把背景素材拖进层级管理器,注意节点的层级关系,然后调节属性即可。
使用相同的方法,把我们主场景的logo,还有底部的边栏也放进场景。
开始按钮我们使用UI节点来创建,右键点击Canvas,创建节点=》创建UI节点=》Button(按钮)。
创建好后,修改节点名称为kaishiyouxi,并删除子节点label。然后把对应状态资源拖进对应的状态即可。如图所示。
效果是不是还可以啊。是不是大家感觉很简单啊。。接着继续学习下一个场景。
制作游戏主场景
刚刚我们制作了游戏的开始场景,现在我们来制作游戏的主场景。还是同样的方法,新建一个名为MainScene的场景,双击打开,修改场景的大小为480x800。
1、首先贴入游戏背景,在此我们使用了2张背景图,只需要把背景拖进层级管理器2次,修改名称为bg1,bg2即可,背景2接着背景1点上方设置位置。
2、摆放玩家主角在屏幕合适位置
3、添加金币按钮在屏幕上方
4、右键Canvas画布=》创建节点=》创建渲染节点=》Label文字。修改节点名为score。String属性值为0。
5、左上角加上声音图标
到此我们主场景大概完成了,下面来预览下。
添加游戏主场景控制脚本
前面简单的实现了主界面的UI设置,现在我们开始制作游戏的控制脚本。
在资源管理器的Script文件夹中,点击右键新建javascript文件,命名为GAME。
双击打开GAME脚本,在properties: 中添加属性代码。
01 |
//GAME.js |
02 |
03 |
cc.Class({ |
04 |
extends: cc.Component,
|
05 |
properties: {
|
06 |
|
07 |
// player 节点,用于获取主角弹跳的高度,和控制主角行动开关
|
08 |
player: {
|
09 |
default: null ,
|
10 |
type: cc.Node
|
11 |
},
|
12 |
// bgsprite1 节点,用于背景移动
|
13 |
bgsprite1: {
|
14 |
default: null ,
|
15 |
type: cc.Node
|
16 |
},
|
17 |
// bgsprite2 节点,用于背景移动
|
18 |
bgsprite2: {
|
19 |
default: null ,
|
20 |
type: cc.Node
|
21 |
},
|
22 |
// score label 的引用
|
23 |
scoreDisplay: {
|
24 |
default: null ,
|
25 |
type: cc.Label
|
26 |
},
|
27 |
},
|
保存好后,我们双击MainScene打开场景,点击Canvas,在右侧的属性检查器最底部,点击[添加组件]=》[添加用户脚本组件]然后选择我们刚刚创建的脚本GAME.js。
添加好后就可以在属性检查器看到我们的属性组件来,然后我们把场景里的节点拖进对应的属性框即可实现节点绑定。不懂得可以多看看官方文档。
这样我门就可以在GAME脚本里来操作节点了。
二、创建HeroPlayer脚本用来操作玩家主角
01 |
//HeroPlayer.js |
02 |
03 |
cc.Class({ |
04 |
extends : cc.Component,
|
05 |
properties: {
|
06 |
//主角跳跃高度
|
07 |
jumpHeight: 0 ,
|
08 |
//主角跳跃持续时间
|
09 |
jumpTimes: 0 ,
|
10 |
//掉落速度
|
11 |
maxMoveSpeed: 0 ,
|
12 |
},
|
13 |
//跳跃
|
14 |
setJumpUpAction: function (){
|
15 |
// 跳跃上升
|
16 |
var jumpUp = cc.moveBy( this .jumpTimes, cc.p( 0 , this .jumpHeight));
|
17 |
//jumpUp.reverse();
|
18 |
return jumpUp;
|
19 |
},
|
20 |
//掉落
|
21 |
setJumpDownAction: function (){
|
22 |
//下落
|
23 |
var jumpDown = cc.moveBy( this .jumpTimes, cc.p( 0 , - this .maxMoveSpeed));
|
24 |
return jumpDown;
|
25 |
},
|
26 |
setJumpRunAction: function (){
|
27 |
// 初始化跳跃动作
|
28 |
this .jumpAction = this .setJumpUpAction();
|
29 |
//掉落动作
|
30 |
this .maxMoveSpeed = this .setJumpDownAction();
|
31 |
//包装动作
|
32 |
var seq = cc.sequence( this .jumpAction, this .maxMoveSpeed);
|
33 |
this .node.runAction(seq);
|
34 |
},
|
35 |
//玩家不操作时,角色进行下坠
|
36 |
heroDownMove: function (){
|
37 |
//下落
|
38 |
var heroDown = cc.moveBy( 0.8 , cc.p( 0 , - 5 ));
|
39 |
return heroDown;
|
40 |
},
|
41 |
// use this for initialization
|
42 |
onLoad: function () {
|
43 |
|
44 |
this .setJumpRunAction();
|
45 |
|
46 |
},
|
47 |
48 |
// called every frame, uncomment this function to activate update callback
|
49 |
update: function (dt) {
|
50 |
this .node.runAction( this .heroDownMove()); //精灵移动
|
51 |
}
|
52 |
|
53 |
|
54 |
}); |
角色有2种状态,一种是玩家点击屏幕会实现角色的跳跃,第二种就是角色会受到引力会自动下落。我们在update来实现自动下落。添加好方法后,我门在层级管理器中点击hero节点。然后在右侧属性检查器中绑定脚本。
我门可以在里面初始化值。跳跃高度值,跳跃持续时间,掉落速度等。
脚本里主要实现了跳跃动作,掉落动作等。
然后回到我们的游戏主脚本也就是GAME脚本。添加触摸事件监听,实现监听触摸来调用主角的跳跃动作。
首先在顶部添加脚本引用,然后创建事件监听的方法。
01 |
//GAME.js |
02 |
var HeroPlayer = require( "HeroPlayer" );
|
03 |
//----- |
04 |
//事件监听 |
05 |
setEventControl: function(){
|
06 |
var self = this ;
|
07 |
var hero = self.player.getComponent(HeroPlayer); //角色绑定控件
|
08 |
|
09 |
cc.eventManager.addListener({
|
10 |
event: cc.EventListener.TOUCH_ONE_BY_ONE,
|
11 |
swallowTouches: true ,
|
12 |
// 设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
|
13 |
onTouchBegan: function (touch, event) {
|
14 |
//实现 onTouchBegan 事件回调函数
|
15 |
var target = event.getCurrentTarget();
|
16 |
// 获取事件所绑定的 target
|
17 |
|
18 |
var locationInNode = target.convertToNodeSpace(touch.getLocation());
|
19 |
cc. log ( "当前点击坐标" +locationInNode);
|
20 |
|
21 |
hero.node.runAction(hero.setJumpUpAction()); //精灵移动
|
22 |
//cc.log("跳跃:--------");
|
23 |
|
24 |
|
25 |
|
26 |
return true ;
|
27 |
},
|
28 |
onTouchMoved: function (touch, event) { // 触摸移动时触发
|
29 |
|
30 |
},
|
31 |
onTouchEnded: function (touch, event) { // 点击事件结束处理
|
32 |
|
33 |
// cc.log("跳跃后角色坐标:" + self.player.getPosition() );
|
34 |
}
|
35 |
|
36 |
}, self.node)
|
37 |
},
|
然后在onload方法实现初始化调用。
1 |
onLoad: function () {
|
2 |
//触摸监听
|
3 |
this .setEventControl();
|
4 |
// 初始化计分
|
5 |
this .score = 0;
|
6 |
|
7 |
},
|
我们可以来运行下,看下效果。
制作游戏主场景背景滚动
刚刚我们实现了玩家的一些功能,测试了下发现我们的玩家跳跃几次后,就会超出屏幕,这样体验很差,那下面我们来实现场景背景的滚动作为参照物来实现玩家移动。也就是说玩家只需要小范围的移动就行了,剩下的交给背景的移动来给用户带来玩家在移动的错觉,游戏都是这样实现的。
新建脚本BgMove,并实现移动方法,参数为移动的距离。实现代码:
01 |
//BgMove.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
// foo: {
|
06 |
// default: null,
|
07 |
// url: cc.Texture2D, // optional, default is typeof default
|
08 |
// serializable: true, // optional, default is true
|
09 |
// visible: true, // optional, default is true
|
10 |
// displayName: 'Foo', // optional
|
11 |
// readonly: false, // optional, default is false
|
12 |
// },
|
13 |
// ...
|
14 |
},
|
15 |
//背景移动
|
16 |
setMoveAction: function(height){
|
17 |
// 移动距离
|
18 |
var moveHeight = height;
|
19 |
var moveAction = cc.moveBy( this .jumpTimes, cc.p(0, - moveHeight));
|
20 |
return moveAction;
|
21 |
},
|
22 |
// use this for initialization
|
23 |
onLoad: function () {
|
24 |
},
|
25 |
// called every frame, uncomment this function to activate update callback
|
26 |
// update: function (dt) {
|
27 |
// },
|
28 |
}); |
创建好脚本后,我们在场景中给节点bg1、bg2绑定此脚本。
绑定后,我们在打开GAME.js脚本,在顶部引用此脚本。
然后在事件监听方法,触摸结束的方法里添加背景移动的监听。
01 |
//事件监听
|
02 |
setEventControl: function(){
|
03 |
var self = this ;
|
04 |
var hero = self.player.getComponent(HeroPlayer); //角色绑定控件
|
05 |
var bg1 = self.bgsprite1.getComponent(MoveBg); //绑定背景控件
|
06 |
var bg2 = self.bgsprite2.getComponent(MoveBg); //绑定背景控件
|
07 |
//..... |
08 |
//...省略部分代码. |
09 |
//..... |
10 |
onTouchEnded: function (touch, event) { // 点击事件结束处理
|
11 |
if (self.player.getPositionY() > 0){
|
12 |
|
13 |
var height = self.player.getPositionY(); //背景需要移动的高度
|
14 |
self.player.setPositionY(height/2); //设置精灵的高度位置
|
15 |
|
16 |
bg1.node.runAction(bg1.setMoveAction(height)); //背景实现向下滚动
|
17 |
bg2.node.runAction(bg2.setMoveAction(height)); //背景实现向下滚动
|
18 |
|
19 |
}
|
20 |
//...省略部分代码.
|
这里分析下代码部分,首先我们创建场景时候,场景Canvas的锚点为(0.5,0.5),也就是屏幕的中心点坐标为0,0。其所有子节点的坐标都是相对于场景来布局,所以说我们的主角布局时候放在屏幕的中下方位置,一开始的Y坐标为负数。每次移动Y坐标会增加,当Y坐标增加超过中心点坐标我们需要进行背景移动,而背景移动的距离则是我们的主角Y坐标值减去中心点的Y坐标0,也就是主角Y坐标值本身。
所以每次触摸结束,我们对主角的Y坐标进行判断,如果大于0,说明背景需要移动,移动距离为主角Y坐标值,然后我门调用背景1和背景2的移动方法,参数为主角的Y坐标。
背景移动时候,我们同时需要修正主角的坐标,设置主角的坐标为超过中心点的一半,这样主角不论怎么移动都只能在屏幕内移动。
下面我门来运行预览,测试下。。
是不是可以实现背景滚动了,大家最后发现了一个问题,背景移动完毕了,没有背景会出现黑色的区域。。
下面我们要实现一个方法,来对背景进行计算。我们现在是两个背景进行拼接的。我们需要来判断哪个背景已经移除屏幕,移除屏幕后改变其位置,让它Y坐标变成正在移动的那个背景的上边,这样来实现无缝拼接。这样才是无限滚动的背景。
下面我们继续在GAME脚本添加新的方法来实现计算,下面贴代码。
01 |
//GAME.js |
02 |
//...省略代码 |
03 |
//如果背景1的坐标移出屏幕开始设置新的坐标
|
04 |
setBgMoveCreate: function(){
|
05 |
//如果背景1的坐标移出屏幕开始设置新的坐标
|
06 |
if ( this .bgsprite1.getPositionY() < -500 ){
|
07 |
this .bgsprite2.setPositionY( this .bgsprite1.getPositionY()+ this .bgsprite1.getContentSize().height);
|
08 |
}
|
09 |
//如果背景2的坐标移出屏幕开始设置新的坐标
|
10 |
if ( this .bgsprite2.getPositionY() < -500 ){
|
11 |
this .bgsprite1.setPositionY( this .bgsprite2.getPositionY()+ this .bgsprite2.getContentSize().height);
|
12 |
}
|
13 |
},
|
14 |
//实现update方法
|
15 |
update: function (dt) {
|
16 |
|
17 |
this .setBgMoveCreate(); //检测背景
|
18 |
|
19 |
},
|
我们在update里不停的检测背景移动事件来解决黑色问题。下面来再次测试下。
到此我们已经实现了 玩家角色的移动,背景的滚动了。。游戏完成了三分之一了。。感觉还可以吧。继续。。
制作游戏障碍物实现碰撞检测
前面我们实现了背景和主角的操作,下面我们开始添加游戏的障碍物以及碰撞检测的功能。
一、制作障碍物Prefab(预制)
Prefab(预制)是cocoscreator官方文档提出的,是为了解决需要重复使用的节点问题。
如何制作预制体prefab呢?具体可以参照官方文档,这里简单的说下,就是在场景中编辑好节点后,直接将节点从 层级管理器 拖到 资源管理器 中即可。
我们来看下极限跳跃的游戏截图分析下。。
游戏中障碍物我们分为2种,一个是向左移动的,一个是向右移动的,这里我就简单省事了,直接创建了2个预制体,每个预制体实现自己的脚本。可以集成在一起的。
我们先制作左边的障碍物,首先把障碍物素材拖进层级管理器取名zhangaiwu1。然后我们来实现并制作左边的脚本,创建脚本guawuleft。实现代码。
01 |
//guaiwuleft.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
|
06 |
times: 0, //控制时间
|
07 |
|
08 |
},
|
09 |
},
|
10 |
onLoad: function () {
|
11 |
|
12 |
this .moveRight();
|
13 |
},
|
14 |
//左右移动 |
15 |
moveRight: function(){
|
16 |
|
17 |
var seq = cc.repeatForever(
|
18 |
cc.sequence(
|
19 |
cc.moveBy( this .times, cc.p(240, 0)), cc.moveBy( this .times, cc.p(-240,0))
|
20 |
));
|
21 |
this .node.runAction(seq);
|
22 |
},
|
脚本写好了,我们对节点进行绑定。
绑定好后,我们把层级管理器中的节点zhangaiwu1拖进我们资源管理器的Texture文件夹中,成功后我们的层级管理器中的节点就会变成蓝色,同时我们会在资源管理器中得到一个预制体文件zhangaiwu1,我们这里改成zhangaiwuleft,方便和辨认。
预制体文件zhangaiwu1,我们这里改成zhangaiwuleft。然后删除层级管理器的zhangaiwu1节点。使用同样的方法,我们创建脚本zhangaiwuright,并制作预制体zhangaiwuright。
01 |
//guawuright.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
|
06 |
times: 0, //控制时间
|
07 |
|
08 |
},
|
09 |
},
|
10 |
onLoad: function () {
|
11 |
|
12 |
this .moveRight();
|
13 |
},
|
14 |
//左右移动
|
15 |
moveRight: function(){
|
16 |
|
17 |
|
18 |
var seq = cc.repeatForever(
|
19 |
cc.sequence(
|
20 |
cc.moveBy( this .times, cc.p(-240, 0)), cc.moveBy( this .times,cc.p(240,0))
|
21 |
));
|
22 |
this .node.runAction(seq);
|
23 |
},
|
这样我们就制作好了2个预制体,分别为zhangaiwuleft和 zhangaiwuright。可以在资源管理器中看到。
制作好了2个障碍物,我们开始在场景中添加我们的障碍物了。
分析下游戏我们可以发现障碍物是可以根据游戏背景移动的,所以我们要把障碍物添加到背景上。
我们开始制作背景bg1的障碍物,首先把zhangaiwuleft和zhangaiwuright两个预制体拖到层级管理器bg1节点,使其成为bg1的子节点。布局时候把zhangaiwuleft放到屏幕左边,zhangaiwuright放到右边,调整位置。同样的方法给bg2添加障碍物。。如图:
通过我们给不同高度的障碍物设置不同的移动时间,我们的游戏看起来更好玩,来运行测试下效果。
好了。我们的游戏看起来还不错吧,下面我们来做碰撞检测,也就是说如果玩家和障碍物碰到了,那么我们的角色就会死掉,游戏就会结束。结束场景等会我们在做,现在我们先做碰撞检测,如果碰到障碍物我们停止触摸来达到玩家不可操作的目的。
打开guaiwuleft脚本,来给左边的障碍物添加碰撞检测的事件。
01 |
//guaiwuleft.js |
02 |
var hero2 = require( "HeroPlayer" ); //引用玩家的操作脚本
|
03 |
//....省略.. |
04 |
//当前节点世界坐标系下的范围包围盒 |
05 |
noteBox: function(){
|
06 |
|
07 |
return this .node.getBoundingBoxToWorld();
|
08 |
|
09 |
},
|
10 |
|
11 |
// called every frame, uncomment this function to activate update callback
|
12 |
update: function (dt) {
|
13 |
|
14 |
var _label = cc.find( "Canvas/hero" ).getComponent(hero2);
|
15 |
|
16 |
//障碍物碰撞框
|
17 |
if (cc.rectIntersectsRect(_label.node.getBoundingBoxToWorld(), this .noteBox())){
|
18 |
|
19 |
cc.eventManager.removeAllListeners(); //移除所有事件监听
|
20 |
|
21 |
}
|
22 |
|
23 |
},
|
同样的方法,我们在guaiwuright中添加碰撞事件。天下代码一大抄,直接抄过去就行了。
我们在此运行检测下。。
我们的角色被障碍物碰到,就死掉了,然后就会屏蔽游戏的触摸事件,玩家角色开始掉落。当角色掉落到屏幕底部时候游戏结束。会切换到结束场景。这里大家看到角色掉没了,不要在意这些细节。。我们接下来开始制作结束场景。
制作游戏结束场景并实现场景切换
前面我们实现了游戏的碰撞检测,碰到障碍物我们的角色就会死掉并开始掉落,角色掉落到屏幕底部时候游戏结束,并跳到结束场景。
我们在资源管理器新建GameOver场景。双击打开场景,调整大小为480x800,添加界面需要的节点。如图。
这样我们的结束场景就制作好了。可以预览下。
制作好了,结束场景我们就需要把我们游戏的三个场景关联起来了。
首先我们双击打开我们的第一个场景WelcomeScene。然后在资源管理器创建playGo.js脚本。代码如下:
01 |
//playGo.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
// foo: {
|
06 |
// default: null,
|
07 |
// url: cc.Texture2D, // optional, default is typeof default
|
08 |
// serializable: true, // optional, default is true
|
09 |
// visible: true, // optional, default is true
|
10 |
// displayName: 'Foo', // optional
|
11 |
// readonly: false, // optional, default is false
|
12 |
// },
|
13 |
// ...
|
14 |
},
|
15 |
// use this for initialization
|
16 |
onLoad: function () {
|
17 |
},
|
18 |
//切换场景
|
19 |
toScene: function(){
|
20 |
cc.director.loadScene( "MainScene" )
|
21 |
}
|
22 |
// called every frame, uncomment this function to activate update callback
|
23 |
// update: function (dt) {
|
24 |
// },
|
25 |
}); |
这个脚本就实现一个功能,就是切换场景到MainScene场景,也就是第二个场景我们游戏的主场景。
下面我们为开始按钮绑定脚本事件。
这样我们的切换场景功能就实现了,同样的方法我们给GameOver场景中的重新开始按钮绑定脚本事件。
给退出游戏按钮添加事件脚本,创建脚本ExitScene。代码如下:
01 |
//ExitScene.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
// foo: {
|
06 |
// default: null,
|
07 |
// url: cc.Texture2D, // optional, default is typeof default
|
08 |
// serializable: true, // optional, default is true
|
09 |
// visible: true, // optional, default is true
|
10 |
// displayName: 'Foo', // optional
|
11 |
// readonly: false, // optional, default is false
|
12 |
// },
|
13 |
// ...
|
14 |
},
|
15 |
// use this for initialization
|
16 |
onLoad: function () {
|
17 |
},
|
18 |
|
19 |
//退出游戏
|
20 |
ExitScene: function(){
|
21 |
cc.director.end();
|
22 |
},
|
23 |
// called every frame, uncomment this function to activate update callback
|
24 |
// update: function (dt) {
|
25 |
// },
|
26 |
}); |
使用同样的方法,给退出游戏按钮绑定事件。
还剩下一个游戏结束的切换场景事件。打开GAME脚本。添加gameover方法,并在update添加判断和处理。
01 |
//GAME.js |
02 |
//....省略.. |
03 |
//gameover方法 然后在update实现gameover判断
|
04 |
gameOver: function () {
|
05 |
|
06 |
cc.eventManager.removeAllListeners(); //移除所有事件监听
|
07 |
this .player.stopAllActions(); //停止 player 节点的跳跃动作
|
08 |
|
09 |
cc.director.loadScene( "GameOver" ); //切换场景到结束场景
|
10 |
},
|
11 |
//加载时执行
|
12 |
onLoad: function () {
|
13 |
//触摸监听
|
14 |
this .setEventControl();
|
15 |
// 初始化计分
|
16 |
this .score = 0;
|
17 |
//添加判断
|
18 |
this .isMoving = true ;
|
19 |
|
20 |
},
|
21 |
//刷新update
|
22 |
update: function (dt) {
|
23 |
|
24 |
this .setBgMoveCreate(); //检测背景
|
25 |
|
26 |
//gameOver判断 玩家坠落到屏幕底部游戏结束
|
27 |
if ( this .player.getPositionY() <= -cc.view.getVisibleSize().height/2){
|
28 |
this .unscheduleAllCallbacks();
|
29 |
|
30 |
if ( this .isMoving)
|
31 |
{
|
32 |
this .gameOver();
|
33 |
this .isMoving = false ;
|
34 |
}
|
35 |
|
36 |
}
|
37 |
|
38 |
},
|
39 |
//......省略代码.... |
下面我们来测试下整个流程环节。双击WelcomeScene场景从第一个场景开始预览。
到此我们整个游戏流程以及完了,接下来完善积分系统,还有声音系统整个游戏就可以上线了。下面我们继续来做积分系统。。
添加游戏积分系统
前面我们实现了整个游戏的流程,下面我们来完善游戏的积分系统。。先来分析下游戏的积分,第一次展示积分的地方就是我们的游戏主场景MainScene,玩家通过一些机制来获取积分,实现积分的更新,当玩家游戏结束后展示玩家所获的的当前积分。
我们一开始制作游戏场景的时候就制作了一个积分节点score,其string属性值为0。打开GAME.js脚本可以发现,一开始的时候我们onLoad方法就初始化了积分。
接着我们在GAME.js脚本里新添加一个函数来实现积分的更新。代码如下:
01 |
//GAME.js |
02 |
//....省略... |
03 |
04 |
//积分更新
|
05 |
gainScore: function () {
|
06 |
this .score += 1;
|
07 |
// 更新 scoreDisplay Label 的文字
|
08 |
this .scoreDisplay.string = this .score.toString();
|
09 |
|
10 |
cc.sys.localStorage.setItem( "ScoreDis" , this .scoreDisplay.string); //本地存储
|
11 |
|
12 |
},
|
13 |
|
14 |
//.....省略... |
这段代码的意思是实现积分+1,增长一个积分。并把积分存储到本地,注意本地存储代码。。。那么什么时候才增长积分呢??
在触摸屏幕接触的时候,如果背景滚动我们就增加一个积分。添加代码位置如下图:
这样每次玩家移动带动背景滚动的时候,积分就会更新。积分更新到时候会存储到本地,这样我们游戏结束的时候就可以正确的显示出来。
新建GameOverScore.js脚本,代码如下:
01 |
//GameOverScore.js |
02 |
cc.Class({ |
03 |
extends: cc.Component,
|
04 |
properties: {
|
05 |
//积分更新
|
06 |
Scores: {
|
07 |
default : null,
|
08 |
type: cc.Label
|
09 |
},
|
10 |
},
|
11 |
//积分更新
|
12 |
disScore: function () {
|
13 |
this .score = cc.sys.localStorage.getItem( "ScoreDis" ); //读取本地存储的积分
|
14 |
// 更新 scoreDisplay Label 的文字
|
15 |
this .Scores.string = "Score: " + this .score.toString(); //显示
|
16 |
},
|
17 |
|
18 |
// use this for initialization
|
19 |
onLoad: function () {
|
20 |
this .disScore(); //首次加载时候调用
|
21 |
},
|
22 |
|
23 |
// called every frame, uncomment this function to activate update callback
|
24 |
// update: function (dt) {
|
25 |
|
26 |
|
27 |
// },
|
28 |
}); |
这段代码的意识是加载的时候,onLoad函数调用积分更新的方法,实现从本地读取游戏场景中存储的积分。
双击打开GameOver场景,如图:
为GameOver场景Canvas绑定刚刚新建的GameOverScore.js脚本。并把score组件拖进scores进行绑定。
这样游戏结束的时候,就会更新score节点组件的显示内容。下面我们来测试下。双击打开主场景,从游戏场景开始测试积分的更新,以及游戏结束的积分显示。
是不是很好玩啊,哈哈。加个积分排行榜更好啊,以后 慢慢扩展来。。。
到此我们整个游戏已经算完成了,当然一个游戏不能没有声音和音效,下面我们来添加声音系统功能。。。
为游戏添加声音音效功能
游戏的声音很重要,我们在这个游戏中需要加2个音效,一个背景音乐。。。第一个音效在玩家与障碍物碰撞的地方加碰撞音效,第二个在玩家主角坠落到屏幕底部的时候加游戏结束的音效。然后游戏开始的时候加载背景音乐。
我们一开始在MainScene场景中的声音图标节点就是我们用来控制声音的开关。。
首先修改guawileft.js脚本,添加音效资源,在onload设置声音大小。代码:
01 |
//guanwileft.js |
02 |
03 |
properties: {
|
04 |
|
05 |
times: 0,
|
06 |
// 碰撞音效资源
|
07 |
pengAudio: {
|
08 |
default : null,
|
09 |
url: cc.AudioClip
|
10 |
},
|
11 |
},
|
12 |
// use this for initialization
|
13 |
onLoad: function () {
|
14 |
|
15 |
this .moveRight();
|
16 |
cc.audioEngine.setEffectsVolume ( 0.2 ); //设置音效声音大小
|
17 |
|
18 |
|
19 |
},
|
同理在guaiwuright.js脚本也是这样添加。。
为障碍物的2个脚本添加好代码后,我们需要修改我们的两个障碍物预制体。绑定音效资源,这里以zhangaiwuleft预制体为例。双击zhangaiwuleft预制体,添加声音资源绑定。如图:
zhangaiwuright预制体同理也是这样添加声音。
碰撞音效加载好后,我们为游戏结束加个音效。打开GAME.js脚本。在 properties中添加属性。代码如下:
01 |
// 背景音乐资源
|
02 |
bgmusic: {
|
03 |
default : null,
|
04 |
type: cc.Node
|
05 |
},
|
06 |
// 游戏音乐资源
|
07 |
gameAudio: {
|
08 |
default : null,
|
09 |
url: cc.AudioClip
|
10 |
},
|
11 |
// 游戏结束音乐资源
|
12 |
gameOverAudio: {
|
13 |
default : null,
|
14 |
url: cc.AudioClip
|
15 |
},
|
添加好代码后,我们双击打开MainScene场景开始为属性绑定资源和节点。。如图:
可以跑起来测试下我们的声音有没有了。。这就完了吗?当然不是,我们的声音图标还没有用到啊!!
下面为我们的声音图标节点加一个脚本,新建脚本AudioScript.js。代码如下:
01 |
//AudioScript.js |
02 |
03 |
cc.Class({ |
04 |
extends: cc.Component,
|
05 |
properties: {
|
06 |
//是否开启音乐 默认开启
|
07 |
isOpen: true ,
|
08 |
// 游戏音乐资源
|
09 |
gameAudio: {
|
10 |
default : null,
|
11 |
url: cc.AudioClip
|
12 |
},
|
13 |
|
14 |
},
|
15 |
// use this for initialization
|
16 |
onLoad: function () {
|
17 |
this .isOpen = true ; //开启音乐
|
18 |
cc.audioEngine.playMusic ( this .gameAudio, true );
|
19 |
|
20 |
},
|
21 |
//检查音乐开启状态
|
22 |
checkMusic:function(){
|
23 |
|
24 |
return isOpen;
|
25 |
},
|
26 |
//获取点击坐标
|
27 |
setCp:function(pos){
|
28 |
|
29 |
var rec = cc.rectContainsPoint( this .node.getBoundingBoxToWorld(),pos) ;
|
30 |
|
31 |
if (rec){
|
32 |
//检查音乐开启状态
|
33 |
//如果音乐开启了则关闭音乐和音效
|
34 |
if ( this .isOpen){
|
35 |
//if (cc.audioEngine.isMusicPlaying()) {
|
36 |
cc.audioEngine.pauseMusic(); //暂停正在播放音乐
|
37 |
cc. log ( "暂停正在播放音乐" );
|
38 |
//this.node.addChild("Texture/menu_music_off.png");
|
39 |
this .isOpen = false ;
|
40 |
}
|
41 |
else {
|
42 |
// cc.log("music is not playing");
|
43 |
cc.audioEngine.resumeMusic (); //恢复背景音乐
|
44 |
cc. log ( "恢复背景音乐" );
|
45 |
this .isOpen = true ;
|
46 |
}
|
47 |
|
48 |
}
|
49 |
},
|
50 |
|
51 |
// called every frame, uncomment this function to activate update callback
|
52 |
// update: function (dt) {
|
53 |
|
54 |
// },
|
55 |
}); |
代码里实现了一个音乐播放的状态,用来给我们判断是否播放了。播放了图标显示声音图标,没有播放显示静音图标。
1 |
var rec = cc.rectContainsPoint( this .node.getBoundingBoxToWorld(),pos) ;
|
此处用来判断声音图标的包围盒和点击坐标的比较,如果为true则表示声音图标被点击到了,如果声音图标被点击则判断当前声音播放状态,并改变状态。声音图标节点显示如图:
声音节点绑定好脚本后,我们继续修改GAME.js脚本中的代码,为AudioScript.js中的方法setCp:function(pos)传参数。
首先在顶部添加引用代码,然后在点击事件添加点击的检测方法,然后update实现更新状态。代码如图:
这里我就不贴代码了,大家手打下。。。到此我们的声音系统也添加完毕了。。。对了,还少一点,声音状态切换的时候声音图标也要改变啊。。。这里大家自己解决。。
[2016.9.6日更新说明:前一段时间大家一直要资源和代码,由于我这段时间都没开电脑,所以一直没放在网盘,今天整理了下,代码和资源一起打包了,下载地址 : 链接: https://pan.baidu.com/s/1bNi8Tw 密码: gcdr]
=================
通过我们大半天的学习,是不是一个完整的小游戏就做好了啊。。做好的小游戏我们最后一步就是分享出去,做游戏不就是装个逼给别人玩吗。。
下面我们来发布我们的游戏,这里我以mac为例。。点击[项目]菜单里的[构建发布]即可打开发布对话框。。
一、游戏名称
我们发布游戏的名称,也就是我们游戏的名字。
二、发布平台
目前可以选择的原生平台包括 Cocos Runtime, Android, iOS, Mac, Windows 五个,其中发布到 Mac 和 Windows 的选项只能在相应的操作系统中才会出现。
三、发布路径
发布路径默认就是我们项目目录下的build目录。
四、初始场景
初始场景这地方一定要注意,一定要先择我们游戏的第一个场景,选错了就坑了。
五、设备方向。
设备方向大家根据自己的项目就行设置,
设置好上面的主要点后,就可以点击[构建]然后[编译]和[运行]了。。
到此为止,我们的整个游戏都完成了。。零基础一天都可以做一个游戏感觉是不是越来越有信心了啊。。
the end.. by:闭眼就天黑
本文转载自注明:http://www.byjth.com/CocosCreator/75.html | 闭眼就天黑专栏_个人博客_技术源于分享