存档

‘chipmunk’ 分类的存档

[cocos2d-js]chipmunk例子(二)

2014年4月10日 没有评论

 

var TAG_SPRITE_BALL = 1;
var TAG_SPRITE_USER = 2;
var TAG_SPRITE_NPC = 3;
var PTM_RATIO = 32;
var GRABABLE_MASK_BIT = 1<<31;
var NOT_GRABABLE_MASK = ~GRABABLE_MASK_BIT;

var MainLayer = cc.Layer.extend({
    _ball:null,
    _man:null,
    _rpc:null,
    _leftGoal:null,
    _rightGoal:null,
    _leftPower:null,
    _rightPower:null,
    _time:0,

    space:null,

    ctor:function () {
        this._super();
        var size = cc.director.getWinSize();




        this._ball = new Ball();
        this._ball.x = size.width / 2;
        this._ball.y = size.height / 2;
        this.addChild(this._ball);


        // 左方向
        var btnLeft = cc.MenuItemImage.create(
            res.btn_left_up,
            res.btn_left_down,
            function () {
                this._man.runLeft();
            }, this);
        btnLeft.x = 50;

        // 右方向
        var btnRight = cc.MenuItemImage.create(
            res.btn_right_up,
            res.btn_right_down,
            function () {
                this._man.runRight();
            }, this);
        btnRight.x = 125;

        // power
        var btnPower = cc.MenuItemImage.create(
            res.btn_power_up,
            res.btn_power_down,
            function () {
                this._man.power();
            }, this);
        btnPower.x = 250;

        // jump
        var btnJump = cc.MenuItemImage.create(
            res.btn_jump_up,
            res.btn_jump_down,
            function () {
                this._man.jump();
            }, this);
        btnJump.x = 330;

        // kick
        var btnKick = cc.MenuItemImage.create(
            res.btn_kick_up,
            res.btn_kick_down,
            function () {
                this._man.kick();
            }, this);
        btnKick.x = 420;

        // 暂停
        var btnPause = cc.MenuItemImage.create(
            "res/pause.png",
            "res/pause2.png",
            function () {
                this.onStop();
            }, this);
        btnPause.x = size.width - 30;
        btnPause.y = size.height - 50;

        var menu = cc.Menu.create(btnLeft, btnRight, btnPower, btnJump, btnKick, btnPause);
        menu.x = 0;
        menu.y = 20;
        this.addChild(menu, 10);





        // 主角
        this._man = new Footballer_cn();
        this._man.flippedX = true;
        this._man.x = 150;
        this._man.y = 50;
        this._man.anchorX = 0.5;
        this._man.anchorY = 0;
        this.addChild(this._man,0,TAG_SPRITE_USER);
        this._npc = new Footballer_br();
        this._npc.x = size.width - 150;
        this._npc.y = 50;
        this._npc.anchorX = 0.5;
        this._npc.anchorY = 0;
        this.addChild(this._npc,0,TAG_SPRITE_NPC);

        // 球门
        this._leftGoal = new Goalpost(true);
        this._leftGoal.x = 0;
        this._leftGoal.y = 50;
        this._leftGoal.anchorX = 0;
        this._leftGoal.anchorY = 0;
        this.addChild(this._leftGoal);

        this._rightGoal = new Goalpost();
        this._rightGoal.x = size.width;
        this._rightGoal.y = 50;
        this._rightGoal.anchorX = 1;
        this._rightGoal.anchorY = 0;
        this.addChild(this._rightGoal);



        // power
        this._leftPower = new PowerProgress(size.width/2-15,size.height-20,1,0.5,this);
        this.addChild(this._leftPower, 10);
        this._rightPower = new PowerProgress(size.width/2+15,size.height-20,0,0.5,this);
        this.addChild(this._rightPower, 10);



        // 系统计划任务,即每帧调用update函数
        this.scheduleUpdate();
        // 自定义计划任务
        this.schedule(this.uiSchedule, 1);

        cc.sys.dumpRoot();
        cc.sys.garbageCollect();

        this.initChipmunk();

        return true;
    },
    onStop:function () {
        this._bStop = !this._bStop;
        if (this._bStop == true) {
            cc.director.pause();
        }
        else {
            cc.director.resume();
        }
    },

    update:function (dt) {
        this.space.step(dt);
    },
    uiSchedule:function () {
        this._time++;
        this._leftPower.showPower();
        this._rightPower.showPower();
    },
    initChipmunk:function() {
        this.space = new cp.Space();
        var sprite =  this.createPhysicsSprite( cc.p(cc.director.getWinSize().width/2 , cc.director.getWinSize().height-50) );
        this.addChild( sprite,100 );

        this.addWalls();
        this.space.gravity = cp.v(0, -100);
    },
    initPhysics:function() {
        var space = this.space ;
        var staticBody = space.staticBody;
        var winSize = cc.director.getWinSize();

        // Walls
        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);
            shape.setFriction(1);
            space.addStaticShape( shape );
        }

        // Gravity
        space.gravity = cp.v(0, -100);
    },
    addWalls:function() {
        // Walls
        var winSize = cc.director.getWinSize();
        var walls = [ new cp.SegmentShape( this.space.staticBody, cp.v(0,0), cp.v(winSize.width,0), 0 ),                // bottom
            new cp.SegmentShape( this.space.staticBody, cp.v(0,winSize.height), cp.v(winSize.width,winSize.height), 0),    // top
            new cp.SegmentShape( this.space.staticBody, cp.v(0,0), cp.v(0,winSize.height), 0),                // left
            new cp.SegmentShape( this.space.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(0.8);
            shape.setFriction(0.1);
            this.space.addStaticShape( shape );
        }
    },
    createPhysicsSprite:function( pos ) {

        var radius = 20;
        var mass = 1;

        var body = new cp.Body(mass, cp.momentForCircle(mass, 0, radius,cp.v(0, 0)));
        body.setPos( pos );
        this.space.addBody( body );
        var shape = new cp.CircleShape(body, radius,cp.v(0, 0)); //new cp.BoxShape( body, 48, 108);
        shape.setElasticity( 1 );
        shape.setFriction( 0.1 );

        this.space.addShape( shape );

        var sprite = cc.PhysicsSprite.create(res.b_ball_01);
        sprite.setBody( body );
        return sprite;
    },
    setupDebugNode:function()
    {
        // debug only
        this._debugNode = cc.PhysicsDebugNode.create( this.space );
        this._debugNode.visible = false ;
        this.addChild( this._debugNode );
    }
});

var MainScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        this.addChild(new GameBackgroundLayer());
        this.addChild(new MainLayer());
    }
});

 

分类: chipmunk, cocos2d, cocos2d-js 标签:

[cocos2d-js]chipmunk例子(一)

2014年4月10日 没有评论

 

initChipmunk:function() {
        this.space = new cp.Space();

        this.setupDebugNode();

        //设置空间内刚体间联系的迭代计算器个数和弹性关系迭代计算器个数.
        //chipmunk使用迭代计算器计算出空间内物体的受力关系.
        //它建立一个大列表存放物体间所有的碰撞,连接等相互影响关系.根据实际情况传递某些相互作用.
        //传递相互作用的数取决于迭代器的个数,每次迭代都使计算结果更精确.
        //如果进行了过多的迭代,虽然物理影响效果会更好,但是这也会消耗过多的cpu处理时间.
        //如果进行的迭代太少,物理模拟效果会不精确,或者使本该静止的物体没能静止下来.
        //使用迭代器的个数在于平衡CPU性能和物理模拟精确度之间权衡.
        this.space.iterations = 60;
        //设置空间的重力向量
        this.space.gravity = cp.v(0, -500);
        // 休眠临界时间
        this.space.sleepTimeThreshold = 0.5;
        this.space.collisionSlop = 0.5;



        this.addFloor();
        this.addWalls();

        var width = 50;
        var height = 60;
        var mass = width * height * 1/1000;
        var rock = this.space.addBody(new cp.Body(mass, cp.momentForBox(mass, width, height)));
        rock.setPos(cp.v(500, 100));
        rock.setAngle(1);
        var shape = this.space.addShape(new cp.BoxShape(rock, width, height));
        shape.setFriction(0.3);
        shape.setElasticity(0.3);


            var radius = 20;
            mass = 3;
            var body = this.space.addBody(new cp.Body(mass, cp.momentForCircle(mass, 0, radius,cp.v(0, 0))));
            body.setPos(cp.v(200, (2 * radius + 5)));
            var circle = this.space.addShape(new cp.CircleShape(body, radius,cp.v(0, 0)));

            circle.setElasticity(0.8);
            circle.setFriction(1);



        var ramp = this.space.addShape(new cp.SegmentShape(this.space.staticBody,cp.v(100, 100),cp.v(300, 200), 10));
        ramp.setElasticity(1); // 弹性
        ramp.setFriction(1); // 摩擦
        ramp.setLayers(NOT_GRABABLE_MASK);

        var sprite = this.createPhysicsSprite(cc.p(400,200));
        this.addChild(sprite);
    },
    addFloor:function() {
        var floor = this.space.addShape(new cp.SegmentShape(this.space.staticBody,cp.v(0, 0),cp.v(640, 0), 0));
        floor.setElasticity(1);
        floor.setFriction(1);
        floor.setLayers(NOT_GRABABLE_MASK);
    },
    addWalls:function() {
        var wall1 = this.space.addShape(new cp.SegmentShape(this.space.staticBody,cp.v(0, 0),cp.v(0, 480), 0));
        wall1.setElasticity(1);
        wall1.setFriction(1);
        wall1.setLayers(NOT_GRABABLE_MASK);

        var wall2 = this.space.addShape(new cp.SegmentShape(this.space.staticBody,cp.v(640, 0),cp.v(640, 480), 0));
        wall2.setElasticity(1);
        wall2.setFriction(1);
        wall2.setLayers(NOT_GRABABLE_MASK);
    },
    createPhysicsSprite:function( pos ) {
        var body = new cp.Body(1, cp.momentForBox(1, 48, 108) );
        body.setPos( pos );
        this.space.addBody( body );
        var shape = new cp.BoxShape( body, 48, 108);
        shape.setElasticity( 0.5 );
        shape.setFriction( 0.5 );
        this.space.addShape( shape );

        var sprite = cc.PhysicsSprite.create(res.b_ball_01);
        sprite.setBody( body );
        return sprite;
    }

 

