Cocos Creator 从零学习 一

前言

尽管知乎上对Cocos2dx成见很大,但是徘徊于纠结用什么游戏引擎不如都试试。况且这个软件是国人开发的,学习起来应该不算困难。

虽然没有学过JavaScript,但是似乎也可以边查边写吧。JavaScript的教程: http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000

Cocos creator目前版本为1.5.1,官网有一份很详细的手册,网址为 http://www.cocos.com/docs/creator/ 。这篇文章是该快速上手这一章的精简版,并且对游戏性进行了提升。

知乎网友表情.png

安装

windows下面的安装是没有任何问题的。mac下的安装,需要注意一下。
在官网下载安装包之后,拖动到applications中之后,打开会提示该应用是未被信任的开发者。此时,打开系统偏好设置中的安全性与隐私中的通用,会看到打开的按钮,通过此方式打开之后,不再进行提醒了。

快速开始

dashboard

从dashboard开始新建项目,或者打开项目。根据教程中关于快速上手的部分,我们从这个地址可以下载到一个初始工程项目 下载初始项目
或者点击这里下载 https://github.com/cocos-creator/tutorial-first-game/releases/download/v1.2/start_project.zip

这个快速上手最终做出的游戏效果是这样的: http://fbdemos.avosapps.com/star-catcher/
这个游戏有点类似于接金币这样的游戏,但是更加困难,游戏的学习曲线非常的大,由于这个小怪物的水平加速度难以驾驭以及上下蹦跳的关系,几乎很难已去接到五角星,而且也没有什么剧情。我们最好把他改的好玩一点吧。

打开这个项目,我们先学习一下界面。左下角是资源面板,在初始项目中,已经建立了一个工程目录,这里有最基本的资源,已经目录组织。assets的意思是资产,在这个总目录下面,有三个子目录,包含有字体,音频,与图片资源。

创建场景

场景是至关重要的,因为场景包含了游戏脚本,而场景在游戏开始的时候会自动加载。在资源面板中的assets下点击加号创建一个场景,重命名为game,双击打开。

屏幕快照 2017-06-20 上午11.01.53.png

左上角的层级管理器显示的是当前的场景中节点之间的关系。
在这个game场景中,只有一个根节点canvas(画布),现在这个节点上是空的,意味着什么都不会加载。

点击根结点在右侧数据面板中,我们可以设置根节点的分辨率。分辨率的高度设置为自适应,总为960x640,和iPhone第一代长宽比一致,推测这个分辨率应该是dp而不是pixel吧。

场景图像

将资源background拖拽到canvas上,使得background成为canvas的一个子节点,注意不要将background变成另一个根节点。
使用cmd+s来保存刚刚的变动。
选中场景中的background图片,然后,在左上角找到变换工具的第四个按钮,分别是平移,旋转,缩放,矩形变换。选中矩形变换,将background变换为一个能覆盖场景的大小,如下图所示。

场景图像

上述步骤也可以直接对background的属性进行设置,设置位置为0,0,宽高为1600和800就行。

用同样的方法添加地面。
用同样的方法插入小怪物,并且重命名为player。图片的默认锚点为中心位置,这里将锚点anchor的y设置为0。

创建脚步

接下来出现了惊人的一幕,教程居然说不会编程也没关系,你可以交给你的程序员小伙伴来解决,果然是我现在只差一个程序员了。

在下图中资源的player的位置建立一个js脚本文件,并打开。


脚本

在properties中插入以下内容,这部分是小怪物的物理属性

        jumpHeight:0,
        jumpDuration:0,
        maxMoveSpeed:0,
        accel:0,

选中小怪物图片,在属性框中找到添加组件,把player脚本添加到player图片上,并且设置好相关参数。

参数设置

完善脚本

我们在脚本中继续加入其他功能。首先是跳跃的动作。

