cocos2dx 3.x使用Box 2 d
5241 ワード
よく知られているcocs 2 dx 3.xにはPhysicsのパッケージがあり、chipmunkとbox 2 dを同時にパッケージしたいのかもしれませんが、なぜchipmunkだけが実現したのかbox 2 dは関係ありません.
最近試してみましたが、chipmunkの問題は多く、PhysicsBodyの速度が十分速い限り、staticBodyやEdgeと衝突しても貫通する可能性があり、貫通していなくてもbodyに速度を設定し続けると、衝突を無視して堂々と着用します.
それからTestCppのbox 2 dに関するコードを見てみると、box 2 dの表現が明らかに良いことがわかりました.
cococos 2 dはcococos 2 d::PhysicsSpriteを実現したが、その実現には問題がある.は、各PhysicsSpriteにおいてDirector::EVENT_AFTER_UPDATEイベントは、Box 2 dワールドとcococosワールドの座標を同期させるが、cococos 2 d::Node::visitで同期 を完全に行うことができる.同期座標では親子ノードの関係はまったく考慮されず、すべてのPhysicsSpriteがSceneに直接接続されている場合にのみ、 が正常に動作する.ゲームシーンにui、main、backgroundなど相対的に変位する階層ノードがある場合、座標同期を行う際の基準ノードはmainノードであるべきであり、box 2 dのdebugモードを描く場合、modelViewマトリクスもmainノード に基づいている必要がある.
だから自分で1つの簡単なbox 2 dに対するパッケージBox 2 dNodeを実現しました:public Node Box 2 d b 2 Worldを初期化し、基準ノードとして設定し、基準ノードリスニングDirector::EVENT_AFTER_UPDATEはb 2 World::Stepを行い、draw時にレンダリングキューにカスタムイベントを挿入してbox 2 dのdebug情報を描画します. Box 2 d b 2 Bodyを作成し、setPositionとsetRotationでcococos座標系をbox 2 d座標系に同期し、visitでbox 2 d座標系をcocos座標系に同期することができます.
キーコードは次のとおりです.
基準ノードb 2 Worldに対してStepを行う
データムノード描画box 2 d debug情報
座標系同期:
最近試してみましたが、chipmunkの問題は多く、PhysicsBodyの速度が十分速い限り、staticBodyやEdgeと衝突しても貫通する可能性があり、貫通していなくてもbodyに速度を設定し続けると、衝突を無視して堂々と着用します.
それからTestCppのbox 2 dに関するコードを見てみると、box 2 dの表現が明らかに良いことがわかりました.
cococos 2 dはcococos 2 d::PhysicsSpriteを実現したが、その実現には問題がある.
だから自分で1つの簡単なbox 2 dに対するパッケージBox 2 dNodeを実現しました:public Node
キーコードは次のとおりです.
基準ノードb 2 Worldに対してStepを行う
void Box2dNode::onEnter()
{
Node::onEnter();
if (m_body)
{
m_body->SetActive(true);
}
if (m_is_box2d_root)
{
// afterUpdate , step box2d
s_after_update_listener = Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_UPDATE, std::bind(&Box2dNode::stepBox2d, this, std::placeholders::_1));
s_after_update_listener->retain();
}
}
void Box2dNode::stepBox2d(EventCustom *event)
{
Director* director = Director::getInstance();
s_world->Step(1 / 60.0f, 1, 1);
}
データムノード描画box 2 d debug情報
void Box2dNode::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags)
{
Node::draw(renderer, transform, flags);
// renderCommand
if (m_is_box2d_root != 0)
{
if (s_draw_command == 0)
{
s_draw_command = new CustomCommand();
}
s_draw_command->init(10, transform, flags);
s_draw_command->func = CC_CALLBACK_0(Box2dNode::onDraw, this, transform, flags);
renderer->addCommand(s_draw_command);
}
}
void Box2dNode::onDraw(const Mat4 &transform, uint32_t flags)
{
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
GL::enableVertexAttribs(cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION);
s_world->DrawDebugData();
CHECK_GL_ERROR_DEBUG();
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
座標系同期:
void Box2dNode::setPosition(float x, float y)
{
if (m_body)
{
_position.x = x;
_position.y = y;
// box2d
Node* parent = this->getParent();
if (parent)
{
AffineTransform mat = getAffineTransformToWorldRoot(parent);
mat = AffineTransformTranslate(mat, x, y);
x = mat.tx;
y = mat.ty;
}
float angle = m_body->GetAngle();
m_body->SetTransform(b2Vec2(x / PTM_RATIO, y / PTM_RATIO), angle);
}
else
{
Node::setPosition(x, y);
}
}
void Box2dNode::setRotation(float fRotation)
{
if (m_body)
{
_rotationZ_X = _rotationZ_Y = fRotation;
updateRotationQuat();
// boxbody
b2Vec2 p = m_body->GetPosition();
float radians = CC_DEGREES_TO_RADIANS(fRotation);
Node* parent = this->getParent();
if (parent)
{
AffineTransform mat = getAffineTransformToWorldRoot(parent);
mat = AffineTransformRotate(mat, radians);
radians = acosf(mat.a);
}
m_body->SetTransform(p, radians);
}
else
{
Node::setRotation(fRotation);
}
}
void Box2dNode::visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
{
// box2d transform
if (m_body)
{
b2Vec2 pos = m_body->GetPosition();
float radians = m_body->GetAngle();
AffineTransform world_xy = AffineTransformTranslate(AffineTransform::IDENTITY, pos.x * PTM_RATIO, pos.y * PTM_RATIO);
AffineTransform world_rot = AffineTransformRotate(AffineTransform::IDENTITY, radians);
AffineTransform world_trans = AffineTransformConcat(world_rot, world_xy);
Node* parent = this->getParent();
if (parent)
{
AffineTransform parent_world = AffineTransformInvert(getAffineTransformToWorldRoot(parent));
AffineTransform local_trans = AffineTransformConcat(world_trans, parent_world);
if (!_anchorPointInPoints.isZero())
{
local_trans = AffineTransformTranslate(local_trans, -_anchorPointInPoints.x, -_anchorPointInPoints.y);
}
_position.x = local_trans.tx;
_position.y = local_trans.ty;
_rotationZ_X = _rotationZ_Y = CC_RADIANS_TO_DEGREES(acosf(local_trans.a));
CGAffineToGL(local_trans, _transform.m);
_transformDirty = false;
_inverseDirty = true;
_transformUpdated = true;
}
}
//---------------------------------------------------------------
Node::visit(renderer, parentTransform, parentFlags);
}