cocos2d-js | 使用物理引擎chipmunk创建物理世界场景和物理精灵层以及添加触摸事件

说一下大致思路。(嘿嘿我也是看完别人的博客总结的,加上自己的理解,自己怎么可能去看源码嘛!(难道你们不是么。。。))

首先,在工程目录里打开project.json文件,

{
    "project_type": "javascript",

    "debugMode" : 1,
    "showFPS" : true,
    "frameRate" : 60,
    "noCache" : false,
    "id" : "gameCanvas",
    "renderMode" : 0,
    "engineDir":"frameworks/cocos2d-html5",

    "modules" : ["cocos2d", "chipmunk"],

    "jsList" : [
        "src/resource.js",
        "src/app.js",
        "src/StartScene.js",
        "src/PlayScene.js"
    ]
}
这一行添加chipmunk
"modules" : ["cocos2d", "chipmunk"],

其实和cocos2d-cpp结构很像,首先我们先在cocos2d-js工程src目录创建一个场景 PlayScene.js 文件,

然后创建一个继承自Scene的类PlayScene,在创建一个继承自Layer的类PlayLayer,

在PlayScene的onEnter方法中addChild(PlayLayer),像这样

var PlayScene = cc.Scene.extend({

	onEnter:function () {
		this._super();

        //add layer
		this.addChild(new PlayLayer(this.space));

		//add scheduleUpdate
		this.scheduleUpdate();

	},
    
    update : function (dt) {

    }

});

var PlayLayer = cc.Layer.extend({

    onEnter : function () {
        this._super();

    },

    onExit : function () {
        this._super();

    },

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

        this.init();

    },

    init : function () {
        this._super();

        var vSize = cc.winSize;



        this.scheduleUpdate();

        return true;
    },


    update : function (dt) {

        
    },

    

});

然后在PlayScene类中声明一个空间space(以便传入层中创建物理精灵身体时用!),

space:null,

然后在onEnter方法后写一个 initPhysicsEdge 方法,用来初始化物理边界,

​
initPhysicsEdge : function () {
        var vSize = cc.winSize;

        //init space
        this.space = new cp.Space();
        
        //set gravity
        this.space.gravity = cp.v(0, -100);

        //init walls
        var staticBody = this.space.staticBody;
        var walls = [

            //bottom
            new cp.SegmentShape(staticBody, cp.v(0, 0), cp.v(vSize.width, 0), 0),

            //top
            new cp.SegmentShape(staticBody, cp.v(0, vSize.height), cp.v(vSize.width, vSize.height), 0),

            //left
            new cp.SegmentShape(staticBody, cp.v(0, 0), cp.v(0, vSize.height), 0),

            //right
            new cp.SegmentShape(staticBody, cp.v(vSize.width, 0), cp.v(vSize.width, vSize.height), 0)

        ];

        //设置四个墙壁的物理特性
        for (var i = 0; i < walls.length; i++){
            var shape = walls[i];

            //弹性系数
            shape.setElasticity(1);

            //摩擦系数
            shape.setFriction(1);

            this.space.addStaticShape(shape);

        };

        cc.log("PhysicsWorld!_____________");

    },

​

设置物理调试框DebugDraw

先在PlayScene里声明一个 _debugNode

_debugNode:null,

实现DebugDraw

showDebug : function () {
        this._debugNode = new cc.PhysicsDebugNode(this.space);
        this._debugNode.visible = false;     // 为true 时, 显示物理框体
        this.addChild(this._debugNode);
    }

现在我们有了两个方法

initPhysicsEdge
showDebug

想让space生效,需要注册到定时器里

在PlayScene类中的update方法里像这样

​
update : function (dt) {
        //chipmunk step
        this.space.step(dt);

    },

​

让showDebug生效,在场景初始化方法里声明

var PlayScene = cc.Scene.extend({
    space:null,
    _debugNode:null,

	onEnter:function () {
		this._super();

        //init PhysicsWorld
        this.initPhysicsEdge();

        //debugDraw
        this.showDebug();

        //add layer
		this.addChild(new PlayLayer(this.space));

		//add scheduleUpdate
		this.scheduleUpdate();

	},

在刚体创建的时候使用

var DEBUG_NODE_SHOW = true;

然后记得在PlayScene类onEnter方法中初始化默认定时器

//add scheduleUpdate
this.scheduleUpdate();

接下来在层里创建一个物理精灵

在PlayLayer的init方法中(cola是我给精灵起的名字。。。)

//initBody
        var SPRITE_WIDTH = 110;//设置body宽高
        var SPRITE_HEIGHT = 35;
        var body = new cp.Body(1, cp.momentForBox(1, SPRITE_WIDTH, SPRITE_HEIGHT));//1为质量
        this.space.addBody(body);

        //initShape with body
        var shape = new cp.BoxShape(body, SPRITE_WIDTH, SPRITE_HEIGHT);
        shape.setElasticity(0.5);//弹性系数
        shape.setFriction(0.5);//摩擦系数
        this.space.addShape(shape);

        //initSprite with body
        var cola = new cc.PhysicsSprite(res.Cola_png);
        cola.setBody(body);
        cola.setPosition(p);//p为cc.p()类型,看你想把它放哪
        this.addChild(cola);

最后。。如果你想写点击事件,需要在PlayLayer层的onEnter方法里初始化一个事件监听器

onEnter : function () {
        this._super();

        cc.eventManager.addListener({
            event : cc.EventListener.TOUCH_ONE_BY_ONE,
            onTouchBegan : this.onTouchBegan.bind(this)
        }, this);

    },

同时在onExit方法里移除监听器

onExit : function () {
        this._super();

        cc.eventManager.removeListener(cc.EventListener.TOUCH_ONE_BY_ONE);

    },

然后比如onTouchBegan

onTouchBegan : function (touch, event) {
        cc.log("TouchBegan");
        var p = touch.getLocation();
        this.updateCola(p);


    },

 点击后会调用到层中的updateCola方法同时传入点击坐标p

你可以把刚刚写在init方法里的物理精灵拿出来,写到updateCola方法里,

updateCola : function (p) {
        cc.log("addCola*********************");

        //initBody
        var SPRITE_WIDTH = 110;//设置body宽高
        var SPRITE_HEIGHT = 35;
        var body = new cp.Body(1, cp.momentForBox(1, SPRITE_WIDTH, SPRITE_HEIGHT));//1为质量
        this.space.addBody(body);

        //initShape with body
        var shape = new cp.BoxShape(body, SPRITE_WIDTH, SPRITE_HEIGHT);
        shape.setElasticity(0.5);//弹性系数
        shape.setFriction(0.5);//摩擦系数
        this.space.addShape(shape);

        //initSprite with body
        var cola = new cc.PhysicsSprite(res.Cola_png);
        cola.setBody(body);
        cola.setPosition(p);
        this.addChild(cola);

        //push into array
        this.ColaSprites.push(cola);

    },

这样每次点击就会在点击的地方出现一个cola,并且做自由落体运动

和cocos2d-cpp有些地方还是不一样的,比如在cocos2d-cpp里create一个对象的时候要调用的初始化方法为init,

而在cocos2d-js里new一个对象的时候调用的初始化方法为ctor

单点触摸事件

cocos2d-js | 触摸事件

层背景颜色

cocos2d-js | 设置背景颜色LayerColor

猜你喜欢

转载自blog.csdn.net/u011607490/article/details/81347359