接触cocos2d-x没多久,现在逐渐熟悉这个游戏引擎。开源的最大好处就是可以直接阅读引擎代码来了解一些尚无详细文档或书籍的模块。比如我现在看cocos2d-x封装的physics部分。
cocos2d-x 3.0后自己对物理引擎做了封装,底层物理是chipmunk物理引擎。如果想用Box2d的话,得自己写代码融入cocos2d-x。
以下是阅读3.1版本的源代码做的一些笔记,以后可能也会接着做一些记录。可能并不完善,只是记录一下学习过程中遇到的一些困惑和心得。
今天看到Node::addChild函数中把即将加入的子节点也加入到物理世界中(如果定义了物理世界):
void Node::addChild(Node *child,int zOrder,int tag) { ... // Recursive add children with which have physics body. for (Node* node = this; node != nullptr; node = node->getParent()) { Scene* scene = dynamic_cast<Scene*>(node); if (scene != nullptr && scene->getPhysicsWorld() != nullptr) { scene->addChildToPhysicsWorld(child); break; } } ... }
这样的话,场景类的addChild中也加入物理世界似乎是多余的:
void Scene::addChild(Node* child,int tag) { Node::addChild(child,zOrder,tag); addChildToPhysicsWorld(child); }
另外,从addChildToPhysicsWorld的源码能看到,加入到物理世界的node节点的子节点也会被加入物理世界:
void Scene::addChildToPhysicsWorld(Node* child) { if (_physicsWorld) { std::function<void(Node*)> addToPhysicsWorldFunc = nullptr; addToPhysicsWorldFunc = [this,&addToPhysicsWorldFunc](Node* node) -> void { if (node->getPhysicsBody()) { _physicsWorld->addBody(node->getPhysicsBody()); } auto& children = node->getChildren(); for( const auto &n : children) { addToPhysicsWorldFunc(n); } }; addToPhysicsWorldFunc(child); } }
但是Node::removeChild却只从物理世界移除要移除的子节点,那个要移除的子节点的子节点却没有从物理世界中移除,这感觉是一个bug。记录一下。
void Node::removeChild(Node* child,bool cleanup /* = true */) { // explicit nil handling if (_children.empty()) { return; } ssize_t index = _children.getIndex(child); if( index != CC_INVALID_INDEX ) this->detachChild( child,index,cleanup ); }
void Node::detachChild(Node *child,ssize_t childIndex,bool doCleanup) { ... #if CC_USE_PHYSICS if (child->_physicsBody != nullptr) { child->_physicsBody->removeFromWorld(); } ... }