Cocos2d-js官方完整项目教程翻译:八、跟我们的游戏添加游戏币和障碍物

一、 简介

在本教程中我们将尝试添加到我们的跑酷游戏和障碍

本教程中,我们的主角应该能够收集硬币时,正在死的时候,障碍物发生碰撞

我们还将介绍如何平铺地图编辑器的游戏关卡设计。由于游戏逻辑有点复杂的比以前

所以我们将重构代码之前我们增加新的游戏组件

二、准备

在我们开始之前让我们完成准备的东西

三、资源和全局设置

我们将为我们的跑酷游戏添加两个游戏元素。所以我们需要添加一些全球性的整数标签来识别每个比赛项目

让我们添加下面的代码片段globals.js结束

// collision type for chipmunk
if(typeof SpriteTag == "undefined") {
    var SpriteTag = {};
    SpriteTag.runner = 0;
    SpriteTag.coin = 1;
    SpriteTag.rock = 2;
};

在这里,我们使用0,1,2分别代表运动员硬币和岩石

我们还介绍了另一spritesheet命名background.png和background.plist。我们已把硬币和岩石精灵spritesheet命名background.png

详情如何包装这些精灵离开的下一个分段

接下来,让我们复制资源文件到我们的研究和进一步的参考目录添加两个变量

var res = {
    helloBG_png : "res/helloBG.png",
    start_n_png : "res/start_n.png",
    start_s_png : "res/start_s.png",
    PlayBG_png  : "res/PlayBG.png",
    runner_png  : "res/running.png",
    runner_plist : "res/running.plist",
    map_png : "res/map.png",
    map00_tmx : "res/map00.tmx",
    map01_tmx : "res/map01.tmx",
    background_png :"res/background.png",
    background_plist : "res/background.plist"
};

var g_resources = [
    //image
    res.helloBG_png,
    res.start_n_png,
    res.start_s_png,
    res.PlayBG_png,
    res.runner_png,
    res.runner_plist,
    res.map_png,
    res.map00_tmx,
    res.map01_tmx,
    res.background_png,
    res.background_plist
];
四、 TexturePacker 包装硬币 和岩石

在前面的章节中,我们已经学会了怎样把一堆小精灵变成一个大的紧凑型sprite图片。

首先,你应该推出TexturePacker和拖动所有资产RES /TexturePacker /硬币和岩石注:你可以整个游戏资源从下载之前。

通过拖动资源你应该用一些路径就像XXX //研究/background.png或XXX //研究/ background.plist指定数据文件的格式结构

如果你不想任何优化spritesheet只是把它们和新闻发布生成最终的spritesheet


五、tiledmap对象层介绍

我们用我们的水平tiledmap地图,但缺乏比赛项目。因此在这一节中,我们将讨论如何设计tiledmap对象层水平项目

添加硬币对象层

首先,我们将添加硬币对象层

发射瓷砖和开放map00.tmxmap01.tmx

创建一个命名的map00.tmxmap01.tmx硬币对象层

通过拖动矩形对象地图设计对象层

你可以改变矩形的大小和它的位置。您也可以复制或删除对象

Cocos2d-js官方完整项目教程翻译:八、跟我们的游戏添加游戏币和障碍物_第1张图片

设计对象提示:你可以在平铺地图图层透明度的变化你可以很容易地放置对象

添加岩石对象层

的过程中创造的岩石对象层或多或少是创建对象层相同的硬币

所以我们将离开自己的实现

重构backgroundlayer类和添加一些辅助方法

有时当你编码时,你会发现很难增加新的功能到现有的结构

这是一个糟糕的代码结构,我们应该停止并且开始重构工作

重构BackgroundLayer类

因为我们将花栗鼠的物理身体进入我们的背景所以我们需要一种方法来获得playscene空间对象的创建

让我们在背景层选择器函数名称的变化和传递参数命名空间到它。我们还应该添加一个新的成员变量

backgroundlayer类。下面的代码片段

ctor:function (space) {
        this._super();

        // clean old array here
        this.objects = [];
        this.space = space;

        this.init();
    },

在这里,我们已经添加了额外的初始化代码。我们添加了一个数组的指定对象并初始化为空数组

(*注:你应该调用这个方法。()权转让后的this.space =空间。因为我们init方法*创建物理对象)

添加辅助方法

添加成员变量backgroundlayer

space:null,
spriteSheet:null,
objects:[],
在init 方法 初始化 sprite集合图片

// create sprite sheet
    cc.spriteFrameCache.addSpriteFrames(res.background_plist);
    this.spriteSheet = cc.SpriteBatchNode.create(res.background_png);
    this.addChild(this.spriteSheet);
添加一个方法 loadobject 初始化 岩石 和硬币

