How to access Physics World in Layer

拟墨画扇 提交于 2019-12-13 01:29:27

问题


I need to create joint between two bodies in layer. Joints are to be added in physics world. How can i access physics world in layer?


回答1:


My JavaScript implementation. Hope it will help.

var space;

function initPhysics() {
    space = new cp.Space();
    space.gravity = cp.v(0, -800);
    space.iterations = 30;
    space.sleepTimeThreshold = Infinity;
    space.collisionSlop = Infinity;
}

function addJoints() {
    chainTableJoint1 = new cp.PivotJoint(chainEnd1, tableBackBody, cp.v.add(cp.v(chainEnd1.getPos().x, tableBackNode.getPosition().y + (tableBackNode.getContentSize().height * 0.5)), boxOffset));
    chainTableJoint2 = new cp.PivotJoint(chainEnd2, tableBackBody, cp.v.add(cp.v(chainEnd2.getPos().x, tableBackNode.getPosition().y + (tableBackNode.getContentSize().height * 0.5)), boxOffset));

    space.addConstraint(chainTableJoint1);
    space.addConstraint(chainTableJoint2);
}



回答2:


you have four options:

1)- override Layer::onEnter() or onEnterTransitionDidFinish () methods then access from theme like this:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }

2)- create a custom Layer::createScene() method then access from Layer::init() like this:

Scene* GameScene::createScene()
{
    auto layer = new (std::nothrow) GameScene;
    if (layer)
    {
        auto scene = Scene::createWithPhysics();
        layer->autorelease();
        scene->addChild(layer);
        if (layer->init()) return scene;
    }
    CC_SAFE_DELETE(layer);
    return nullptr;
}

// then in Layer::init() you do this:

Layer::init(){
    auto world = _director->getRunningScene()->getPhysicsWorld();
}

3)- add a PhysicsWorld getter method to the director (involves some library code customization's):

first go to CCDirector.h and then add a forward declaration of the scene class under NS_CC_BEGIN like this:

NS_CC_BEGIN
class cocos2d::Scene;

then go to the private section of the Director class and add these two lines like this:

private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;

then go to the public section of the Director class and add this getter method like this:

public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};

this is an overview of the changes made in CCDirector.h file:

// CCDirector.h
NS_CC_BEGIN

// 1
class cocos2d::Scene;

class Director : public Ref{

public:
    //2
    cocos2d::PhysicsWorld* getWorld() const{
        return _myPhysicsWorld;
    };
private:
    // 3
    cocos2d::PhysicsWorld* _myPhysicsWorld;
    friend class cocos2d::Scene;
};

NS_CC_END

so after that we go to CCScene.cpp into a method with this signature (bool Scene::initWithPhysics()) in it you will find a call to PhysicsWorld::construct(this) add just right after that method call this line:

_director->_myPhysicsWorld = _physicsWorld;

and this should be the overview of what we did in CCScene.cpp:

// CCScene.cpp
class Scene : public Node{

    bool Scene::initWithPhysics(){

         _physicsWorld = PhysicsWorld::construct(this);
         // 4 since Director is a singleton class, we can access its instance from anywhere
        _director->_myPhysicsWorld = _physicsWorld;

    }
};  

now as soon as Scene::createWithPhysics() gets called anywhere the director will get a copy of the PhysicsWorld pointer which can be accessed using our director getWorld() method anywhere anytime!! (because the director is a singleton as you know) and thats all without exposing _myPhysicsWorld to the user meaning he can only read _myPhysicsWorld from the outside!!

4)- make your own Custom PhysicsWorld class and since PhysicsWorld::construct() is protected which means it can be easily inherited.

// PhysicsManager.h

class PhysicsManager : public cocos2d::PhysicsWorld
{
public:

    static PhysicsManager* createWorld(cocos2d::Scene* scene) {
        _myPhysicsWorld = PhysicsWorld::construct(scene);
    }

    PhysicsWorld* getWorld() const { return _myPhysicsWorld; }

private:
    static cocos2d::PhysicsWorld* _myPhysicsWorld;
};

//PhysicsManager.cpp

PhysicsManager::PhysicsWorld* _myPhysicsWorld;

now you can use it like this:

Layer::init(){

    auto physicsManager = PhysicsManager::createWorld(this->getScene());

    auto world = physicsManager->getWorld();

}

remember that you can even make it a singleton class if you want to!

Edit:

I forgot to mention that there is another good solution in here:

http://discuss.cocos2d-x.org/t/physics-joint-distance-problem/17926/2



来源:https://stackoverflow.com/questions/28486310/how-to-access-physics-world-in-layer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!