cocos2d-x 3.0 alpha 0 chipmunk debug draw

Was wanting to get a quick demo up with cocos2d-x and chipmunk to play around with chipmunk physics and had a bit of train wreck trying to get a debug node to work properly. It’s really not complicated, but hopefully this will keep someone else from stumbling through it like I did. I should’ve kept link to the person that inspired this. It wasn’t completely my idea.

ChipmunkDebugNode.h

//
// desc: ChipmunkDebugNode.h
//

#ifndef _CHIPMUNKDEBUGNODE_H_
#define _CHIPMUNKDEBUGNODE_H_

//
// includes
//
#include "cocos2d.h"
#include "chipmunk.h"

//
// struct ChipmunkDebugNode
//
struct ChipmunkDebugNode : cocos2d::Node
{
    //
    // static methods
    //
    static ChipmunkDebugNode *create(cpSpace *space);
    static void DrawShape(cpShape *shape, void *data);
    
    //
    // init
    //
    virtual bool init(cpSpace *space);
    
    //
    // overload draw
    //
    virtual void draw();
    
    //
    // variables
    //
    cpSpace *_space;
};

#endif // #ifndef _CHIPMUNKDEBUGNODE_H_

ChipmunkDebugNode.cpp

//
// desc: ChipmunkDebugNode.cpp
//

//
// includes
//
#include "ChipmunkDebugNode.h"

// cocos2d namespace
USING_NS_CC;

ChipmunkDebugNode *ChipmunkDebugNode::create(cpSpace *space)
{
    ChipmunkDebugNode *chipmunkDebugNode = new ChipmunkDebugNode();
    if (chipmunkDebugNode && chipmunkDebugNode->init(space)) {
        chipmunkDebugNode->autorelease();
        return chipmunkDebugNode;
    }
    
    // else cleanup
    delete chipmunkDebugNode;
    return NULL;
}

void ChipmunkDebugNode::DrawShape(cpShape* shape, void *data)
{
    if (!shape) {
        return;
    }
    
    glLineWidth(5.0f);
    DrawPrimitives::setDrawColor4F(0.5f, 0.5f, 0.5f, 1.0f);
    
    if (shape->klass_private->type == CP_CIRCLE_SHAPE) {
        cpCircleShape *circle = (cpCircleShape *)shape;
        cpVect center = cpvadd(shape->body->p, cpvrotate(circle->c, shape->body->rot));
        DrawPrimitives::drawCircle(Point(center.x, center.y), circle->r, shape->body->a, 20, true);
        return;
    }
    
    if (shape->klass_private->type == CP_POLY_SHAPE) {
        cpPolyShape *poly = (cpPolyShape *)shape;
        
        // convert chipmunk points to coco points
        Point *pointArray = new Point[poly->numVerts];
        for (int i=0; i < poly->numVerts; i++) {
            pointArray[i] = Point(poly->tVerts[i].x, poly->tVerts[i].y);
        }
        
        DrawPrimitives::drawPoly(pointArray, poly->numVerts, true);
        delete pointArray;
        return;
    }
    
    if (shape->klass_private->type == CP_SEGMENT_SHAPE) {
        cpSegmentShape* segment = (cpSegmentShape*)shape;
        DrawPrimitives::drawLine(Point(segment->ta.x, segment->ta.y),
                                 Point(segment->tb.x, segment->tb.y));
        return;
    }
    
    cpSegmentShape *segment = (cpSegmentShape *)shape;
    DrawPrimitives::drawLine(Point(segment->ta.x, segment->ta.y),
                             Point(segment->tb.x, segment->tb.y));
}

//
// descP init
//
bool ChipmunkDebugNode::init(cpSpace *space)
{
    if (!Node::init()) {
        return false;
    }
    
    // init variables
    _space = space;
    
    return true;
}

//
// desc: override draw
//
void ChipmunkDebugNode::draw()
{
    cpSpaceEachShape(_space, &DrawShape, this);
}

And for completeness, here is example of using it inside my root layer. Should all be pretty straight forward once you see it.

// setup chimpunk stuff
cpSpace *space = cpSpaceNew();
cpSpaceSetGravity(space, cpv(0.0f, -1.0f));

cpBody *body = cpBodyNew(100.0f, INFINITY);
cpShape *shape = cpCircleShapeNew(body, 30.0f, cpvzero);

body->p = cpv(visibleSize.width / 2.0f, visibleSize.height / 2.0f);

cpSpaceAddBody(space, body);
cpSpaceAddShape(space, shape);

// create and add chipmunk debug node
this->addChild(ChipmunkDebugNode::create(space));