最近笔者在学习cocos2d-js,打算和朋友合作完成一款游戏,但是在制作过程中发现现在网上cocos2d-js的资料少的可怜,特别是物理引擎这一块,熟悉Chipmunk和Box2d的朋友们都知道,这两个引擎的C++的资料是非常丰富的,但关于JS的少之又少,所以笔者想借此机会分享一点Chipmunk js的用法。笔者能力有限,不喜勿喷。
首先先来介绍一下Chipmunk这款物理引擎。Chipmunk物理引擎,由Howling Moon Software的Scott Lebcke开发,用纯C编写。
Chipmunk的核心概念:空间(space):类似于场景,所有的物理事件发生的地方。
刚体(body):接触过物理引擎的朋友都知道,用来模拟物理形态的物体。
形状(shape):物体的形状。
节点,关节(joint):链接刚体的节点。
cocos2d-js中封装好了Chipmunk引擎,所以只需要按以下步骤就可以完成物理引擎的使用:
1.创建物理空间:create space
2.确认物理空间边界:create wall
3.建立空间中的物体:create body
4.给物体指定形状:bind shape
5.给刚体绑定精灵:bind sprite
通过以上五步基本就可以实现简单的物理引擎的使用,下面,我们用Chipmunk实现一根摇摆的绳子。
先看一下效果图:
看过图相信读者也基本明白如何实现绳子了,对,就是把一连串的刚体串在一起,就能实现绳子的物理特性,废话不多说,咱们直接上代码。
RodeTestScene.js:
首先建立Scene,把Layer加到Scene上
var RopeTestScene=cc.Scene.extend({
onEnter: function () {
this._super();
var layer=new RopeTestLayer();
this.addChild(layer);
}
});
下面看看我们Layer的构造函数里面使用的方法
var DEBUG_NODE_SHOW = true; //<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 26px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none; background-color: rgb(255, 255, 255);">是否绘制调试遮罩开关常量</span>
var RADIUS=10; //半径
var RopeTestLayer=cc.Layer.extend({
space:null,
ctor:function(){
this._super();
var size=cc.winSize;
this.initPhysics(); //初始化物理空间
this.scheduleUpdate();
//绳子
this.createRope();
return true;
},
setupDebugNode: function () {
this._debugNode = new cc.PhysicsDebugNode(this.space);
this._debugNode.visible = DEBUG_NODE_SHOW;
this.addChild(this._debugNode);
},
initPhysics:function(){
var winSize=cc.director.getWinSize();
this.space=new cp.Space();
this.setupDebugNode();
this.space.gravity=cp.v(0,-100);
var staticBody=this.space.staticBody;
var walls=[
new cp.SegmentShape(staticBody, cp.v(0, 0), cp.v(winSize.width, 0), 0),
new cp.SegmentShape(staticBody, cp.v(0, winSize.height),cp.v(winSize.width, winSize.height), 0),
new cp.SegmentShape(staticBody, cp.v(0, 0),cp.v(0, winSize.height), 0),
new cp.SegmentShape(staticBody, cp.v(winSize.width, 0),cp.v(winSize.width, winSize.height), 0)
];
//把四面墙添加到space,这里要注意,墙是静态shape,这点很重要
for(var i=0;i<walls.length;i++){
var shape=walls[i];
shape.setElasticity(1);
shape.setFriction(1);
this.space.addStaticShape(shape);
}
},
createRope:function(){
var size=cc.winSize;
this.List=[]; //建立一个容器,用来储存咱们的20个刚体
for(var i=0;i<20;i++){
var body=new cp.Body(1,cp.momentForCircle(1,0,RADIUS,cp.v(0,0))); //圆形刚体
body.setPos(cc.p(size.width/2-i*10,size.height*0.9-i*50)); //为了能让绳子摆动,坐标稍微偏移一点
this.space.addBody(body); //将刚体添加到空间里
var shape=new cp.CircleShape(body,RADIUS,cp.v(0,0)); //圆型形状
shape.setElasticity(0.5);
shape.setFriction(0.5);
this.space.addShape(shape); //将形状添加到空间里
var sprite=new cc.PhysicsSprite(res.Point_png); //创建精灵
sprite.setBody(body); //绑定刚体
sprite.setScale(0.2);
sprite.setPosition(cc.p(size.width/2-i*10,size.height*0.9-i*50));
this.addChild(sprite); //添加精灵到场景
this.List.push(body); //将刚体压入容器
}
for(var i=1;i<this.List.length;i++){ //注意我们从第二个刚体开始循环
var body1=this.List[i-1]; //前一个刚体
var body2=this.List[i]; //当前刚体
var joint_j=new cp.SlideJoint(body1,body2,cc.p(0,0),cc.p(0,0),30,50); //将当前刚体和前一个刚体相连
this.space.addConstraint(joint_j); //将节点添加到空间
}
//静态刚体,作为绳子的顶端
var body_up=new cp.StaticBody(1,cp.momentForCircle(1,0,RADIUS,cp.v(0,0))); //注意,这是一个静态刚体
body_up.setPos(cc.p(size.width/2,size.height));
var shape_up=new cp.CircleShape(body_up,Radius,cp.v(0,0));
shape_up.setElasticity(0.5);
shape_up.setFriction(0.5);
this.space.addStaticShape(shape_up); //静态形态
var joint_up=new cp.SlideJoint(body_up,this.List[0],cc.p(0,0),cc.p(0,0),30,50);
this.space.addConstraint(joint_up);
}
update:function(dt){
var timeStep=0.03;
this.space.step(timeStep);
},
onExit:function(){
this._super();
cc.log("onExit");
}