Cocos Creator——极限跳跃

转自闭眼就天黑博客,以下内容为重新整理版。

极限跳跃

分析

制作准备,cocos creator 官方文档,api,百度页面,等等。。
第一次接触这个玩意,所以我用了半个小时的时间先大概浏览下文档。。。

做任何游戏之前,先来分析游戏的结构和玩法,本次也不例外。

用思维导图我们很快可以分析出游戏需要展示的内容。

开始场景

我们刚刚分析了《极限跳跃》这款游戏,下面我们开始制作第一个游戏场景,也就是游戏的开始场景。
首先,打开 CocosCreator,新建 HelloWorld 项目。选择项目路径,输入项目名称“jxty”,点击新建项目。

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

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

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

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

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

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

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


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

一、创建场景

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

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

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

使用相同的方法,把我们主场景的 logo,还有底部的边栏也放进场景。
开始按钮我们使用 UI 节点来创建,右键点击 Canvas,创建节点=》创建 UI 节点=》Button(按钮)。
创建好后,修改节点名称为 kaishiyouxi,并删除子节点 label。然后把对应状态资源拖进对应的状态即可。如图所示。

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

主场景

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

1、首先贴入游戏背景,在此我们使用了 2 张背景图 d,只需要把背景拖进层级管理器 2 次,修改名称为 bg1,bg2 即可,背景 2 接着背景 1 点上方设置位置。
2、摆放玩家主角在屏幕合适位置
3、添加金币按钮在屏幕上方
4、右键 Canvas 画布=》创建节点=》创建渲染节点=》Label 文字。修改节点名为 score。String 属性值为 0。

5、左上角加上声音图标
到此我们主场景大概完成了,下面来预览下。

主场景脚本

CocosCreator 零基础制作游戏《极限跳跃》四、添加游戏主场景控制脚本

前面简单的实现了主界面的 UI 设置,现在我们开始制作游戏的控制脚本。
在资源管理器的 Script 文件夹中,点击右键新建 javascript 文件,命名为 GAME。
双击打开 GAME 脚本,在 properties: 中添加属性代码。

//GAME.js
cc.Class({
  extends: cc.Component,
  properties: {
    // player 节点,用于获取主角弹跳的高度,和控制主角行动开关
    player: {
      default: null,
      type: cc.Node
    },
    // bgsprite1 节点,用于背景移动
    bgsprite1: {
      default: null,
      type: cc.Node
    },
    // bgsprite2 节点,用于背景移动
    bgsprite2: {
      default: null,
      type: cc.Node
    },
    // score label 的引用
    scoreDisplay: {
      default: null,
      type: cc.Label
    }
  }
});

保存好后,我们双击 MainScene 打开场景,点击 Canvas,在右侧的属性检查器最底部,点击[添加组件]=》[添加用户脚本组件]然后选择我们刚刚创建的脚本 GAME.js。
添加好后就可以在属性检查器看到我们的属性组件来,然后我们把场景里的节点拖进对应的属性框即可实现节点绑定。不懂得可以多看看官方文档。

这样我门就可以在 GAME 脚本里来操作节点了。
二、创建 HeroPlayer 脚本用来操作玩家主角

//HeroPlayer.js
cc.Class({
  extends: cc.Component,
  properties: {
    //主角跳跃高度
    jumpHeight: 0,
    //主角跳跃持续时间
    jumpTimes: 0,
    //掉落速度
    maxMoveSpeed: 0
  },
  //跳跃
  setJumpUpAction: function() {
    // 跳跃上升
    var jumpUp = cc.moveBy(this.jumpTimes, cc.p(0, this.jumpHeight));
    //jumpUp.reverse();
    return jumpUp;
  },
  //掉落
  setJumpDownAction: function() {
    //下落
    var jumpDown = cc.moveBy(this.jumpTimes, cc.p(0, -this.maxMoveSpeed));
    return jumpDown;
  },
  setJumpRunAction: function() {
    // 初始化跳跃动作
    this.jumpAction = this.setJumpUpAction();
    //掉落动作
    this.maxMoveSpeed = this.setJumpDownAction();
    //包装动作
    var seq = cc.sequence(this.jumpAction, this.maxMoveSpeed);
    this.node.runAction(seq);
  },
  //玩家不操作时,角色进行下坠
  heroDownMove: function() {
    //下落
    var heroDown = cc.moveBy(0.8, cc.p(0, -5));
    return heroDown;
  },
  // use this for initialization
  onLoad: function() {
    this.setJumpRunAction();
  },
  // called every frame, uncomment this function to activate update callback
  update: function(dt) {
    this.node.runAction(this.heroDownMove()); //精灵移动
  }
});

