Cocos2d x 如何在层中访问物理世界

Cocos2d x 如何在层中访问物理世界,cocos2d-x,game-physics,cocos2d-x-3.0,chipmunk,Cocos2d X,Game Physics,Cocos2d X 3.0,Chipmunk,我需要在层中的两个实体之间创建关节。将在物理世界中添加接头。如何访问层中的物理世界?我的JavaScript实现。希望这会有帮助 var space; function initPhysics() { space = new cp.Space(); space.gravity = cp.v(0, -800); space.iterations = 30; space.sleepTimeThreshold = Infinity; space.collisi

我需要在层中的两个实体之间创建关节。将在物理世界中添加接头。如何访问层中的物理世界?

我的JavaScript实现。希望这会有帮助

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);
}
您有四种选择:

1)覆盖层::oneter()或onentertTransitiondFinish() 方法然后从主题访问,如下所示:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
2)创建一个自定义的Layer::createScene()方法,然后像这样从Layer::init()访问:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
3)向控制器添加PhysicsWorld getter方法(包括一些库代码自定义):

首先转到CCDirector.h,然后在NS_CC_BEGIN下添加场景类的前向声明,如下所示:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
然后转到Director类的private部分,添加以下两行:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
然后转到Director类的public部分,添加如下getter方法:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
这是对CCDirector.h文件中所做更改的概述:

// 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
因此,在这之后,我们转到CCScene.cpp,进入一个具有此签名(bool Scene::initWithPhysics())的方法,您将发现一个对PhysicsWorld::construct(this)的调用,该添加正好在该方法之后,调用此行:

_director->_myPhysicsWorld = _physicsWorld;
这应该是我们在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;

    }
};  
现在,只要在任何地方调用Scene::createWithPhysics(),控制器就会获得PhysicsWorld指针的副本,可以使用我们的控制器getWorld()方法随时随地访问该指针!!(因为导演是一个单身汉,你知道)这一切都不会让用户看到“我的物理世界”,这意味着他只能从外部阅读“我的物理世界”

4)创建自己的自定义PhysicsWorld类,因为PhysicsWorld::construct()受到保护,这意味着它可以很容易地继承

// 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;
现在您可以这样使用它:

    Layer::onEnter(){
        Layer::onEnter();
        auto world = _director->getRunningScene()->getPhysicsWorld();
    }
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();
}
NS_CC_BEGIN
class cocos2d::Scene;
private:
cocos2d::PhysicsWorld* _myPhysicsWorld;
friend class Scene;
public:
cocos2d::PhysicsWorld* getWorld() const{
    return _myPhysicsWorld;
};
Layer::init(){

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

    auto world = physicsManager->getWorld();

}
记住,如果你想的话,你甚至可以把它变成一个单例类

编辑:

我忘了提到这里还有一个很好的解决方案: