阅读896 返回首页    go 阿里云 go 技术社区[云栖]


CocosCreator零基础制作游戏《极限跳跃》

CocosCreator零基础制作游戏《极限跳跃》


制作游戏开始场景


我们刚刚分析了《极限跳跃》这款游戏,下面我们开始制作第一个游戏场景,也就是游戏的开始场景。

首先,打开CocosCreator,新建HelloWorld项目。选择项目路径,输入项目名称“jxty”,点击新建项目。 

QQ20160529-1@2x.png 

新建好项目,项目会自动打开。这里大家可以看下官方的文档,了解 下编辑器的功能和用法。

QQ20160529-3@2x.png

资源管理器里显示了项目资源文件夹(assets)中的所有资源。这里会以树状结构显示文件夹并自动同步在操作系统中对项目资源文件夹内容的修改。您可以将文件从项目外面直接拖拽进来,或使用菜单导入资源。


场景编辑器是用来展示和编辑场景中可视内容的工作区域。所见即所得的场景搭建工作都依靠场景编辑器中的显示来完成。


层级管理器用树状列表的形式展示场景中的所有节点和他们的层级关系,所有在场景编辑器中看到的内容都可以在层级管理器中找到对应的节点条目,在编辑场景时这两个面板的内容会同步显示,一般我们也会同时使用这两个面板来搭建场景。


属性检查器是我们查看并编辑当前选中节点和组件属性的工作区域,这个面板会以最适合的形式展示和编辑来自脚本定义的属性数据


工具栏上包括了场景编辑工具和预览游戏时的操作按钮,最右边显示了远程测试和调试时使用访问地址,以及连接中的设备数。


 

首先我们点击工具栏上的预览按钮来查看当前场景的显示。 

QQ20160529-4@2x.png

QQ20160529-5@2x.png

简单的熟悉下编辑器怎么用的,下面开始我们的主题。。


一、创建场景 


在资源管理器中,我们选中Scene文件夹,点击鼠标右键,选择[新建]=》[Scene],就会创建一个新的场景,New Scene。我们右键对它重命名为WelcomeScene。如图。

QQ20160529-6@2x.png


下面我们把游戏用到的资源全部放倒资源管理器中的Texture文件夹中。双击 WelcomeScene打开场景界面。新建的场景默认都是空的,这里我们调整场景大小为480x800像素大小的竖屏游戏。

QQ20160529-7@2x.png


二、把背景素材拖进层级管理器,注意节点的层级关系,然后调节属性即可。

QQ20160529-8@2x.png


使用相同的方法,把我们主场景的logo,还有底部的边栏也放进场景。

开始按钮我们使用UI节点来创建,右键点击Canvas,创建节点=》创建UI节点=》Button(按钮)。

创建好后,修改节点名称为kaishiyouxi,并删除子节点label。然后把对应状态资源拖进对应的状态即可。如图所示。

QQ20160529-23@2x.png

效果是不是还可以啊。是不是大家感觉很简单啊。。接着继续学习下一个场景。


制作游戏主场景


刚刚我们制作了游戏的开始场景,现在我们来制作游戏的主场景。还是同样的方法,新建一个名为MainScene的场景,双击打开,修改场景的大小为480x800。


1、首先贴入游戏背景,在此我们使用了2张背景图,只需要把背景拖进层级管理器2次,修改名称为bg1,bg2即可,背景2接着背景1点上方设置位置。

2、摆放玩家主角在屏幕合适位置

3、添加金币按钮在屏幕上方

4、右键Canvas画布=》创建节点=》创建渲染节点=》Label文字。修改节点名为score。String属性值为0。QQ20160529-10@2x.png

5、左上角加上声音图标

到此我们主场景大概完成了,下面来预览下。

QQ20160529-11@2x.png


添加游戏主场景控制脚本


前面简单的实现了主界面的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。

添加好后就可以在属性检查器看到我们的属性组件来,然后我们把场景里的节点拖进对应的属性框即可实现节点绑定。不懂得可以多看看官方文档。

QQ20160529-12@2x.png

这样我门就可以在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(0this.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节点。然后在右侧属性检查器中绑定脚本。

QQ20160529-13@2x.png

我门可以在里面初始化值。跳跃高度值,跳跃持续时间,掉落速度等。

脚本里主要实现了跳跃动作,掉落动作等。

然后回到我们的游戏主脚本也就是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     },

我们可以来运行下,看下效果。

QQ20160529-14@2x.png

制作游戏主场景背景滚动