loadObjects:function (map, mapIndex) {
    // add coins
    var coinGroup = map.getObjectGroup("coin");
    var coinArray = coinGroup.getObjects();
    for (var i = 0; i < coinArray.length; i++) {
        var coin = new Coin(this.spriteSheet,
            this.space,
            cc.p(coinArray[i]["x"] + this.mapWidth * mapIndex,coinArray[i]["y"]));
        coin.mapIndex = mapIndex;
        this.objects.push(coin);
    }

    // add rock
    var rockGroup = map.getObjectGroup("rock");
    var rockArray = rockGroup.getObjects();
    for (var i = 0; i < rockArray.length; i++) {
        var rock = new Rock(this.spriteSheet,
            this.space,
            rockArray[i]["x"] + this.mapWidth * mapIndex);
        rock.mapIndex = mapIndex;
        this.objects.push(rock);
    }
},

在这里,我们重申所有对象的信息在平铺地图创建响应的花栗鼠刚体。最后我们存储这些对象对象数组

这些代码是自解释的。你应该只注重mapindex参数。我们使用的参数计算我们应该将刚体

我们需要init方法结束通话loadobject法在第一个屏幕地图创建物理对象

this.loadObjects(this.map00, 0);
this.loadObjects(this.map01, 1);

用于删除未使用的ChipMunk刚体添加两个辅助方法

第一种方法称为removeobjects。它消除了一个对象的mapindex。这里是实现

removeObjects:function (mapIndex) {
        while((function (obj, index) {
            for (var i = 0; i < obj.length; i++) {
                if (obj[i].mapIndex == index) {
                    obj[i].removeFromParent();
                    obj.splice(i, 1);
                    return true;
                }
            }
            return false;
        })(this.objects, mapIndex));
    },

另外一个方法是 removeObjectByShape:

   removeObjectByShape:function (shape) {
        for (var i = 0; i < this.objects.length; i++) {
            if (this.objects[i].getShape() == shape) {
                this.objects[i].removeFromParent();
                this.objects.splice(i, 1);
                break;
            }
        }
    },
这个方法将删除ChipMunk对象的形状。

六、包装:加入checkandreload方法和一次性的逻辑生成

在地图上移动我们也应该loadobject方法重新硬币和石头”

我们也可以通过调用removeobjects方法删除所有未使用的对象

下面的代码片段

checkAndReload:function (eyeX) {
        var newMapIndex = parseInt(eyeX / this.mapWidth);
        if (this.mapIndex == newMapIndex) {
            return false;
        }

        if (0 == newMapIndex % 2) {
            // change mapSecond
            this.map01.setPositionX(this.mapWidth * (newMapIndex + 1));
            this.loadObjects(this.map01, newMapIndex + 1);
        } else {
            // change mapFirst
            this.map00.setPositionX(this.mapWidth * (newMapIndex + 1));
            this.loadObjects(this.map00, newMapIndex + 1);
        }
        this.removeObjects(newMapIndex - 1);
        this.mapIndex = newMapIndex;

        return true;
    },

七、添加硬币和石头

现在是时候添加硬币和岩石的实现。尽管实现的细节也应该注意到这两种设计思想

等级。在这里,我们宁愿从CC代替cc.sprite类。我们让每一个对象实例cc.sprite

八、 硬币 类的设计 与实现

创建一个新的文件名为coin.js。我们将在本文件中定义我们的硬币类。确保你有位于您的src目录

派生的命名硬币从cc.Class让我们在整个实施一看

var Coin = cc.Class.extend({
space:null,
sprite:null,
shape:null,
_mapIndex:0,// which map belongs to
get mapIndex() {
    return this._mapIndex;
},
set mapIndex(index) {
    this._mapIndex = index;
},

/** Constructor
 * @param {cc.SpriteBatchNode *}
 * @param {cp.Space *}
 * @param {cc.p}
 */
ctor:function (spriteSheet, space, pos) {
    this.space = space;

    // init coin animation
    var animFrames = [];
    for (var i = 0; i < 8; i++) {
        var str = "coin" + i + ".png";
        var frame = cc.spriteFrameCache.getSpriteFrame(str);
        animFrames.push(frame);
    }

    var animation = cc.Animation.create(animFrames, 0.2);
    var action = cc.RepeatForever.create(cc.Animate.create(animation));

    this.sprite = cc.PhysicsSprite.create("#coin0.png");

    // init physics
    var radius = 0.95 * this.sprite.getContentSize().width / 2;
    var body = new cp.StaticBody();
    body.setPos(pos);
    this.sprite.setBody(body);

    this.shape = new cp.CircleShape(body, radius, cp.vzero);
    this.shape.setCollisionType(SpriteTag.coin);
    //Sensors only call collision callbacks, and never generate real collisions
    this.shape.setSensor(true);

    this.space.addStaticShape(this.shape);

    // add sprite to sprite sheet
    this.sprite.runAction(action);
    spriteSheet.addChild(this.sprite, 1);
},

removeFromParent:function () {
    this.space.removeStaticShape(this.shape);
    this.shape = null;
    this.sprite.removeFromParent();
    this.sprite = null;
},

getShape:function () {
    return this.shape;
}
});

让我们一块解释代码

首先,我们把三的成员变量命名为:空间,雪碧和形状。我们将使用这些变量来创建对象的物理身体的硬币

它的显示属性

然后,我们增加了一个成员变量_mapindex。我们使用的获取/设置语法糖来定义变量的访问