分类: chipmunk, cocos2d 标签:

PivotJoints with friction and limits in Cocos2d V3 (Chipmunk)

2014年2月2日 没有评论

I try to convert a game which I started with SpriteKit to Cocos2d V3. I have some problems with the physics though. I create a human like playing figure. The limbs are connected via PinJoints in SpriteKit. I recreated that basic functionality via PivotJoints in Chipmunk. That works as expected.

But I need to add some friction to the joints. Right now they just rotate as fast as possible and even more important I need to limit the rotation angle of the joints. As you can imagine, most people can’t rotate their shoulders freely by 360 degrees. ;)

AFAIK I should use ChipmunkRotaryLimitJoint and ChipmunkGearJoint to achieve that. My problem is, that I can’t make it work because I don’t know how to attach them correctly. This is my code right now:

- (CCPhysicsJoint *)createPinJointWithBodyA:(CCPhysicsBody *)bodyA
                                      bodyB:(CCPhysicsBody *)bodyB
                                     anchor:(CGPoint)anchor
                                   friction:(CGFloat)friction
                                 lowerLimit:(CGFloat)lowerLimit
                                 upperLimit:(CGFloat)upperLimit
{

    CCPhysicsJoint *pin = [CCPhysicsJoint 
        connectedPivotJointWithBodyA:bodyA
                               bodyB:bodyB
                             anchorA:anchor];

    ChipmunkRotaryLimitJoint *limitJoint = [ChipmunkRotaryLimitJoint 
        rotaryLimitJointWithBodyA:bodyA.body 
                            bodyB:bodyB.body
                              min:CC_DEGREES_TO_RADIANS(lowerLimit)
                              max:CC_DEGREES_TO_RADIANS(upperLimit)];

    ChipmunkGearJoint *gearJoint = [ChipmunkGearJoint 
        gearJointWithBodyA:bodyA.body
                     bodyB:bodyB.body
                     phase:0.5
                     ratio:0.5];

    return pin;
}