在properties下面加入这一段

    setJumpAction: function(){
        var jumpUp = cc.moveBy(this.jumpDuration, cc.p(0,this.jumpHeight)).easing(cc.easeQuadraticActionOut());
        var jumpDown = cc.moveBy(this.jumpDuration, cc.p(0,-this.jumpHeight)).easing(cc.easeQuadraticActionIn());
        return cc.repeatForever(cc.sequence(jumpUp, jumpDown));
    },

moveBy是官方的API,在官方API中查询一下该API的使用,第一个参数是移动的距离,第二个参数是移动的位置。很显然是向上移动了一段距离。后面的easing是生成缓动运动,生成的对象是easeQuadraticActionIn和Out,这两个是二次曲线。原来的教程中是三次曲线,这个和真实世界中的物理运动差的太多了。

在onload方法中加入下面这段代码,启动动画。

    onLoad: function () {
        this.jumpAction = this.setJumpAction();
        this.node.runAction(this.jumpAction);
    },

现在点击播放按钮刻可以查看初始的效果。

控制角色

为主角加上移动的控制。
在setJumpAction下面继续添加方法。

    setInputControl: function(){
        var self = this;
        cc.eventManager.addListener({
            event: cc.EventListener.KEYBOARD,
            onKeyPressed: function(keyCode, event){
                switch(keyCode){
                    case cc.KEY.a:
                        self.accLeft = true;
                        self.accRight = false;
                        break;
                    case cc.KEY.d:
                        self.accRight = true;
                        self.accLeft = false;
                }
            },
            onKeyReleased: function(keyCode, event){
                switch(keyCode){
                    case cc.KEY.a:
                        self.accLeft = false;
                        break;
                    case cc.KEY.d:
                        self.accRight = false;
                        break;
                }
            }
        }, self.node)
    },

更新onload和update代码

    onLoad: function () {
        this.jumpAction = this.setJumpAction();
        this.node.runAction(this.jumpAction);
        
        this.accLeft = false;
        this.accRight = false;
        
        this.xSpeed = 0;
        
        this.setInputControl();
    },

    update: function(dt){
        if(this.accLeft){
            this.xSpeed -= this.accel * dt;
        }
        else if(this.accRight){
            this.xSpeed += this.accel * dt;
        }
        if(this.xSpeed >0){
            this.xSpeed -= this.accel/2 * dt;
        }
        else if( this.xSpeed <0){
            this.xSpeed += this.accel/2 * dt;
        }
        if(Math.abs(this.xSpeed) > this.maxMoveSpeed){
            this.xSpeed = this.maxMoveSpeed * this.xSpeed / Math.abs(this.xSpeed);
        }
        
        this.node.x += this.xSpeed * dt;
    },

第一个代码添加了个监听器,按键变动的时候改变accLeft和accRight的值。启动时打开监听,然后,在每一帧需要更新的时候,计算怪物的位置。

增加五角星

添加Game脚本到assets/scripts文件夹下,双击打开脚本,加入以下代码

cc.Class({
    extends: cc.Component,

    properties: {
        // 这个属性引用了星星预制资源
        starPrefab: {
            default: null,
            type: cc.Prefab
        },
        // 星星产生后消失时间的随机范围
        maxStarDuration: 0,
        minStarDuration: 0,
        // 地面节点,用于确定星星生成的高度
        ground: {
            default: null,
            type: cc.Node
        },
        // player 节点,用于获取主角弹跳的高度,和控制主角行动开关
        player: {
            default: null,
            type: cc.Node
        },
        scoreDisplay: {
            default: null,
            type: cc.Label
        }
    },

    onLoad: function () {
        // 获取地平面的 y 轴坐标
        this.groundY = this.ground.y + this.ground.height/2;
        // 生成一个新的星星
        this.spawnNewStar();
        this.score = 0;
    },
    
    gainScore: function () {
        this.score += 1;
        // 更新 scoreDisplay Label 的文字
        this.scoreDisplay.string = 'Score: ' + this.score.toString();
    },

    spawnNewStar: function() {
        // 使用给定的模板在场景中生成一个新节点
        var newStar = cc.instantiate(this.starPrefab);
        // 将新增的节点添加到 Canvas 节点下面
        this.node.addChild(newStar);
        // 为星星设置一个随机位置
        newStar.setPosition(this.getNewStarPosition());
        newStar.getComponent('star').game = this;
    },

    getNewStarPosition: function () {
        var randX = 0;
        // 根据地平面位置和主角跳跃高度,随机得到一个星星的 y 坐标
        var randY = this.groundY + cc.random0To1() * this.player.getComponent('Player').jumpHeight + 50;
        // 根据屏幕宽度,随机得到一个星星 x 坐标
        var maxX = this.node.width/2;
        randX = cc.randomMinus1To1() * maxX;
        // 返回星星坐标
        return cc.p(randX, randY);
    },
    
    // called every frame, uncomment this function to activate update callback
    // update: function (dt) {

    // },
});