角色有 2 种状态,一种是玩家点击屏幕会实现角色的跳跃,第二种就是角色会受到引力会自动下落。我们在 update 来实现自动下落。添加好方法后,我门在层级管理器中点击 hero 节点。然后在右侧属性检查器中绑定脚本。

我门可以在里面初始化值。跳跃高度值,跳跃持续时间,掉落速度等。
脚本里主要实现了跳跃动作,掉落动作等。
然后回到我们的游戏主脚本也就是 GAME 脚本。添加触摸事件监听,实现监听触摸来调用主角的跳跃动作。
首先在顶部添加脚本引用,然后创建事件监听的方法。

//GAME.js
var HeroPlayer = require("HeroPlayer");
//-----
//事件监听
setEventControl: function() {
  var self = this;
  var hero = self.player.getComponent(HeroPlayer);//角色绑定控件
  cc.eventManazger.addListener({
    event: cc.EventListener.TOUCH_ONE_BY_ONE,
    swallowTouches: true,
    // 设置是否吞没事件,在 onTouchBegan 方法返回 true 时吞没
    onTouchBegan: function (touch, event) {
      //实现 onTouchBegan 事件回调函数
      var target = event.getCurrentTarget();
      // 获取事件所绑定的 target
      var locationInNode = target.convertToNodeSpace(touch.getLocation());
      cc.log("当前点击坐标" + locationInNode);
      hero.node.runAction(hero.setJumpUpAction());//精灵移动
      //cc.log("跳跃:--------");
      return true;
    },
    onTouchMoved: function (touch, event) {            // 触摸移动时触发
    },
    onTouchEnded: function (touch, event) {            // 点击事件结束处理
      //  cc.log("跳跃后角色坐标:" + self.player.getPosition() );
    }
  }, self.node)
},

然后在 onload 方法实现初始化调用。

onLoad: function () {
        //触摸监听
        this.setEventControl();
        // 初始化计分
        this.score = 0;
},

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

制作游戏主场景背景滚动

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

新建脚本 BgMove,并实现移动方法,参数为移动的距离。实现代码:

//BgMove.js
cc.Class({
  extends: cc.Component,
  properties: {
    // foo: {
    //    default: null,
    //    url: cc.Texture2D,  // optional, default is typeof default
    //    serializable: true, // optional, default is true
    //    visible: true,      // optional, default is true
    //    displayName: 'Foo', // optional
    //    readonly: false,    // optional, default is false
    // },vcj
    // ...
  },
  //背景移动
  setMoveAction: function(height) {
    // 移动距离
    var moveHeight = height;
    var moveAction = cc.moveBy(this.jumpTimes, cc.p(0, -moveHeight));
    return moveAction;
  },
  // use this for initialization
  onLoad: function() {}
  // called every frame, uncomment this function to activate update callback
  // update: function (dt) {
  // },
});

创建好脚本后,我们在场景中给节点 bg1、bg2 绑定此脚本。

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

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

