【问题标题】:How to access Physics World in Layer如何在层中访问物理世界
【发布时间】:2015-02-12 19:38:15
【问题描述】:

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

【问题讨论】:

    标签: cocos2d-x game-physics cocos2d-x-3.0 chipmunk


    【解决方案1】:

    我的 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);
    }
    

    【讨论】:

      【解决方案2】:

      你有四个选择:

      1)- 覆盖 Layer::onEnter() 或 onEnterTransitionDidFinish () 方法然后像这样从主题访问:

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

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

      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)- 为director添加PhysicsWorld getter方法(涉及一些库代码定制):

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

      NS_CC_BEGIN
      class cocos2d::Scene;
      

      然后转到 Director 类的私有部分并像这样添加这两行:

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

      然后转到 Director 类的公共部分并像这样添加这个 getter 方法:

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

      这是对 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()) 中,您会在该方法调用 this 之后找到对 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() 方法访问该指针! (因为如你所知,导演是单身人士)这一切都没有将 _myPhysicsWorld 暴露给用户,这意味着他只能从外部读取 _myPhysicsWorld!

      4)- 制作您自己的 Custom 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::init(){
      
          auto physicsManager = PhysicsManager::createWorld(this->getScene());
      
          auto world = physicsManager->getWorld();
      
      }
      

      请记住,如果您愿意,您甚至可以将其设为单例类!

      编辑:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-21
        • 1970-01-01
        相关资源
        最近更新 更多