Box2d debug draw in coco2d-x v4.0

Hi friends,
I’m using coco2d-x v4.0 and box2d in c++ and developing for android via android studio. Anyone know how I can view exactly the box that box2d is drawing?.
The following files have deprecated functions and classes that do not work with cocos2d-x v4.0
#include “GLES-Render.h”
#include “GLES-Render.h”

I don’t feel that v4 has a ton of value for those developing on Android. Have you considered 3.17.2? Are you also developing for iOS?

i plan to develop for iOS next month. So should i switch back to 3.17.2?

My advice is to get everything working on 3.17.2 for android and ios. This process works, tried and true.

If then you want to take a copy of your project and upgrade to v4 for iOS Metal rendering then work at that. This also give time for more bug fixes in v4.

I guess this will inform all those who were in my condition. Thanks alot.

This is my opinion. Our developers are working on so many aspects of v4 and Creator development. There is a great deal of overlap these days with features that need to go into both platforms.

I’ve re-implemented Box2D debug drawing using DrawNode, so now it will work with both V3 and V4 of Cocos2d-x. The main source files are Box2dDebugDraw.h and Box2dDebugDraw.cpp.

Box2dDebugDraw.h:

#pragma once

#include "Box2D/Box2D.h"
#include "cocos2d.h"

class CcxBox2dDebugDraw : public b2Draw
{
public:
    CcxBox2dDebugDraw();
    CcxBox2dDebugDraw(float32 ratio);
    virtual ~CcxBox2dDebugDraw();

    void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color) override;
    void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color) override;
    void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) override;
    void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) override;
    void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override;
    void DrawTransform(const b2Transform& xf) override;
    void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color) override;

    void setRatio(float32 ratio) { _ratio = ratio; }

    cocos2d::DrawNode* GetDrawNode() const { return _drawNode; }

protected:
    float32 _ratio;

    cocos2d::DrawNode* _drawNode = nullptr;
};

Box2DDebugDraw.cpp:

#include "Box2DDebugDraw.h"
#include "cocos2d.h"

USING_NS_CC;

CcxBox2dDebugDraw::CcxBox2dDebugDraw()
    : CcxBox2dDebugDraw(1.0f)
{
}

CcxBox2dDebugDraw::CcxBox2dDebugDraw(float32 ratio)
    : _ratio(ratio)
{
    _drawNode = DrawNode::create();
    _drawNode->retain();
    _drawNode->setGlobalZOrder(10000);
}

CcxBox2dDebugDraw::~CcxBox2dDebugDraw()
{
    _drawNode->removeFromParent();
    CC_SAFE_RELEASE(_drawNode);
}

void CcxBox2dDebugDraw::DrawPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    const auto vertices = new Vec2[vertexCount];
    for (int i = 0; i < vertexCount; i++)
    {
        vertices[i] = Vec2((old_vertices[i].x * _ratio), (old_vertices[i].y * _ratio));
    }
    _drawNode->drawPoly(vertices, vertexCount, true, Color4F(color.r, color.g, color.b, color.a));
    delete[] vertices;
}

void CcxBox2dDebugDraw::DrawSolidPolygon(const b2Vec2* old_vertices, int vertexCount, const b2Color& color)
{
    const auto vertices = new Vec2[vertexCount];
    for (int i = 0; i < vertexCount; i++) 
    {
        vertices[i] = Vec2((old_vertices[i].x * _ratio), (old_vertices[i].y * _ratio));
    }
    _drawNode->drawSolidPoly(vertices, vertexCount, Color4F(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 0.2f));
    _drawNode->drawPoly(vertices, vertexCount, true, Color4F(color.r, color.g, color.b, 1));
    delete[] vertices;
}

void CcxBox2dDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
    const auto pos = Vec2((center.x * _ratio), (center.y * _ratio));
    _drawNode->drawCircle(pos, radius * _ratio, 0, 16, false, Color4F(color.r, color.g, color.b, 1));
}

void CcxBox2dDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
    const auto pos = Vec2((center.x * _ratio), (center.y * _ratio));
    // Draw filled circle
    _drawNode->drawSolidCircle(pos, radius * _ratio, 0, 16, Color4F(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 0.2f));
    // Draw edge of circle
    _drawNode->drawCircle(pos, radius * _ratio, 0, 16, false, Color4F(color.r, color.g, color.b, 1));

    // Draw the axis line
    DrawSegment(center, center + radius * axis, color);
}

void CcxBox2dDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
    const auto pos1 = Vec2((p1.x * _ratio), (p1.y * _ratio));
    const auto pos2 = Vec2((p2.x * _ratio), (p2.y * _ratio));

    _drawNode->drawSegment(pos1, pos2, 1, Color4F(color.r, color.g, color.b, 1));
}

void CcxBox2dDebugDraw::DrawTransform(const b2Transform& xf)
{
    b2Vec2 p1 = xf.p, p2;
    const float32 k_axisScale = 0.4f;
    p2 = p1 + k_axisScale * xf.q.GetXAxis();
    DrawSegment(p1, p2, b2Color(1, 0, 0));

    p2 = p1 + k_axisScale * xf.q.GetYAxis();
    DrawSegment(p1, p2, b2Color(0, 1, 0));
}

void CcxBox2dDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
    const auto pos1 = Vec2((p.x * _ratio), (p.y * _ratio));
    _drawNode->drawPoint(pos1, 1.f, Color4F(color.r, color.g, color.b, 1));
}

Example of usage:

b2WorldNode::~b2WorldNode()
{
#if (CC_BOX2D_DEBUG)
    _debugDrawInst = nullptr;
#endif
}

bool b2WorldNode::init()
{
#if (CC_BOX2D_DEBUG)
    _debugDrawInst = std::make_unique<CcxBox2dDebugDraw>(getPTM());

    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    flags += b2Draw::e_jointBit;
    flags += b2Draw::e_aabbBit;
    flags += b2Draw::e_pairBit;
    flags += b2Draw::e_centerOfMassBit;
    _debugDrawInst->SetFlags(flags);

    getb2World()->SetDebugDraw(_debugDrawInst.get());
#endif

    return true;
}


#if (CC_BOX2D_DEBUG)
void b2WorldNode::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t parentFlags)
{
    Node::draw(renderer, transform, parentFlags);

    auto director = Director::getInstance();
    director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);

    _debugDrawInst->GetDrawNode()->clear();
    getb2World()->DrawDebugData();
    _debugDrawInst->GetDrawNode()->draw(renderer, transform, parentFlags);
    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}

#endif

and in b2WorldNode.h:

#if (CC_BOX2D_DEBUG)
    void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4& parentTransform, uint32_t parentFlags) override;
#endif	

#if (CC_BOX2D_DEBUG)
    std::unique_ptr<CcxBox2dDebugDraw> _debugDrawInst = nullptr;
#endif

The b2WorldNode is a subclass of cocos2d::Node, and just handles a reference to b2World in order to update the physics engine.

7 Likes