//事件监听
setEventControl: function(){
  var self = this;
  var hero = self.player.getComponent(HeroPlayer);//角色绑定控件
  var bg1 = self.bgsprite1.getComponent(MoveBg);//绑定背景控件
  var bg2 = self.bgsprite2.getComponent(MoveBg);//绑定背景控件
//.....
//...省略部分代码.
//.....
  onTouchEnded: function (touch, event) {            // 点击事件结束处理
    if (self.player.getPositionY() > 0) {
      var height = self.player.getPositionY();//背景需要移动的高度
      self.player.setPositionY(height / 2);//设置精灵的高度位置

      bg1.node.runAction(bg1.setMoveAction(height));//背景实现向下滚动
      bg2.node.runAction(bg2.setMoveAction(height));//背景实现向下滚动
    }
//...省略部分代码.

这里分析下代码部分,首先我们创建场景时候,场景 Canvas 的锚点为(0.5,0.5),也就是屏幕的中心点坐标为 0,0。其所有子节点的坐标都是相对于场景来布局,所以说我们的主角布局时候放在屏幕的中下方位置,一开始的 Y 坐标为负数。每次移动 Y 坐标会增加,当 Y 坐标增加超过中心点坐标我们需要进行背景移动,而背景移动的距离则是我们的主角 Y 坐标值减去中心点的 Y 坐标 0,也就是主角 Y 坐标值本身。
所以每次触摸结束,我们对主角的 Y 坐标进行判断,如果大于 0,说明背景需要移动,移动距离为主角 Y 坐标值,然后我门调用背景 1 和背景 2 的移动方法,参数为主角的 Y 坐标。
背景移动时候,我们同时需要修正主角的坐标,设置主角的坐标为超过中心点的一半,这样主角不论怎么移动都只能在屏幕内移动。
下面我门来运行预览,测试下。。

是不是可以实现背景滚动了,大家最后发现了一个问题,背景移动完毕了,没有背景会出现黑色的区域。。
下面我们要实现一个方法,来对背景进行计算。我们现在是两个背景进行拼接的。我们需要来判断哪个背景已经移除屏幕,移除屏幕后改变其位置,让它 Y 坐标变成正在移动的那个背景的上边,这样来实现无缝拼接。这样才是无限滚动的背景。
下面我们继续在 GAME 脚本添加新的方法来实现计算,下面贴代码。

//GAME.js
//...省略代码
//如果背景1的坐标移出屏幕开始设置新的坐标
setBgMoveCreate: function(){
  //如果背景1的坐标移出屏幕开始设置新的坐标
  if(this.bgsprite1.getPositionY()  < -500 ){
    this.bgsprite2.setPositionY(this.bgsprite1.getPositionY()+this.bgsprite1.getContentSize().height);
  }
  //如果背景2的坐标移出屏幕开始设置新的坐标
  if(this.bgsprite2.getPositionY() < -500 ){
    this.bgsprite1.setPositionY(this.bgsprite2.getPositionY()+this.bgsprite2.getContentSize().height);
  }
},
//实现update方法
update: function (dt) {

  this.setBgMoveCreate();//检测背景

},

我们在 update 里不停的检测背景移动事件来解决黑色问题。下面来再次测试下。

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

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

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

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

Prefab(预制)是 cocos creator 官方文档提出的,是为了解决需要重复使用的节点问题。
如何制作预制体 prefab 呢?具体可以参照官方文档,这里简单的说下,就是在场景中编辑好节点后,直接将节点从 层级管理器 拖到 资源管理器 中即可。
我们来看下极限跳跃的游戏截图分析下。。

游戏中障碍物我们分为 2 种,一个是向左移动的,一个是向右移动的,这里我就简单省事了,直接创建了 2 个预制体,每个预制体实现自己的脚本。可以集成在一起的。
我们先制作左边的障碍物,首先把障碍物素材拖进层级管理器取名 zhangaiwu1。然后我们来实现并制作左边的脚本,创建脚本 guawuleft。实现代码。

//guaiwuleft.js
cc.Class({
    extends: cc.Component,
    properties: {

        times: 0,//控制时间

        },
    },
    onLoad: function () {

        this.moveRight();
    },
//左右移动
    moveRight: function(){

        var seq = cc.repeatForever(
             cc.sequence(
                 cc.moveBy(this.times, cc.p(240, 0)), cc.moveBy(this.times, cc.p(-240,0))
             ));
        this.node.runAction(seq);
    },

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

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

预制体文件 zhangaiwu1,我们这里改成 zhangaiwuleft。然后删除层级管理器的 zhangaiwu1 节点。使用同样的方法,我们创建脚本 zhangaiwuright,并制作预制体 zhangaiwuright。

//guawuright.js
cc.Class({
    extends: cc.Component,
    properties: {

        times: 0,//控制时间

        },
    },
    onLoad: function () {

        this.moveRight();
    },
    //左右移动
    moveRight: function(){


        var seq = cc.repeatForever(
             cc.sequence(
                 cc.moveBy(this.times, cc.p(-240, 0)), cc.moveBy(this.times,cc.p(240,0))
             ));
       this.node.runAction(seq);
    },

这样我们就制作好了 2 个预制体,分别为 zhangaiwuleft 和 zhangaiwuright。可以在资源管理器中看到。

制作好了 2 个障碍物,我们开始在场景中添加我们的障碍物了。
分析下游戏我们可以发现障碍物是可以根据游戏背景移动的,所以我们要把障碍物添加到背景上。
我们开始制作背景 bg1 的障碍物,首先把 zhangaiwuleft 和 zhangaiwuright 两个预制体拖到层级管理器 bg1 节点,使其成为 bg1 的子节点。布局时候把 zhangaiwuleft 放到屏幕左边,zhangaiwuright 放到右边,调整位置。同样的方法给 bg2 添加障碍物。。如图:

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

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

//guaiwuleft.js
var hero2 = require("HeroPlayer");//引用玩家的操作脚本
//....省略..
//当前节点世界坐标系下的范围包围盒
 noteBox: function(){

        return this.node.getBoundingBoxToWorld();

    },

    // called every frame, uncomment this function to activate update callback
    update: function (dt) {

        var _label = cc.find("Canvas/hero").getComponent(hero2);

      //障碍物碰撞框
    if(cc.rectIntersectsRect(_label.node.getBoundingBoxToWorld(), this.noteBox())){

           cc.eventManager.removeAllListeners();//移除所有事件监听

            }

    },

同样的方法,我们在 guaiwuright 中添加碰撞事件。天下代码一大抄,直接抄过去就行了。
我们在此运行检测下。。

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

Show Comments