刚刚我们实现了玩家的一些功能,测试了下发现我们的玩家跳跃几次后,就会超出屏幕,这样体验很差,那下面我们来实现场景背景的滚动作为参照物来实现玩家移动。也就是说玩家只需要小范围的移动就行了,剩下的交给背景的移动来给用户带来玩家在移动的错觉,游戏都是这样实现的。


新建脚本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绑定此脚本。

QQ20160529-15@2x.png


绑定后,我们在打开GAME.js脚本,在顶部引用此脚本。

QQ20160529-16@2x.png

然后在事件监听方法,触摸结束的方法里添加背景移动的监听。

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坐标。

背景移动时候,我们同时需要修正主角的坐标,设置主角的坐标为超过中心点的一半,这样主角不论怎么移动都只能在屏幕内移动。

下面我门来运行预览,测试下。。

beijingyidong.gif

是不是可以实现背景滚动了,大家最后发现了一个问题,背景移动完毕了,没有背景会出现黑色的区域。。

下面我们要实现一个方法,来对背景进行计算。我们现在是两个背景进行拼接的。我们需要来判断哪个背景已经移除屏幕,移除屏幕后改变其位置,让它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里不停的检测背景移动事件来解决黑色问题。下面来再次测试下。

beijingyidong22.gif


到此我们已经实现了 玩家角色的移动,背景的滚动了。。游戏完成了三分之一了。。感觉还可以吧。继续。。


制作游戏障碍物实现碰撞检测


前面我们实现了背景和主角的操作,下面我们开始添加游戏的障碍物以及碰撞检测的功能。

一、制作障碍物Prefab(预制)

Prefab(预制)是cocoscreator官方文档提出的,是为了解决需要重复使用的节点问题。

如何制作预制体prefab呢?具体可以参照官方文档,这里简单的说下,就是在场景中编辑好节点后,直接将节点从 层级管理器 拖到 资源管理器 中即可。

我们来看下极限跳跃的游戏截图分析下。。

QQ20160529-17@2x.png


游戏中障碍物我们分为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     },

脚本写好了,我们对节点进行绑定。

QQ20160529-18@2x.png

绑定好后,我们把层级管理器中的节点zhangaiwu1拖进我们资源管理器的Texture文件夹中,成功后我们的层级管理器中的节点就会变成蓝色,同时我们会在资源管理器中得到一个预制体文件zhangaiwu1,我们这里改成zhangaiwuleft,方便和辨认。

QQ20160529-19@2x.png


预制体文件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。可以在资源管理器中看到。

QQ20160529-20@2x.png

制作好了2个障碍物,我们开始在场景中添加我们的障碍物了。

分析下游戏我们可以发现障碍物是可以根据游戏背景移动的,所以我们要把障碍物添加到背景上。

我们开始制作背景bg1的障碍物,首先把zhangaiwuleft和zhangaiwuright两个预制体拖到层级管理器bg1节点,使其成为bg1的子节点。布局时候把zhangaiwuleft放到屏幕左边,zhangaiwuright放到右边,调整位置。同样的方法给bg2添加障碍物。。如图:

QQ20160529-21@2x.png

通过我们给不同高度的障碍物设置不同的移动时间,我们的游戏看起来更好玩,来运行测试下效果。

zhangaiwu.gif

好了。我们的游戏看起来还不错吧,下面我们来做碰撞检测,也就是说如果玩家和障碍物碰到了,那么我们的角色就会死掉,游戏就会结束。结束场景等会我们在做,现在我们先做碰撞检测,如果碰到障碍物我们停止触摸来达到玩家不可操作的目的。

打开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中添加碰撞事件。天下代码一大抄,直接抄过去就行了。

我们在此运行检测下。。

pengzhuanjiance.gif

我们的角色被障碍物碰到,就死掉了,然后就会屏蔽游戏的触摸事件,玩家角色开始掉落。当角色掉落到屏幕底部时候游戏结束。会切换到结束场景。这里大家看到角色掉没了,不要在意这些细节。。我们接下来开始制作结束场景。


制作游戏结束场景并实现场景切换


前面我们实现了游戏的碰撞检测,碰到障碍物我们的角色就会死掉并开始掉落,角色掉落到屏幕底部时候游戏结束,并跳到结束场景。

我们在资源管理器新建GameOver场景。双击打开场景,调整大小为480x800,添加界面需要的节点。如图。

QQ20160529-22@2x.png

这样我们的结束场景就制作好了。可以预览下。

制作好了,结束场景我们就需要把我们游戏的三个场景关联起来了。

首先我们双击打开我们的第一个场景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场景,也就是第二个场景我们游戏的主场景。

下面我们为开始按钮绑定脚本事件。

QQ2016052<p style=最后更新:2017-04-22 19:32:35

  上一篇:go C++之那些年踩过的坑
  下一篇:go Test2