(The values in the gearJoint call are just place holders!)

Does anybody have an idea how this is supposed to work? I found some things via Google, but all tutorials assume, that I use chipmunk in some other environment. Do I have to create my own CCPhysicJoint implementation for these limit and gear joints?

Thanks and best wishes,
Thomas

I think I solved this problem. It turned out I had to create my own CCPhysicsJoint Category that implements the ChipmunkRotaryLimitJoint and a ChipmunkRotaryDampedSpring. It’s not exactly the same but it works good enough for now.

The code looks like this right now:

[CCPhysicsJoint connectedRotaryLimitJointWithBodyA:bodyA
                                             bodyB:bodyB
                                               min:CC_DEGREES_TO_RADIANS(lowerLimit)
                                               max:CC_DEGREES_TO_RADIANS(upperLimit)];

[CCPhysicsJoint connectedDampedRotarySpringWithBodyA:bodyA
                                               bodyB:bodyB
                                           restAngle:0
                                           stiffness:friction *1000.0f
                                             damping:10000.0f];

I just asked if this should be included in the Cocos2D codebase. For the time being, this is the wrapper:

CCPhysicsJoint+THCAdditions.h

//
//  CCPhysicsJoint+THCAdditions.h
//
//  Created by Thomas Hempel on 02.02.14.
//  Copyright (c) 2014 Thomas Hempel. All rights reserved.
//

#import "CCPhysicsBody.h"
#import "CCPhysicsJoint.h"

@interface CCPhysicsJoint (THCAdditions)

+ (CCPhysicsJoint *)connectedRotaryLimitJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max;
+ (CCPhysicsJoint *)connectedGearJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio;
+ (CCPhysicsJoint *)connectedSimpleMotorJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate;
+ (CCPhysicsJoint *)connectedDampedRotarySpringWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:(CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping;

@end

CCPhysicsJoint+THCAdditions.m

//
//  CCPhysicsJoint+THCAdditions.m
//
//  Created by Thomas Hempel on 02.02.14.
//  Copyright (c) 2014 Thomas Hempel. All rights reserved.
//

#import "CCPhysicsJoint+THCAdditions.h"
#import "CCPhysics+ObjectiveChipmunk.h"

// ------------------------------------------------------------------------
#pragma mark - Rotary Limit Joint
// ------------------------------------------------------------------------

@interface CCPhysicsRotaryLimitJoint : CCPhysicsJoint
@end

@implementation CCPhysicsRotaryLimitJoint {
    ChipmunkRotaryLimitJoint *_constraint;
}

- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max
{
    if ((self = [super init])){
        _constraint = [ChipmunkRotaryLimitJoint rotaryLimitJointWithBodyA:bodyA.body
                                                                    bodyB:bodyB.body
                                                                      min:min
                                                                      max:max];
        _constraint.userData = self;
    }
    return self;
}

- (ChipmunkConstraint *)constraint
{
    return _constraint;
}

- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}

@end

// ------------------------------------------------------------------------
#pragma mark - Gear Joint
// ------------------------------------------------------------------------

@interface CCPhysicsGearJoint : CCPhysicsJoint
@end

@implementation CCPhysicsGearJoint {
    ChipmunkGearJoint *_constraint;
}

- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio
{
    if ((self = [super init])){
        _constraint = [ChipmunkGearJoint gearJointWithBodyA:bodyA.body
                                                      bodyB:bodyB.body
                                                      phase:phase
                                                      ratio:ratio];
        _constraint.userData = self;
    }

    return self;
}