从 资源管理器 中拖拽 assets/textures/star 资源到场景中,添加名叫 Star 的JavaScript脚本到assets/scripts/中,并关联脚本。
打开star脚本,添加如下代码

cc.Class({
    extends: cc.Component,

    properties: {
        // foo: {
        //    default: null,      // The default value will be used only when the component attaching
        //                           to a node for the first time
        //    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
        // },
        // ...
        pickRadius:0,
    },

    // use this for initialization
    onLoad: function () {

    },
    
    getPlayerDistance: function () {
        // 根据 player 节点位置判断距离
        var playerPos = this.game.player.getPosition();
        // 根据两点位置计算两点之间距离
        var dist = cc.pDistance(this.node.position, playerPos);
        return dist;
    },

    onPicked: function() {
        // 当星星被收集时,调用 Game 脚本中的接口,生成一个新的星星
        this.game.spawnNewStar();
        this.game.gainScore();
        // 然后销毁当前星星节
        this.node.destroy();
        
    },
    
    update: function (dt) {
        // 每帧判断和主角之间的距离是否小于收集距离
        if (this.getPlayerDistance() < this.pickRadius) {
            // 调用收集行为
            this.onPicked();
            return;
        }
    },    
    
    

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

    // },
});

现在在star的属性中设置pickRadius为60。
从层级管理器中将star节点拖拽到资源管理器中的assets文件夹下,就生成了名叫star的 Prefab 资源。
从场景中删除star节点。
选中Canvas节点后,拖拽脚本到 属性检查器,从资源管理器中拖拽star Prefab 资源到Game组件的Star Prefab属性中,从层级编辑器中拖拽ground和Player 节点到组件中相同名字的属性上。

接下来再加入计分机制,和上面的过程十分的类似,这里就略去不详细写了,此时,测试一下游戏的效果,已经可以看到游戏大致效果。

如果你有任何问题,可以查看官方的上手的教程,也可以点击这里可以下载到此为止的工程:
链接: https://pan.baidu.com/s/1dFw3VSP 密码: 7vgu

官方在接下来继续进行了游戏的完善,不过我不打算继续完善下去了,接下来将关注对触摸屏的支持

效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,073评论 25 707
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一种新的协议。它实...
    香橙柚子阅读 23,557评论 8 183
  • 多看视频上别人的研磨手法,建议直接上中端磨石,刃黑1000+龙虾5000+北山8000搭配一块名仓。龙虾北山可以二...
    a冶铁阅读 1,753评论 5 5
  • 在课本之外的地方接触到贺宾客这群在朝堂颇有地位的名作者时,条件反射地就会率先贴上文人的标签,从而招致一些本末倒置的...
    王家人宁阅读 309评论 0 0
  • 最后一次,我永远走在夜里,盼不来曙光黎明,更没有灯盏追逐我的踪迹。每年的 这个时候都落小雨,哪怕天晴哪怕月明。扔掉...
    李一十八阅读 213评论 0 3