ctor方法是硬币类的构造函数。我们将创建一个spritesheet硬币空间位置的对象

由于金币是圆形的,所以我们已经创建了附加到刚体的圆形。矢量函数其余部分自我解释

最后,我们需要定义一个做清理工作的方法。这是removefromparent方法。首先去除刚体空间然后拆下雪碧

从它的父。getshape方法仅仅是一个用于访问存储在硬币的形状对象的getter方法

九、 岩石 类的设计 与实现

设计原则的是更多或更少的硬币除了刚性的形状类型的部分

因为我们的岩类是一个矩形框。因此我们使用cp.boxshape硬币取代cc.circleshape

这里是rock.js完整的源代码

var Rock = cc.Class.extend({
    space:null,
    sprite:null,
    shape:null,
    _map:0,// which map belong to
    get map() {
        return this._map;
    },
    set map(newMap) {
        this._map = newMap;
    },

    /** Constructor
     * @param {cc.SpriteBatchNode *}
     * @param {cp.Space *}
     * @param {cc.p}
     */
    ctor:function (spriteSheet, space, posX) {
        this.space = space;

        this.sprite = cc.PhysicsSprite.create("#rock.png");
        var body = new cp.StaticBody();
        body.setPos(cc.p(posX, this.sprite.getContentSize().height / 2 + g_groundHight));
        this.sprite.setBody(body);

        this.shape = new cp.BoxShape(body,
            this.sprite.getContentSize().width,
            this.sprite.getContentSize().height);
        this.shape.setCollisionType(SpriteTag.rock);

        this.space.addStaticShape(this.shape);
        spriteSheet.addChild(this.sprite);
    },

    removeFromParent:function () {
        this.space.removeStaticShape(this.shape);
        this.shape = null;
        this.sprite.removeFromParent();
        this.sprite = null;
    },

    getShape:function () {
        return this.shape;
    }
});
十、提升playScene

playscene onenter功能重构

首先,让我们添加一个额外的数组的指定shapestoremove并初始化playscene.js onenter函数开始

//the following line goes in init member variable define area
shapesToRemove :[],

//the following line goes at the beginning of the *onEnter* function.
this.shapesToRemove = [];
其次,修改backgroundlayer创作。 在这里, 我们 只是通过 空间 对象 构造函数 backgroundlayer

this.gameLayer.addChild(new BackgroundLayer(this.space), 0, TagOfLayer.background);

十一、添加碰撞检测回调

首先,我们应该调用这两个方法initphyiscs方法结束

// setup chipmunk CollisionHandler
        this.space.addCollisionHandler(SpriteTag.runner, SpriteTag.coin,
            this.collisionCoinBegin.bind(this), null, null, null);
        this.space.addCollisionHandler(SpriteTag.runner, SpriteTag.rock,
            this.collisionRockBegin.bind(this), null, null, null);

addcollisionhandler方法需要一个回调发生碰撞时

然后我们定义这两个回调函数来处理主角和硬币和岩石撞击

 collisionCoinBegin:function (arbiter, space) {
        var shapes = arbiter.getShapes();
        // shapes[0] is runner
        this.shapesToRemove.push(shapes[1]);
    },

    collisionRockBegin:function (arbiter, space) {
        cc.log("==game over");
    },
在背景层删除未使用的刚体。 你应该在 最后 更新 方法 中添加以下代码

 // Simulation cpSpaceAddPostStepCallback
        for(var i = 0; i < this.shapesToRemove.length; i++) {
            var shape = this.shapesToRemove[i];
            this.gameLayer.getChildByTag(TagOfLayer.background).removeObjectByShape(shape);
        }
        this.shapesToRemove = [];
我们无法删除物理身体的物理模拟过程中。 因此我们 使用一个额外的 数组的指定 shapestoremove 需要 删除的 时间数据

十二、包装所有东西

祝贺你!你几乎到达终点。在我们打调试按钮来查看结果。让我们添加一些额外的胶水代码连接在一起的一切

开放project.json和添加两个数组项jslist阵列的末端

"jsList" : [
        "src/resource.js",
        "src/app.js",
        "src/AnimationLayer.js",
        "src/BackgroundLayer.js",
        "src/PlayScene.js",
        "src/StatusLayer.js",
        "src/globals.js",
        "src/coin.js",
        "src/rock.js"
    ]

建立并运行!恭喜我们做到了

让我们看看我们最后的果实


十二、总结

在本教程中,我们已经度过了一个很长的旅程。但是值得的不是吗

我们已经学会了如何使用tiledmap对象层设计复杂的游戏水平和如何定制自己的类来扩展你的代码结构

你可以从这里http://cocos2d-x.org/docs/tutorial/framework/html5/parkour-game-with-javascript-v3.0/chapter8/res/Parkour.zip下载完整的源代码

十三、接下来怎么办

在下一个教程中我们将介绍如何不断更新游戏HUD我们还会添加逻辑和简单的手势识别我们的游戏制作游戏

玩家跳过障碍。保持协调



你可能感兴趣的:(JavaScript,js,canvas,html5,cocos2d-x)