- (ChipmunkConstraint *)constraint
{
    return _constraint;
}

- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}

@end

// ------------------------------------------------------------------------
#pragma mark - Simple Motor Joint
// ------------------------------------------------------------------------

@interface CCPhysicsSimpleMotorJoint : CCPhysicsJoint
@end

@implementation CCPhysicsSimpleMotorJoint {
    ChipmunkSimpleMotor *_constraint;
}

- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate
{
    if ((self = [super init])){
        _constraint = [ChipmunkSimpleMotor simpleMotorWithBodyA:bodyA.body
                                                          bodyB:bodyB.body
                                                           rate:rate];
        _constraint.userData = self;
    }

    return self;
}

- (ChipmunkConstraint *)constraint
{
    return _constraint;
}

- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}

@end

// ------------------------------------------------------------------------
#pragma mark - Damped Rotary Spring
// ------------------------------------------------------------------------

@interface CCPhysicsDampedRotarySpring : CCPhysicsJoint
@end

@implementation CCPhysicsDampedRotarySpring {
    ChipmunkDampedRotarySpring *_constraint;
}

- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:    (CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping
{
    if ((self = [super init])){
        _constraint = [ChipmunkDampedRotarySpring dampedRotarySpringWithBodyA:bodyA.body
                                                                        bodyB:bodyB.body
                                                                    restAngle:restAngle
                                                                    stiffness:stiffness
                                                                      damping:damping];
        _constraint.userData = self;
    }

    return self;
}

- (ChipmunkConstraint *)constraint
{
    return _constraint;
}

- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}

@end

// ------------------------------------------------------------------------
#pragma mark - Implementation
// ------------------------------------------------------------------------


@implementation CCPhysicsJoint (THCAdditions)

+ (CCPhysicsJoint *)connectedRotaryLimitJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max
{

    CCPhysicsJoint *joint = [[CCPhysicsRotaryLimitJoint alloc] initWithBodyA:bodyA bodyB:bodyB min:min max:max];
    [bodyA addJoint:joint];
    [bodyB addJoint:joint];

    [bodyA.physicsNode.space smartAdd:joint];

    return joint;
}

+ (CCPhysicsJoint *)connectedGearJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio
{
    CCPhysicsJoint *joint = [[CCPhysicsGearJoint alloc] initWithBodyA:bodyA bodyB:bodyB phase:phase ratio:ratio];

    [bodyA addJoint:joint];
    [bodyB addJoint:joint];

    [bodyA.physicsNode.space smartAdd:joint];

    return joint;
}

+ (CCPhysicsJoint *)connectedSimpleMotorJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate
{
    CCPhysicsJoint *joint = [[CCPhysicsSimpleMotorJoint alloc] initWithBodyA:bodyA bodyB:bodyB rate:rate];

    [bodyA addJoint:joint];
    [bodyB addJoint:joint];

    [bodyA.physicsNode.space smartAdd:joint];

    return joint;
}

+ (CCPhysicsJoint *)connectedDampedRotarySpringWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:(CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping
{
    CCPhysicsJoint *joint = [[CCPhysicsDampedRotarySpring alloc] initWithBodyA:bodyA bodyB:bodyB restAngle:restAngle stiffness:stiffness damping:damping];

    [bodyA addJoint:joint];
    [bodyB addJoint:joint];

    [bodyA.physicsNode.space smartAdd:joint];

    return joint;
}

@end

Best wishes,
Thomas

Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk

2013年11月4日 没有评论

1、   概述

    游戏中模拟真实的世界是个比较麻烦的事情,通常这种事情都是交给物理引擎来做。首屈一指的是Box2D了,它几乎能模拟所有的物理效果。而chipmunk则是个更轻量的引擎,能够满足简单的物理需求,比如最常用的的碰撞检测等。这些引擎在使用的过程中有个令人讨厌的地方,它们参数太多了。通常为了初始化一个简单的场景要写很多代码。在cocos2d-x 3.0版本中,出现了一个新类族——physicals。它将Box2D或者chipmunk做了一层封装,使我们的上层调用有更友好的接口。它通过宏来切换使用哪种物理引擎,目前的版本只有chipmunk的实现,Box2D的实现没有写,所以手动将宏切换的话是不行的。另外,当前版本还是有bug的,下面会提到,先看效果图吧:

Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk

2、 原理分析

    相信大家都对物理引擎的使用有所了解,篇幅有限,一些基本概念就不复述了。如果你曾经用过Box2D或者chipmunk,再使用这套封装,你只会有一种爽到爆的感觉。

    在这个版本中,物理世界的概念被加入到Scene中,即当创建一个场景时,就可以指定这个场景是否使用物理引擎。相对应的,每一个Sprite中也有body的概念。可以直接将body关联到Sprite上。Listener当然也不需要再弄一套东西来监听,只要注册到场景中就可以了。

    不知你听到这个改动有和感想,反正我是震惊了。

    接下来我们动手做一个吧。


3、创建场景

    首先,运行脚本创建一个新工程:testNewPhy,编译运行确保一切正常。 

    找到 CreateScene函数,更改scene的初始化。

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::createWithPhysics();
    scene->getPhysicsWorld()->setDebugDraw(true); //此句仅3.0 alpha0 有效
    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

    更改create,创建一个支持物理的世界,打开debugDraw。两行就可以搞定了。

    打开debugDrawMask,两行就可以搞定了。DrawMask参数可以选择打开绘制哪些部分比如,Joint、Shape等等。    

    接下来,我们要将这个World传到Layer中。所以我们在HelloWorld类中加入一个函数。将这个world存起来。 

//……
	 void setPhyWorld(PhysicsWorld* world){m_world = world;}
private:
	PhysicsWorld* m_world;
}

    同时在creatScene创建layer完成后,将这个值设定上。

 // ……
    auto layer = HelloWorld::create();
    layer->setPhyWorld(scene->getPhysicsWorld());
// ……

    另外,我们更改一下menuItem的响应,来控制debugDraw的绘制:


  此函数已在3.0 alpha1中失效

void HelloWorld::menuCloseCallback(Object* pSender)
{
	if(m_world->isDebugDraw())
	{
		 m_world->setDebugDraw(false);
	}
	else
	{
		m_world->setDebugDraw(true);
	}
}


    使用如下函数

void HelloWorld::menuCloseCallback(Object* pSender)
{
	if(m_world->getDebugDrawMask() != PhysicsWorld::DEBUGDRAW_NONE)
	{
		 m_world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_NONE);
	}
	else
	{
		m_world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
	}

}

    

4、创建边界

    创建了物理世界,还要有东西才行。接下来,我们着手创建一个边界。我们可以方便的使用PhysicalsBody的create方法创建自己想要的物体。 

    在init中进行更改: 

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
   
	auto edgeSp = Sprite::create();
	auto body = PhysicsBody::createEdgeBox(visibleSize,3); //此句仅3.0 alpha0 有效
        auto body = PhysicsBody::createEdgeBox(visibleSize,PHYSICSBODY_MATERIAL_DEFAULT,3);
        edgeSp->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
        edgeSp->setPhysicsBody(body);this->addChild(edgeSp);edgeSp->setTag(0);
        return true;
}

    其中,PHYSICSBODY_MATERIAL_DEFAULT宏表示的是创建的Body的默认材质,3是边线宽度。编译运行我们会看到场景边上有红色的边界。

Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk

5、添加元素

    我们先将点击响应搭建起来,在init中将touchEnable设置为true,重新onTouchesEnd方法:

void HelloWorld::onTouchesEnded(const std::vector<Touch*>& touches, Event *event)
{
	for(auto touch:touches)
	{
		auto location = touch->getLocation();
		addNewSpriteAtPosition(location);
	}
}

    然后我们来实现addNewSpriteAtPosition函数。关联body与sprite从未如此简单,我们只需创建一个body,创建一个sprite然后将body设置为sprite的body即可。 

