Chipmunk引擎在Cocos2d-js中的使用

本文详细介绍了如何在Cocos2d-js项目中集成并使用Chipmunk物理引擎,包括空间(space)、物体(body)、形状(shape)和关节(joint)的创建与操作。同时,重点讲解了在持续碰撞和物体分开时的事件监听及处理机制,为实现动态交互场景提供了关键支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Chipmunk是一个开源的物理引擎,最近想做一个动作Html5游戏,需要用到物理引擎,所以找来学了下。

Chipmunk的核心概念:
  1. 空间(space)
  2. 物体(body)
  3. 形状(shape)
  4. 关节(joint)
一般来说,使用该引擎的流程如下:




接下来介绍Chipmunk在Cocos2d-js中的使用。

Cocos2d-js中自带了Chipmunk,但是如果要使用还得在project.json中的"modules"配置中添加模块声明:
"modules" : ["cocos2d""external"]
"external" 模块包含了chipmunk等子模块

首先,在Layer对象的构造函数ctor中新建space对象,并且为之添加边界:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  var winSize = cc.director.getWinSize();
 
        this.space = new cp.Space(); //以cp开头的对象表明其是chipmunk的类
        this._debugNode = new cc.PhysicsDebugNode(this.space);
        this._debugNode.visible = true;//是否开启debug模式,开启后会显示遮罩和关节等
        this.addChild(this._debugNode);
         
        this.space.gravity = cp.v(0, -100);
//设置space这个空间的重力,cp.v用来表示一个二维矢量,这里表示x轴重力为0,y为-100
        var staticBody = this.space.staticBody;
 
        // 设置边界
        //cp.SegmentShape()用来为space设置边界,后三个参数分别为边界起点、终点以及边界宽度
        var walls = [ new cp.SegmentShape(staticBody, cp.v(0, 0), cp.v(winSize.width, 0), 0),            // bottom
            new cp.SegmentShape(staticBody, cp.v(0, winSize.height), cp.v(winSize.width, winSize.height), 0),// top
            new cp.SegmentShape(staticBody, cp.v(0, 0), cp.v(0, winSize.height), 0),             // left
            new cp.SegmentShape(staticBody, cp.v(winSize.width, 0), cp.v(winSize.width, winSize.height), 0)  // right
        ];
        for (var i = 0; i < walls.length; i++) {
            var shape = walls[i];
            shape.setElasticity(1);//设置弹性为1
            shape.setFriction(1);//设置摩擦力为1
            this.space.addStaticShape(shape);
        }
space对象的边界也是shape+body对象,只不过是静态的,不可动。

然后在space中添加body:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        var body = new cp.Body(1, cp.momentForBox(1, SPRITE_WIDTH, SPRITE_HEIGHT));
        //cp.Body()有两个参数,第一个为质量,第二个为惯性值,通过cp.momentForBox()得到
        //cp.momentForBox()得到一个长方形的惯性值,第一个参数为“惯性力矩”一般设为1,后面两个参数为长方形body的宽和高
        body.setPos(p);
        //设置body的重心,p为cc.p对象
        this.space.addBody(body);
      
  //新建一个shape对象需要传入一个body对象作为参数,该body对象就是shape要与之绑定的对象
        var shape = new cp.BoxShape(body, SPRITE_WIDTH, SPRITE_HEIGHT);
        shape.setElasticity(0.5);
        shape.setFriction(0.5);
        this.space.addShape(shape);
  //创建物理引擎精灵对象
        var sprite = new cc.PhysicsSprite("res/BoxA2.png");
        sprite.setBody(body);//sprite与body绑定
        sprite.setPosition(cc.p(p.x, p.y));
        this.addChild(sprite);
body.data = sprite; //这样设置之后可以通过body.data来得到绑定的sprite

我将body、 shape、 sprite三者的关系理解为 :body是一个物体的内在属性,比如质量多大,运动起来的惯性是怎样的,shape则是一个物体的外在属性,比如是圆的还是方的,表面是光滑还是粗糙(摩擦力),物体与之相撞后的弹力等。像边界这样 不动 的staticBody,不用设置其质量、惯性,直接由this.space.staticBody得到就可以。sprite就是一个物体看起来的样子,哪怕sprite的图片是个方的,只要与之绑定的shape是圆的,它还是可以滚起来。


为物体添加关节:
关节(joint)是一条线段,将两个物体连在一起,物体围绕两个端点可以转动。

this.space.addConstraint(new cp.PinJoint(body1, body2, cp.v(0,0), cp.v(0, SPRITE_WIDTH / 2)));

该方法可以为两个物体(body1,body2)添加关节。cp.PinJoint()方法的后两个参数为关节在body1和body2里面连接点的坐标,它是模型坐标


在上述步骤之后,便完成了对物体和空间的初始化。接下来需要调用this.scheduleUpdate()来开启动画。并且在其回调函数update()中设置绘制间隔:
1
2
3
4
    update: function () {
        var period = 0.05;
        this.space.step(period);
    }


到此为止,space中的物体后便会发生相撞后反弹、下落等动作,但如果需要两个物体相撞后执行一些方法,则需设置碰撞检测。

设置碰撞检测:
1
2
3
4
5
6
        this.space.addCollisionHandler(COLLISION_TYPE, COLLISION_TYPE,
                this.collisionBegin.bind(this),
                this.collisionPre.bind(this),
                this.collisionPost.bind(this),
                this.collisionSeparate.bind(this)
        );


.addCollisionHandler()方法有6个参数。前两个为两个碰撞物体碰撞类型,碰撞类型是一个整数,只有物体的碰撞类型与碰撞检测中设置的碰撞类型相等时碰撞才能发生。后面四个参数为四个回调方法,它们执行的时机分别是:
  1. 物体第一次相撞时触发,只能触发一次,该方法返回一个布尔值,若为true,则可触发后面的方法
  2. 持续碰撞时触发,可反复触发,该方法返回一个布尔值,若为true,则可触发方法第三个方法
  3. 也是持续碰撞时触发,但仅当第二个方法返回true时才执行
  4. 物体分开时触发,只能触发一次

此外 还需要为物体的shape设置碰撞检测类型: shape.setCollisionType(COLLISION_TYPE);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值