void HelloWorld::addNewSpriteAtPosition(Point p)
{    
    auto sp = Sprite::create("1.png");
    sp->setTag(1);
    auto body = PhysicsBody::createBox(Size(80, 40));
    sp->setPhysicsBody(body);	
    sp->setPosition(p);
    this->addChild(sp);
}

    在这其中,当前版本的cocos2d-x 3.0有一个小问题。关联的时候,并未将body相应的owner设置为对应的sprite,我们需要修改sprite.cpp中的setPhysicsBody这个函数。增加最后一行。此bug已修复

void Sprite::setPhysicsBody(PhysicsBody* body)
{
    _physicsBody = body;
    _physicsBody->retain();
    _physicsBody->setPosition(getPosition());
    _physicsBody->setRotation(getRotation());
    _physicsBody->_owner = this;
}

     编译运行,我们点击屏幕即可动态创建元素了。

Cocos2d-x 3.0 开发(九)使用Physicals代替Box2D和chipmunk

6、碰撞检测

    碰撞检测的回调是在world中注册函数来实现的。首先我们在HelloWorld中声明一个变量。并重写OnEnter方法。

    碰撞检测的回调是在Scene中注册Listener来实现的。当有碰撞发生时,就会调用对应的Listener。所有的碰撞都使用EventListenerPhysicsContact类。我们可以通过重写它的onContactBegin、onContactPreSolve、onContactPostSolve、onContactSeperate方法来更改它的行为。

    下面函数已失效

//声明
PhysicsContactListener m_listener;

//实现

void HelloWorld::onEnter()
{
	Layer::onEnter();

	m_listener.onContactBegin = [=](const PhysicsContact& contact)
	{
		auto cnt = const_cast<PhysicsContact*>(&contact);

		auto sp = cnt->getShapeA()->getBody()->getOwner();
		int tag = sp->getTag();
		if(tag == 1)
		{
			Texture2D *texture = TextureCache::getInstance()->addImage("2.png");
			sp->setTexture(texture);
		}

		sp = cnt->getShapeB()->getBody()->getOwner();
		tag = sp->getTag();
		if(tag == 1)
		{
			Texture2D *texture = TextureCache::getInstance()->addImage("1.png");
			sp->setTexture(texture);
		}
		return true;
	};
	m_world->registerContactListener(&m_listener);
}

    应使用:

void HelloWorld::onEnter()
{
	Layer::onEnter();
	auto listener = EventListenerPhysicsContact::create();
	listener->onContactBegin = [=](EventCustom* event, const PhysicsContact& contact)
	{
		auto sp = (Sprite*)contact.getShapeA()->getBody()->getNode();
		int tag = sp->getTag();
		if(tag == 1)
		{
			Texture2D *texture = TextureCache::getInstance()->addImage("2.png");
			sp->setTexture(texture);
		}

		sp = (Sprite*)contact.getShapeB()->getBody()->getNode();
		tag = sp->getTag();
		if(tag == 1)
		{
			Texture2D *texture = TextureCache::getInstance()->addImage("1.png");
			sp->setTexture(texture);
		}
		return true;
	};	
	Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener,10); //第二个参数是优先级,10是随意写的
}

    其中,我们将listener的onContactBegin方法重写。并通过shape->body->owner的方式来取到sprite。更改它的显示。最后将listener注册到m_world中。

    编译运行,然后点击menuItem,将debugDrow关闭,即可。

7、总结

    通过创建一个支持Physicals的场景,来创建物理系统。将body创建出来,并调用sprite的setPhysicsBody来为一个sprite设定body。通过PhysicsContactListener来创建一个Listener并通过registerContactListener将其注册,来处理碰撞。

 

    Demo下载:http://download.csdn.net/detail/fansongy/6502401

    Demo 下载(3.0 alpha1版本):http://download.csdn.net/detail/fansongy/6652089

    本篇博客出自阿修罗道,转载请注明出处,禁止用于商业用途http://blog.csdn.net/fansongy/article/details/14142323  


分类: box2D, chipmunk, cocos2d, 未分类 标签: