code:
#include "BugsTest.h"
#include "Bug-350.h"
#include "Bug-422.h"
#include "Bug-458/Bug-458.h"
#include "Bug-624.h"
#include "Bug-886.h"
#include "Bug-899.h"
#include "Bug-914.h"
#include "Bug-1159.h"
#include "Bug-1174.h"

#define TEST_BUG(bugNO)                                 \
{                                                       \
CCScene* pScene = CCScene::node();                      \
Bug##bugNO##Layer* pLayer = new Bug##bugNO##Layer();    \
pLayer->init();                                         \
pScene->addChild(pLayer);                               \
CCDirector::sharedDirector()->replaceScene(pScene);     \
pLayer->autorelease();                                  \
}

enum
{
    MAX_COUNT = 9,
    LINE_SPACE = 40,
    kItemTagBasic = 5432,
};

static CCPoint s_tCurPos = CCPointZero;

const std::string testsName[MAX_COUNT] =
{
    "Bug-350",
    "Bug-422",
    "Bug-458",
    "Bug-624",
    "Bug-886",
    "Bug-899",
    "Bug-914",
    "Bug-1159",
    "Bug-1174"
};

////////////////////////////////////////////////////////
//
// BugsTestMainLayer
//
////////////////////////////////////////////////////////
void BugsTestMainLayer::onEnter()
{
    CCLayer::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();
    m_pItmeMenu = CCMenu::menuWithItems(NULL);
    CCMenuItemFont::setFontName("Arial");
    CCMenuItemFont::setFontSize(24);
    for (int i = 0; i < MAX_COUNT; ++i)
    {
        CCMenuItemFont* pItem = CCMenuItemFont::itemFromString(testsName[i].c_str(), this,
                                                    menu_selector(BugsTestMainLayer::menuCallback));
        pItem->setPosition(ccp(s.width / 2, s.height - (i + 1) * LINE_SPACE));
        m_pItmeMenu->addChild(pItem, kItemTagBasic + i);
    }

    m_pItmeMenu->setPosition(s_tCurPos);
    addChild(m_pItmeMenu);
    setIsTouchEnabled(true);
}

void BugsTestMainLayer::menuCallback(CCObject* pSender)
{
    CCMenuItemFont* pItem = (CCMenuItemFont*)pSender;
    int nIndex = pItem->getZOrder() - kItemTagBasic;

    switch (nIndex)
    {
    case 0:
        TEST_BUG(350);
        break;
    case 1:
        TEST_BUG(422);
        break;
    case 2:
        TEST_BUG(458);
        break;
    case 3:
        TEST_BUG(624);
        break;
    case 4:
        TEST_BUG(886);
        break;
    case 5:
        TEST_BUG(899);
        break;
    case 6:
        TEST_BUG(914);
        break;
    case 7:
        TEST_BUG(1159);
        break;
    case 8:
        TEST_BUG(1174);
        break;
    default:
        break;
    }
}

void BugsTestMainLayer::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);

    m_tBeginPos = touch->locationInView();
    m_tBeginPos = CCDirector::sharedDirector()->convertToGL( m_tBeginPos );
}

void BugsTestMainLayer::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);

    CCPoint touchLocation = touch->locationInView();
    touchLocation = CCDirector::sharedDirector()->convertToGL( touchLocation );
    float nMoveY = touchLocation.y - m_tBeginPos.y;

    CCPoint curPos  = m_pItmeMenu->getPosition();
    CCPoint nextPos = ccp(curPos.x, curPos.y + nMoveY);
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    if (nextPos.y < 0.0f)
    {
        m_pItmeMenu->setPosition(CCPointZero);
        return;
    }

    if (nextPos.y > ((MAX_COUNT + 1)* LINE_SPACE - winSize.height))
    {
        m_pItmeMenu->setPosition(ccp(0, ((MAX_COUNT + 1)* LINE_SPACE - winSize.height)));
        return;
    }

    m_pItmeMenu->setPosition(nextPos);
    m_tBeginPos = touchLocation;
    s_tCurPos   = nextPos;
}

////////////////////////////////////////////////////////
//
// BugsTestBaseLayer
//
////////////////////////////////////////////////////////
void BugsTestBaseLayer::onEnter()
{
    CCLayer::onEnter();

    CCSize s = CCDirector::sharedDirector()->getWinSize();

    CCMenuItemFont::setFontName("Arial");
    CCMenuItemFont::setFontSize(24);
    CCMenuItemFont* pMainItem = CCMenuItemFont::itemFromString("Back", this,
        menu_selector(BugsTestBaseLayer::backCallback));
    pMainItem->setPosition(ccp(s.width - 50, 25));
    CCMenu* pMenu = CCMenu::menuWithItems(pMainItem, NULL);
    pMenu->setPosition( CCPointZero );
    addChild(pMenu);
}

void BugsTestBaseLayer::backCallback(CCObject* pSender)
{
    CCDirector::sharedDirector()->enableRetinaDisplay(false);
    BugsTestScene* pScene = new BugsTestScene();
    pScene->runThisTest();
    pScene->autorelease();
}

////////////////////////////////////////////////////////
//
// BugsTestScene
//
////////////////////////////////////////////////////////
void BugsTestScene::runThisTest()
{
    CCLayer* pLayer = new BugsTestMainLayer();
    addChild(pLayer);
    pLayer->release();

    CCDirector::sharedDirector()->replaceScene(this);
}


code:
#ifndef __BUGS_TEST_H__
#define __BUGS_TEST_H__

#include "../testBasic.h"

class BugsTestMainLayer : public CCLayer
{
public:
    virtual void onEnter();
    void menuCallback(CCObject* pSender);

    virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);
    virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);

protected:
    CCPoint m_tBeginPos;
    CCMenu* m_pItmeMenu;
};

class BugsTestBaseLayer : public CCLayer
{
public:
    virtual void onEnter();
    void backCallback(CCObject* pSender);
};

class BugsTestScene : public TestScene
{
public:
    virtual void runThisTest();
};

#endif

license: mit


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

static void
update(int ticks)
{
	int steps = 3;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static void
add_box()
{
	const cpFloat size = 10.0f;
	const cpFloat mass = 1.0f;

	cpVect verts[] = {
		cpv(-size,-size),
		cpv(-size, size),
		cpv( size, size),
		cpv( size,-size),
	};

	cpFloat radius = cpvlength(cpv(size, size));

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts, cpvzero)));
	body->p = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius));
	body->v = cpvmult(cpv(2*frand() - 1, 2*frand() - 1), 200);

	cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 4, verts, cpvzero));
	shape->e = 1.0f; shape->u = 0.0f;
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	cpSpaceResizeActiveHash(space, 30.0f, 1000);
	space->iterations = 10;

	cpBody *body, *staticBody = &space->staticBody;
	cpShape *shape;

	// Create segments around the edge of the screen.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	for(int i=0; i<10; i++)
		add_box();

	body = cpSpaceAddBody(space, cpBodyNew(100.0f, 10000.0f));

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpv(-75,0), cpv(75,0), 5.0f));
	shape->e = 1.0f; shape->u = 1.0f;

	cpSpaceAddConstraint(space, cpPivotJointNew2(body, staticBody, cpvzero, cpvzero));

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Bounce = {
	"Bounce",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

struct chipmunkDemo;

typedef cpSpace *(*demoInitFunc)(void);
typedef void (*demoUpdateFunc)(int ticks);
typedef void (*demoDestroyFunc)(void);

typedef struct chipmunkDemo {
	const char *name;

	drawSpaceOptions *drawOptions;

	demoInitFunc initFunc;
	demoUpdateFunc updateFunc;
	demoDestroyFunc destroyFunc;
} chipmunkDemo;

static inline cpFloat
frand(void)
{
	return (cpFloat)rand()/(cpFloat)RAND_MAX;
}

extern cpVect arrowDirection;
extern char messageString[1024];

#define GRABABLE_MASK_BIT (1<<31)
#define NOT_GRABABLE_MASK (~GRABABLE_MASK_BIT)


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

static cpBody *
addBall(cpVect pos, cpVect boxOffset)
{
	cpFloat radius = 15.0f;
	cpFloat mass = 1.0f;
	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
	body->p = cpvadd(pos, boxOffset);

	cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	shape->e = 0.0f; shape->u = 0.7f;

	return body;
}

static cpBody *
addLever(cpVect pos, cpVect boxOffset)
{
	cpFloat mass = 1.0f;
	cpVect a = cpv(0,  15);
	cpVect b = cpv(0, -15);

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
	body->p = cpvadd(pos, cpvadd(boxOffset, cpv(0, -15)));

	cpShape *shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 5.0f));
	shape->e = 0.0f; shape->u = 0.7f;

	return body;
}

static cpBody *
addBar(cpVect pos, cpVect boxOffset)
{
	cpFloat mass = 2.0f;
	cpVect a = cpv(0,  30);
	cpVect b = cpv(0, -30);

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
	body->p = cpvadd(pos, boxOffset);

	cpShape *shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 5.0f));
	shape->e = 0.0f; shape->u = 0.7f;

	return body;
}

static cpBody *
addWheel(cpVect pos, cpVect boxOffset)
{
	cpFloat radius = 15.0f;
	cpFloat mass = 1.0f;
	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)));
	body->p = cpvadd(pos, boxOffset);

	cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	shape->e = 0.0f; shape->u = 0.7f;
	shape->group = 1; // use a group to keep the car parts from colliding

	return body;
}

static cpBody *
addChassis(cpVect pos, cpVect boxOffset)
{
	int num = 4;
	cpVect verts[] = {
		cpv(-40,-15),
		cpv(-40, 15),
		cpv( 40, 15),
		cpv( 40,-15),
	};

	cpFloat mass = 5.0f;
	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, num, verts, cpvzero)));
	body->p = cpvadd(pos, boxOffset);

	cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
	shape->e = 0.0f; shape->u = 0.7f;
	shape->group = 1; // use a group to keep the car parts from colliding

	return body;
}

static cpSpace *
init(void)
{
	space = cpSpaceNew();
	space->iterations = 10;
	space->gravity = cpv(0, -100);
	space->sleepTimeThreshold = 0.5f;

	cpBody *staticBody = &space->staticBody;
	cpShape *shape;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,120), cpv(320,120), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,0), cpv(320,0), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-120), cpv(320,-120), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160,-240), cpv(-160,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(0,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(160,-240), cpv(160,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	cpVect boxOffset;
	cpBody *body1, *body2;

	cpVect posA = cpv( 50, 60);
	cpVect posB = cpv(110, 60);

	#define POS_A cpvadd(boxOffset, posA)
	#define POS_B cpvadd(boxOffset, posB)

	// Pin Joints - Link shapes with a solid bar or pin.
	// Keeps the anchor points the same distance apart from when the joint was created.
	boxOffset = cpv(-320, -240);
	body1 = addBall(posA, boxOffset);
	body2 = addBall(posB, boxOffset);
	cpSpaceAddConstraint(space, cpPinJointNew(body1, body2, cpv(15,0), cpv(-15,0)));

	// Slide Joints - Like pin joints but with a min/max distance.
	// Can be used for a cheap approximation of a rope.
	boxOffset = cpv(-160, -240);
	body1 = addBall(posA, boxOffset);
	body2 = addBall(posB, boxOffset);
	cpSpaceAddConstraint(space, cpSlideJointNew(body1, body2, cpv(15,0), cpv(-15,0), 20.0f, 40.0f));

	// Pivot Joints - Holds the two anchor points together. Like a swivel.
	boxOffset = cpv(0, -240);
	body1 = addBall(posA, boxOffset);
	body2 = addBall(posB, boxOffset);
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, body2, cpvadd(boxOffset, cpv(80,60))));
	// cpPivotJointNew() takes it's anchor parameter in world coordinates. The anchors are calculated from that
	// cpPivotJointNew2() lets you specify the two anchor points explicitly

	// Groove Joints - Like a pivot joint, but one of the anchors is a line segment that the pivot can slide in
	boxOffset = cpv(160, -240);
	body1 = addBall(posA, boxOffset);
	body2 = addBall(posB, boxOffset);
	cpSpaceAddConstraint(space, cpGrooveJointNew(body1, body2, cpv(30,30), cpv(30,-30), cpv(-30,0)));

	// Damped Springs
	boxOffset = cpv(-320, -120);
	body1 = addBall(posA, boxOffset);
	body2 = addBall(posB, boxOffset);
	cpSpaceAddConstraint(space, cpDampedSpringNew(body1, body2, cpv(15,0), cpv(-15,0), 20.0f, 5.0f, 0.3f));

	// Damped Rotary Springs
	boxOffset = cpv(-160, -120);
	body1 = addBar(posA, boxOffset);
	body2 = addBar(posB, boxOffset);
	// Add some pin joints to hold the circles in place.
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A));
	cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B));
	cpSpaceAddConstraint(space, cpDampedRotarySpringNew(body1, body2, 0.0f, 3000.0f, 60.0f));

	// Rotary Limit Joint
	boxOffset = cpv(0, -120);
	body1 = addLever(posA, boxOffset);
	body2 = addLever(posB, boxOffset);
	// Add some pin joints to hold the circles in place.
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A));
	cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B));
	// Hold their rotation within 90 degrees of each other.
	cpSpaceAddConstraint(space, cpRotaryLimitJointNew(body1, body2, (cpFloat)-M_PI_2, (cpFloat)M_PI_2));

	// Ratchet Joint - A rotary ratchet, like a socket wrench
	boxOffset = cpv(160, -120);
	body1 = addLever(posA, boxOffset);
	body2 = addLever(posB, boxOffset);
	// Add some pin joints to hold the circles in place.
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A));
	cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B));
	// Ratchet every 90 degrees
	cpSpaceAddConstraint(space, cpRatchetJointNew(body1, body2, 0.0f, (cpFloat)M_PI_2));

	// Gear Joint - Maintain a specific angular velocity ratio
	boxOffset = cpv(-320, 0);
	body1 = addBar(posA, boxOffset);
	body2 = addBar(posB, boxOffset);
	// Add some pin joints to hold the circles in place.
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A));
	cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B));
	// Force one to sping 2x as fast as the other
	cpSpaceAddConstraint(space, cpGearJointNew(body1, body2, 0.0f, 2.0f));

	// Simple Motor - Maintain a specific angular relative velocity
	boxOffset = cpv(-160, 0);
	body1 = addBar(posA, boxOffset);
	body2 = addBar(posB, boxOffset);
	// Add some pin joints to hold the circles in place.
	cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A));
	cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B));
	// Make them spin at 1/2 revolution per second in relation to each other.
	cpSpaceAddConstraint(space, cpSimpleMotorNew(body1, body2, (cpFloat)M_PI));

	// Make a car with some nice soft suspension
	boxOffset = cpv(0, 0);
	cpBody *wheel1 = addWheel(posA, boxOffset);
	cpBody *wheel2 = addWheel(posB, boxOffset);
	cpBody *chassis = addChassis(cpv(80, 100), boxOffset);

	cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel1, cpv(-30, -10), cpv(-30, -40), cpvzero));
	cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel2, cpv( 30, -10), cpv( 30, -40), cpvzero));

	cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel1, cpv(-30, 0), cpvzero, 50.0f, 20.0f, 1.5f));
	cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel2, cpv( 30, 0), cpvzero, 50.0f, 20.0f, 1.5f));

	return space;
}

static void
update(int ticks)
{
	cpSpaceStep(space, 1.0f/60.0f);
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Joints = {
	"Joints and Constraints",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static const int image_width = 188;
static const int image_height = 35;
static const int image_row_length = 24;

static const unsigned char image_bitmap[] = {
	15,-16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-64,15,63,-32,-2,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,31,-64,15,127,-125,-1,-128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,127,-64,15,127,15,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-2,
	31,-1,-64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-64,0,-4,63,-1,-32,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,1,-1,-64,15,-8,127,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	1,-1,-64,0,-8,-15,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-31,-1,-64,15,-8,-32,
	-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,-15,-1,-64,9,-15,-32,-1,-32,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,31,-15,-1,-64,0,-15,-32,-1,-32,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,63,-7,-1,-64,9,-29,-32,127,-61,-16,63,15,-61,-1,-8,31,-16,15,-8,126,7,-31,
	-8,31,-65,-7,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
	-4,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-2,63,-8,31,-4,-1,15,-13,
	-2,63,-1,-3,-1,-64,9,-29,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
	-2,63,-33,-1,-1,-32,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
	-1,63,-33,-1,-1,-16,9,-25,-32,0,7,-8,127,-97,-25,-1,-1,63,-4,63,-4,-1,15,-13,
	-1,63,-49,-1,-1,-8,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
	-1,-65,-49,-1,-1,-4,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
	-1,-65,-57,-1,-1,-2,9,-57,-32,0,7,-8,127,-97,-25,-8,-1,63,-2,127,-4,-1,15,-13,
	-1,-1,-57,-1,-1,-1,9,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
	-1,-61,-1,-1,-1,-119,-57,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
	-1,-61,-1,-1,-1,-55,-49,-32,0,7,-1,-1,-97,-25,-8,-1,63,-1,-1,-4,-1,15,-13,-1,
	-1,-63,-1,-1,-1,-23,-49,-32,127,-57,-1,-1,-97,-25,-1,-1,63,-1,-1,-4,-1,15,-13,
	-1,-1,-63,-1,-1,-1,-16,-49,-32,-1,-25,-1,-1,-97,-25,-1,-1,63,-33,-5,-4,-1,15,
	-13,-1,-1,-64,-1,-9,-1,-7,-49,-32,-1,-25,-8,127,-97,-25,-1,-1,63,-33,-5,-4,-1,
	15,-13,-1,-1,-64,-1,-13,-1,-32,-49,-32,-1,-25,-8,127,-97,-25,-1,-2,63,-49,-13,
	-4,-1,15,-13,-1,-1,-64,127,-7,-1,-119,-17,-15,-1,-25,-8,127,-97,-25,-1,-2,63,
	-49,-13,-4,-1,15,-13,-3,-1,-64,127,-8,-2,15,-17,-1,-1,-25,-8,127,-97,-25,-1,
	-8,63,-49,-13,-4,-1,15,-13,-3,-1,-64,63,-4,120,0,-17,-1,-1,-25,-8,127,-97,-25,
	-8,0,63,-57,-29,-4,-1,15,-13,-4,-1,-64,63,-4,0,15,-17,-1,-1,-25,-8,127,-97,
	-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,-1,-64,31,-2,0,0,103,-1,-1,-57,-8,127,-97,
	-25,-8,0,63,-57,-29,-4,-1,-1,-13,-4,127,-64,31,-2,0,15,103,-1,-1,-57,-8,127,
	-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,127,-64,15,-8,0,0,55,-1,-1,-121,-8,
	127,-97,-25,-8,0,63,-61,-61,-4,127,-1,-29,-4,63,-64,15,-32,0,0,23,-1,-2,3,-16,
	63,15,-61,-16,0,31,-127,-127,-8,31,-1,-127,-8,31,-128,7,-128,0,0
};

static inline int
get_pixel(int x, int y)
{
	return (image_bitmap[(x>>3) + y*image_row_length]>>(~x&0x7)) & 1;
}

static cpSpace *space;

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpShape *
make_ball(cpFloat x, cpFloat y)
{
	cpBody *body = cpBodyNew(1.0f, INFINITY);
	body->p = cpv(x, y);

	cpShape *shape = cpCircleShapeNew(body, 0.95f, cpvzero);
	shape->e = 0.0f; shape->u = 0.0f;

	return shape;
}

static cpSpace *
init(void)
{
	space = cpSpaceNew();
	cpSpaceResizeActiveHash(space, 2.0f, 10000);
	cpSpaceResizeStaticHash(space, 2.0f, 10000);
	space->iterations = 1;

	cpBody *body;
	cpShape *shape;

	for(int y=0; y<image_height; y++){
		for(int x=0; x<image_width; x++){
			if(!get_pixel(x, y)) continue;

			cpFloat x_jitter = 0.05f*frand();
			cpFloat y_jitter = 0.05f*frand();

			shape = make_ball(2*(x - image_width/2 + x_jitter), 2*(image_height/2 - y + y_jitter));
			cpSpaceAddBody(space, shape->body);
			cpSpaceAddShape(space, shape);
		}
	}

	body = cpSpaceAddBody(space, cpBodyNew(INFINITY, INFINITY));
	body->p = cpv(-1000.0f, -10.0f);
	body->v = cpv(400.0f, 0.0f);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 8.0f, cpvzero));
	shape->e = 0.0f; shape->u = 0.0f;
	shape->layers = NOT_GRABABLE_MASK;

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

drawSpaceOptions draw_options = {
	0, 0, 0, 2.0f, 3.0f, 0.0f,
};

chipmunkDemo LogoSmash = {
	"Logo Smash",
	&draw_options,
	init,
	update,
	destroy,
};


code:
// This Demo was written by Juan Pablo Carbajal. Nov 2008.

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"
#include "CCCommon.h"

#define WIDTH 600
#define HEIGHT 400

#define SINGMAX 10 // Maximum number of singularities per body
#define NMAG 10 // Number of magnets
#define NCHG 10 // Number of charged bodies
#define NMIX 10 // Number of charged magnets

#define COU_MKS  8.987551787e9 // Some physical constants
#define MAG_MKS 1e-7

// Prototypes
struct DataforForce;
typedef void (*SingForceFunc)(struct DataforForce* data);
void make_mix(cpVect p, cpFloat ang, cpFloat mag,cpFloat chg);

// Structures
// Singularities
typedef struct ActorSingularity{
	// Number of singularities
	int Nsing;
	// Value of the singularities
	cpFloat value[SINGMAX];
	// Type of the singularities
	char type[SINGMAX][100];
	// Global position of the singularities
	cpVect Gpos[SINGMAX];
	// Local position of the singularities
	cpVect position[SINGMAX];
	// Angle of the singularities measured in the body axes
	cpFloat angle[SINGMAX];
	// Angle of the singularities measured from x
	cpFloat Gangle[SINGMAX];
	// Force function
	SingForceFunc force_func[SINGMAX];
	// Force function
	SingForceFunc torque_func[SINGMAX];
}Sing;

// Data for the force functions
typedef struct DataforForce{
	//Everything in global coordinates
	// Position of the source
	cpVect p0;
	// Observed position
	cpVect p;
	// Relative position source-observed
	cpVect relp;
	// distance, disntace^2, ditance ^3
	cpFloat r[3];
	// angle of the source
	cpFloat ang0;
	// angle of the observed singularity
	cpFloat ang;
	// Foce value
	cpVect F;
	// Torque value
	cpFloat T;
}ForceData;

// Global Varibales
static cpSpace *space;

// **** Forces ****** //
// Calculate the forces between two bodies. all this functions requieres
// a pointer to an structure with the necessary fields.

// forces between charges
static void
CoulombForce(ForceData* data){
	data->F=cpvmult(cpvnormalize(data->relp),(cpFloat)COU_MKS/data->r[1]);
}

// forces between magnets
static void
MagDipoleForce(ForceData* data){
	static cpFloat phi,alpha,beta,Fr,Fphi;

	// Angle of the relative position vector
	phi=cpvtoangle(data->relp);
	alpha=data->ang0;
	beta=data->ang;

	alpha =phi - alpha;
	beta = phi - beta;

	// Components in polar coordinates
	Fr=(2.0e0f*cosf(alpha)*cosf(beta) - sinf(alpha)*sinf(beta));
	Fphi=sinf(alpha+beta);
//	printf("%g %g %g %g %g\n",phi,alpha,beta,Fphi);

	// Cartesian coordinates
	data->F=cpv(Fr*cosf(phi)-Fphi*sinf(phi),Fr*sinf(phi)+Fphi*cosf(phi));
	data->F=cpvmult(data->F,-3.e0f*(cpFloat)MAG_MKS/(data->r[1]*data->r[1]));
}

static void
MagDipoleTorque(ForceData* data){
	static cpFloat phi,alpha,beta;

	phi=cpvtoangle(data->relp);
	alpha=data->ang0;
	beta=data->ang;
	alpha =phi - alpha;
	beta = phi - beta;

	// Torque. Though we could use a component of F to save some space,
	// we use another variables for the sake of clarity.

	data->T=((cpFloat)MAG_MKS/data->r[2])*(3.0e0f*cosf(alpha)*sinf(beta) + sinf(alpha-beta));
}
// ******* //

// This function fills the data structure for the force functions
// The structure Sing has the information about the singularity (charge or magnet)
static void
FillForceData(Sing* source,int inds, Sing* obs,int indo, ForceData* data)
{
	// Global Position and orientation of the source singularity
	 data->p0=source->Gpos[inds];
	 data->ang0=source->Gangle[inds];

	// Global Position and orientation of the observed singularity
	 data->p=obs->Gpos[indo];
	 data->ang=obs->Gangle[indo];

	// Derived magnitudes
	 data->relp=cpvsub(data->p,data->p0); //Relative position
	 data->r[0]=cpvlength(data->relp); // Distance
	 data->r[1]=cpvlengthsq(data->relp); // Square Distance
	 data->r[2]=data->r[0]*data->r[1]; // Cubic distance

     source->force_func[inds](data); // The value of the force
	 data->F= cpvmult(data->F,source->value[inds]*obs->value[indo]);
}

// Calculation of the interaction
static void
LRangeForceApply(cpBody *a, cpBody *b){

	Sing* aux = (Sing*)a->data;
	Sing* aux2 = (Sing*)b->data;
	cpVect delta;
	// General data needed to calculate interaction
	static ForceData fdata;
	fdata.F=cpvzero;

	// Calculate the forces between the charges of different bodies
	for (int i=0; i<aux->Nsing; i++)
	{
		for (int j=0; j<aux2->Nsing; j++)
		{
			if(!strcmp(aux->type[i],aux2->type[j]))
			{
				//printf("%s %s\n",aux->type[i],aux2->type[j]);
				FillForceData (aux2,j,aux,i,&fdata);

				//Force applied to body A
				delta=cpvsub(aux->Gpos[i], a->p);
				cpBodyApplyForce(a,fdata.F, delta);

	 			if(aux->torque_func[i] != NULL)
				{
					//Torque on A
					aux->torque_func[i](&fdata);
					a->t += aux->value[i]*aux2->value[j]*fdata.T;

				}
			}
		}
	}
}

// function for the integration of the positions
// The following functions are variations to the starndrd integration in Chipmunk
// you can go ack to the standard ones by doing the appropiate changes.
static void
ChargedBodyUpdatePositionVerlet(cpBody *body, cpFloat dt)
{
    // Long range interaction
    cpArray *bodies = space->bodies;
	static cpBody* B;
	Sing* aux=(Sing*)body->data;
	Sing* aux2;

	// General data needed to calculate interaction
	static ForceData fdata;
	fdata.F=cpvzero;

	for(int i=0; i< bodies->num; i++)
	{
	  B=(cpBody*)bodies->arr[i];
	  aux2=(Sing*)B->data;

	  if(B != body)
	  {
        // Calculate the forces between the singularities of different bodies
        LRangeForceApply(body, B);
	  }
	}

	cpVect dp = cpvmult(cpvadd(body->v, body->v_bias), dt);
	dp = cpvadd(dp,cpvmult(cpvmult(body->f, body->m_inv), 0.5e0f*dt*dt));
	body->p = cpvadd(body->p, dp);

	cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt
				   + 0.5f*body->t*body->i_inv*dt*dt);

	// Update position of the singularities
	aux = (Sing*)body->data;
	for (int i=0; i<aux->Nsing; i++)
	{
        aux->Gpos[i]=cpvadd(body->p,cpvrotate(cpv(aux->position[i].x,
										  aux->position[i].y), body->rot));
		aux->Gangle[i]= aux->angle[i] + body->a;
	}

 	body->v_bias = cpvzero;
	body->w_bias = 0.0f;
}

// function for the integration of the velocities
static void
ChargedBodyUpdateVelocityVerlet(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
	body->v = cpvadd(body->v, cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), 0.5e0f*dt));
	body->w = body->w + body->t*body->i_inv*0.5e0f*dt;

	body->f = cpvzero;
	body->t = 0.0e0f;

	// Long range interaction
    cpArray *bodies = space->bodies;
	static cpBody* B;

	// General data needed to calculate interaction
	static ForceData fdata;
	fdata.F=cpvzero;

	for(int i=0; i< bodies->num; i++)
	{
	  B=(cpBody*)bodies->arr[i];

	  if(B != body)
	  {
        // Calculate the forces between the singularities of different bodies
        LRangeForceApply(body, B);
	  }
	}
	body->v = cpvadd(cpvmult(body->v,damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), 0.5e0f*dt));
	body->w = body->w*damping + body->t*body->i_inv*0.5e0f*dt;
}

static void
update(int ticks)
{
	int steps = 10;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	cpArray *bodies = space->bodies;

	for(int i=0; i< bodies->num; i++)
		  cpBodyResetForces((cpBody*)bodies->arr[i]);

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}

}

static void
make_mag(cpVect p, cpFloat ang, cpFloat mag)
{
	int nverts=6;
	cpVect verts[] = {
		cpv(-10,-10),
		cpv(-10, 10),
		cpv( 10, 10),
		cpv( 15, 5),
		cpv( 15, -5),
		cpv( 10,-10)
	};

	cpBody *body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, nverts, verts, cpvzero));
	body->p = p;
	body->v = cpvzero;
	cpBodySetAngle(body, ang);
	body->w = 0.0e0f;

    // Load the singularities
    Sing *magnet=(Sing*)cpmalloc(sizeof(Sing));
	magnet->Nsing=1;
	magnet->value[0]=mag;
	sprintf(magnet->type[0],"magdipole");

	// The position and angle could be different form the one of the body
	magnet->position[0]=cpvzero;
	magnet->Gpos[0]=cpvadd(p,magnet->position[0]);
	magnet->angle[0]=0.0f;
	magnet->Gangle[0]=ang;

	magnet->force_func[0]=MagDipoleForce;
	magnet->torque_func[0]=MagDipoleTorque;

	body->data=magnet;

    body->position_func=ChargedBodyUpdatePositionVerlet;
    body->velocity_func=ChargedBodyUpdateVelocityVerlet;
	cpSpaceAddBody(space, body);

	cpShape *shape = cpPolyShapeNew(body, nverts, verts, cpvzero);
	shape->e = 0.0f; shape->u = 0.7f;
	cpSpaceAddShape(space, shape);
}

static void
make_charged(cpVect p, cpFloat chg)
{
	int nverts=4;
	cpVect verts[] = {
		cpv(-10,-10),
		cpv(-10, 10),
		cpv( 10, 10),
		cpv( 10,-10)
	};

	cpBody *body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, nverts, verts, cpvzero));
	body->p = p;
	body->v = cpvzero;
	cpBodySetAngle(body, 0);
	body->w = 0.0e0f;

    // Load the singularities
    Sing *charge=(Sing*)cpmalloc(sizeof(Sing));;
	charge->Nsing=1;
	charge->value[0]=chg;
	sprintf(charge->type[0],"electrical");

	// The position and angle could be different form the one of the body
	charge->position[0]=cpvzero;
	charge->Gpos[0]=cpvadd(p,charge->position[0]);
	charge->Gangle[0]=0;

	charge->force_func[0]=CoulombForce;
	charge->torque_func[0]=NULL;

	body->data=charge;

    body->position_func=ChargedBodyUpdatePositionVerlet;
    body->velocity_func=ChargedBodyUpdateVelocityVerlet;
	cpSpaceAddBody(space, body);

	cpShape *shape = cpPolyShapeNew(body, nverts, verts, cpvzero);
	shape->e = 0.0f; shape->u = 0.7f;
	cpSpaceAddShape(space, shape);
}
void
make_mix(cpVect p, cpFloat ang, cpFloat mag,cpFloat chg)
{
	int nverts=5;
	cpVect verts[] = {
		cpv(-10,-10),
		cpv(-10, 10),
		cpv( 10, 10),
		cpv( 20, 0),
		cpv( 10,-10)
	};

	cpBody *body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, nverts, verts, cpvzero));
	body->p = p;
	body->v = cpvzero;
	cpBodySetAngle(body, ang);
	body->w = 0.0e0f;

    // Load the singularities
    Sing *mix=(Sing*)cpmalloc(sizeof(Sing));;
	mix->Nsing=2;
	mix->value[0]=mag;
	mix->value[1]=chg;
	sprintf(mix->type[0],"magdipole");
	sprintf(mix->type[1],"electrical");

	// The position and angle could be different form the one of the body
	mix->position[0]=cpvzero;
	mix->Gpos[0]=cpvadd(p,mix->position[0]);
	mix->position[1]=cpvzero;
	mix->Gpos[1]=cpvadd(p,mix->position[1]);
	mix->Gangle[0]=ang;
	mix->Gangle[1]=ang;

	mix->force_func[0]=MagDipoleForce;
	mix->force_func[1]=CoulombForce;
	mix->torque_func[0]=MagDipoleTorque;
	mix->torque_func[1]=NULL;

	body->data=mix;

    body->position_func=ChargedBodyUpdatePositionVerlet;
    body->velocity_func=ChargedBodyUpdateVelocityVerlet;
	cpSpaceAddBody(space, body);

	cpShape *shape = cpPolyShapeNew(body, nverts, verts, cpvzero);
	shape->e = 0.0f; shape->u = 0.7f;
	cpSpaceAddShape(space, shape);
}

static cpSpace*
init(void)
{
	cpResetShapeIdCounter();
	space = cpSpaceNew();
	space->iterations = 5;
	space->gravity = cpvzero; //cpv(0,-100);

	cpSpaceResizeActiveHash(space, 30.0f, 2999);

	// Screen border
/*	shape = cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddShape(space, shape);

	shape = cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddShape(space, shape);

	shape = cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f);
	shape->e = 1.0; shape->u = 1.0;
	cpSpaceAddShape(space, shape);

	// Reference line
	// Does not collide with other objects, we just want to draw it.
	shape = cpSegmentShapeNew(staticBody, cpv(-320,0), cpv(320,0), 0.0f);
	shape->collision_type = 1;
	cpSpaceAddShape(space, shape);
	// Add a collision pair function to filter collisions
	cpSpaceAddCollisionPairFunc(space, 0, 1, NULL, NULL);
*/

	srand((unsigned int) time(NULL));
    cpVect p;
	cpFloat ang;

	// Create magnets
	for(int i=0; i<NMAG; i++)
	{
	  p.x=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*WIDTH/2.0f;
  	  p.y=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*HEIGHT/2.0f;
  	  ang=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*3.1415f;
	  make_mag(p, ang,1.0e7f);
	}

	// Create charged objects
	for(int i=0; i<NCHG; i++)
	{
	  p.x=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*WIDTH/2.0f;
  	  p.y=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*HEIGHT/2.0f;
  	  ang=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*3.1415f;
	  make_charged(p, (float)(1.0e-3) *powf(-1.0f,i%2));
	}

	// Create charged magnets objects
	for(int i=0; i<NMIX; i++)
	{
      p.x=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*WIDTH/2.0f;
  	  p.y=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*HEIGHT/2.0f;
  	  ang=(2.0e0f*rand()/((cpFloat)RAND_MAX) - 1.0e0f)*3.1415f;
	  make_mix(p, ang,1.0e7f*powf(-1.0f,i%2), (float)(1.0e-3) *powf(-1.0f,i%2));
	}

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo MagnetsElectric = {
	"Magnets and Electric Charges (By: Juan Pablo Carbajal)",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

typedef struct OneWayPlatform {
	cpVect n; // direction objects may pass through
	cpArray *passThruList; // list of objects passing through
} OneWayPlatform;

static OneWayPlatform platformInstance;

static cpBool
preSolve(cpArbiter *arb, cpSpace *space, void *ignore)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	OneWayPlatform *platform = (OneWayPlatform *)a->data;

	if(cpvdot(cpArbiterGetNormal(arb, 0), platform->n) < 0){
		cpArbiterIgnore(arb);
		return cpFalse;
	}

	return cpTrue;
}

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 10;
	space->gravity = cpv(0, -100);

	cpBody *body, *staticBody = &space->staticBody;
	cpShape *shape;

	// Create segments around the edge of the screen.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	// Add our one way segment
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160,-100), cpv(160,-100), 10.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->collision_type = 1;
	shape->layers = NOT_GRABABLE_MASK;

	// We'll use the data pointer for the OneWayPlatform struct
	platformInstance.n = cpv(0, 1); // let objects pass upwards
	platformInstance.passThruList = cpArrayNew(0);
	shape->data = &platformInstance;

	// Add a ball to make things more interesting
	cpFloat radius = 15.0f;
	body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero)));
	body->p = cpv(0, -200);
	body->v = cpv(0, 170);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	shape->e = 0.0f; shape->u = 0.9f;
	shape->collision_type = 2;

	cpSpaceAddCollisionHandler(space, 1, 2, NULL, preSolve, NULL, NULL, NULL);

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);

	cpArrayFree(platformInstance.passThruList);
}

chipmunkDemo OneWay = {
	"One Way Platforms",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;
static cpBody *planetBody;

static cpFloat gravityStrength = 5.0e6f;

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);

		// Update the static body spin so that it looks like it's rotating.
		cpBodyUpdatePosition(planetBody, dt);
	}
}

static void
planetGravityVelocityFunc(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
	// Gravitational acceleration is proportional to the inverse square of
	// distance, and directed toward the origin. The central planet is assumed
	// to be massive enough that it affects the satellites but not vice versa.
	cpVect p = body->p;
	cpFloat sqdist = cpvlengthsq(p);
	cpVect g = cpvmult(p, -gravityStrength / (sqdist * cpfsqrt(sqdist)));

	cpBodyUpdateVelocity(body, g, damping, dt);
}

static cpVect
rand_pos(cpFloat radius)
{
	cpVect v;
	do {
		v = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius));
	} while(cpvlength(v) < 85.0f);

	return v;
}

static void
add_box()
{
	const cpFloat size = 10.0f;
	const cpFloat mass = 1.0f;

	cpVect verts[] = {
		cpv(-size,-size),
		cpv(-size, size),
		cpv( size, size),
		cpv( size,-size),
	};

	cpFloat radius = cpvlength(cpv(size, size));

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts, cpvzero)));
	body->velocity_func = planetGravityVelocityFunc;
	body->p = rand_pos(radius);

	// Set the box's velocity to put it into a circular orbit from its
	// starting position.
	cpFloat r = cpvlength(body->p);
	cpFloat v = cpfsqrt(gravityStrength / r) / r;
	body->v = cpvmult(cpvperp(body->p), v);

	// Set the box's angular velocity to match its orbital period and
	// align its initial angle with its position.
	body->w = v;
	cpBodySetAngle(body, cpfatan2(body->p.y, body->p.x));

	cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 4, verts, cpvzero));
	shape->e = 0.0f; shape->u = 0.7f;
}

static cpSpace *
init(void)
{
	planetBody = cpBodyNew(INFINITY, INFINITY);
	planetBody->w = 0.2f;

	cpResetShapeIdCounter();

	space = cpSpaceNew();
	cpSpaceResizeActiveHash(space, 30.0f, 10000);
	space->iterations = 20;

	for(int i=0; i<30; i++)
		add_box();

	cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(planetBody, 70.0f, cpvzero));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	return space;
}

static void
destroy(void)
{
	cpBodyFree(planetBody);
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Planet = {
	"Planet",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

typedef struct PlayerStruct {
	cpFloat u;
	cpShape *shape;
	cpVect groundNormal;
	cpArray *groundShapes;
} PlayerStruct;

PlayerStruct playerInstance;

static cpBool
begin(cpArbiter *arb, cpSpace *space, void *ignore)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	PlayerStruct *player = (PlayerStruct *)a->data;

	cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
	if(n.y > 0.0f){
		cpArrayPush(player->groundShapes, b);
	}

	return cpTrue;
}

static cpBool
preSolve(cpArbiter *arb, cpSpace *space, void *ignore)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	PlayerStruct *player = (PlayerStruct *)a->data;

	if(cpArbiterIsFirstContact(arb)){
		a->u = player->u;

		// pick the most upright jump normal each frame
		cpVect n = cpvneg(cpArbiterGetNormal(arb, 0));
		if(n.y >= player->groundNormal.y){
			player->groundNormal = n;
		}
	}

	return cpTrue;
}

static void
separate(cpArbiter *arb, cpSpace *space, void *ignore)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	PlayerStruct *player = (PlayerStruct *)a->data;

	cpArrayDeleteObj(player->groundShapes, b);

	if(player->groundShapes->num == 0){
		a->u = 0.0f;
		player->groundNormal = cpvzero;
	}
}

static void
playerUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
	cpBodyUpdateVelocity(body, gravity, damping, dt);
	body->v.y = cpfmax(body->v.y, -700);
	body->v.x = cpfclamp(body->v.x, -400, 400);
}

static void
update(int ticks)
{
	static int lastJumpState = 0;
	int jumpState = (arrowDirection.y > 0.0f);

	cpBody *body = playerInstance.shape->body;

	cpVect groundNormal = playerInstance.groundNormal;
	if(groundNormal.y > 0.0f){
		playerInstance.shape->surface_v = cpvmult(cpvperp(groundNormal), 400.0f*arrowDirection.x);
		if(arrowDirection.x) cpBodyActivate(body);
	} else {
		playerInstance.shape->surface_v = cpvzero;
	}

	// apply jump
	if(jumpState && !lastJumpState && cpvlengthsq(groundNormal)){
//		body->v = cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.5f), 500.0f);
		body->v = cpvadd(body->v, cpvmult(cpvslerp(groundNormal, cpv(0.0f, 1.0f), 0.75f), 500.0f));
		cpBodyActivate(body);
	}

	if(playerInstance.groundShapes->num == 0){
		cpFloat air_accel = body->v.x + arrowDirection.x*(2000.0f);
		body->f.x = body->m*air_accel;
//		body->v.x = cpflerpconst(body->v.x, 400.0f*arrowDirection.x, 2000.0f/60.0f);
	}

	int steps = 3;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}

	lastJumpState = jumpState;
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 10;
	space->gravity = cpv(0, -1500);

	cpBody *body, *staticBody = &space->staticBody;
	cpShape *shape;

	// Create segments around the edge of the screen.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	// add some other segments to play with
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-200), cpv(-220,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(320,-200), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(200,-240), cpv(320,-100), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-220,-80), cpv(200,-80), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;
	shape->collision_type = 2;

	// Set up the player
	cpFloat radius = 15.0f;
	body = cpSpaceAddBody(space, cpBodyNew(10.0f, INFINITY));
	body->p = cpv(0, -220);
	body->velocity_func = playerUpdateVelocity;

	shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	shape->e = 0.0f; shape->u = 2.0f;
	shape->collision_type = 1;

	playerInstance.u = shape->u;
	playerInstance.shape = shape;
	playerInstance.groundShapes = cpArrayNew(0);
	shape->data = &playerInstance;

	cpSpaceAddCollisionHandler(space, 1, 2, begin, preSolve, NULL, separate, NULL);

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);

	cpArrayFree(playerInstance.groundShapes);
}

chipmunkDemo Player = {
	"Player",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

// Iterate over all of the bodies and reset the ones that have fallen offscreen.
static void
eachBody(cpBody *body, void *unused)
{
	if(body->p.y < -260 || cpfabs(body->p.x) > 340){
		cpFloat x = rand()/(cpFloat)RAND_MAX*640 - 320;
		body->p = cpv(x, 260);
	}
}

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
		cpSpaceEachBody(space, &eachBody, NULL);
	}
}

#define NUM_VERTS 5

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 5;
	space->gravity = cpv(0, -100);

	cpSpaceResizeStaticHash(space, 40.0f, 999);
	cpSpaceResizeActiveHash(space, 30.0f, 2999);

	cpBody *body, *staticBody = &space->staticBody;
	cpShape *shape;

	// Create vertexes for a pentagon shape.
	cpVect verts[NUM_VERTS];
	for(int i=0; i<NUM_VERTS; i++){
		cpFloat angle = -2*(cpFloat)M_PI*i/((cpFloat) NUM_VERTS);
		verts[i] = cpv(10*cosf(angle), 10*sinf(angle));
	}

	// Vertexes for a triangle shape.
	cpVect tris[] = {
		cpv(-15,-15),
		cpv(  0, 10),
		cpv( 15,-15),
	};

	// Create the static triangles.
	for(int i=0; i<9; i++){
		for(int j=0; j<6; j++){
			cpFloat stagger = (j%2)*40;
			cpVect offset = cpv(i*80 - 320 + stagger, j*70 - 240);
			shape = cpSpaceAddShape(space, cpPolyShapeNew(staticBody, 3, tris, offset));
			shape->e = 1.0f; shape->u = 1.0f;
			shape->layers = NOT_GRABABLE_MASK;
		}
	}

	// Add lots of pentagons.
	for(int i=0; i<300; i++){
		body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, NUM_VERTS, verts, cpvzero)));
		cpFloat x = rand()/(cpFloat)RAND_MAX*640 - 320;
		body->p = cpv(x, 350);

		shape = cpSpaceAddShape(space, cpPolyShapeNew(body, NUM_VERTS, verts, cpvzero));
		shape->e = 0.0f; shape->u = 0.4f;
	}

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Plink = {
	"Plink",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;
static cpConstraint *motor;

#define numBalls 5
static cpBody *balls[numBalls];

static void
update(int ticks)
{
	cpFloat coef = (2.0f + arrowDirection.y)/3.0f;
	cpFloat rate = arrowDirection.x*30.0f*coef;

	cpSimpleMotorSetRate(motor, rate);
	motor->maxForce = (rate ? 1000000.0f : 0.0f);

	int steps = 2;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);

		for(int i=0; i<numBalls; i++){
			cpBody *ball = balls[i];
			if(ball->p.x > 320.0f){
				ball->v = cpvzero;
				ball->p = cpv(-224.0f, 200.0f);
			}
		}
	}
}

static cpBody *
add_ball(cpVect pos)
{
	cpBody *body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 30, 0, cpvzero)));
	body->p = pos;

	cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 30, cpvzero));
	shape->e = 0.0f; shape->u = 0.5f;

	return body;
}

static cpSpace *
init(void)
{
	space = cpSpaceNew();
	space->gravity = cpv(0, -600);

	cpBody *staticBody = &space->staticBody;
	cpShape *shape;

	// beveling all of the line segments slightly helps prevent things from getting stuck on cracks
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-256,300), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-192,0), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,0), cpv(-192, -64), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,-64), cpv(-128,144), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,80), cpv(-192,176), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,176), cpv(-128,240), 2.0f));
	shape->e = 0.0f; shape->u = 0.0f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,144), cpv(192,64), 2.0f));
	shape->e = 0.0f; shape->u = 0.5f; shape->layers = 1;
	shape->layers = NOT_GRABABLE_MASK;

	cpVect verts[] = {
		cpv(-30,-80),
		cpv(-30, 80),
		cpv( 30, 64),
		cpv( 30,-80),
	};

	cpBody *plunger = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY));
	plunger->p = cpv(-160,-80);

	shape = cpSpaceAddShape(space, cpPolyShapeNew(plunger, 4, verts, cpvzero));
	shape->e = 1.0f; shape->u = 0.5f; shape->layers = 1;

	// add balls to hopper
	for(int i=0; i<numBalls; i++)
		balls[i] = add_ball(cpv(-224 + i,80 + 64*i));

	// add small gear
	cpBody *smallGear = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 80, 0, cpvzero)));
	smallGear->p = cpv(-160,-160);
	cpBodySetAngle(smallGear, (cpFloat)-M_PI_2);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(smallGear, 80.0f, cpvzero));
	shape->layers = 0;

	cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, smallGear, cpv(-160,-160), cpvzero));

	// add big gear
	cpBody *bigGear = cpSpaceAddBody(space, cpBodyNew(40.0f, cpMomentForCircle(40.0f, 160, 0, cpvzero)));
	bigGear->p = cpv(80,-160);
	cpBodySetAngle(bigGear, (cpFloat)M_PI_2);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(bigGear, 160.0f, cpvzero));
	shape->layers = 0;

	cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, bigGear, cpv(80,-160), cpvzero));

	// connect the plunger to the small gear.
	cpSpaceAddConstraint(space, cpPinJointNew(smallGear, plunger, cpv(80,0), cpv(0,0)));
	// connect the gears.
	cpSpaceAddConstraint(space, cpGearJointNew(smallGear, bigGear, (cpFloat)-M_PI_2, -2.0f));

	// feeder mechanism
	cpFloat bottom = -300.0f;
	cpFloat top = 32.0f;
	cpBody *feeder = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForSegment(1.0f, cpv(-224.0f, bottom), cpv(-224.0f, top))));
	feeder->p = cpv(-224, (bottom + top)/2.0f);

	cpFloat len = top - bottom;
	cpSpaceAddShape(space, cpSegmentShapeNew(feeder, cpv(0.0f, len/2.0f), cpv(0.0f, -len/2.0f), 20.0f));

	cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, feeder, cpv(-224.0f, bottom), cpv(0.0f, -len/2.0f)));
	cpVect anchr = cpBodyWorld2Local(feeder, cpv(-224.0f, -160.0f));
	cpSpaceAddConstraint(space, cpPinJointNew(feeder, smallGear, anchr, cpv(0.0f, 80.0f)));

	// motorize the second gear
	motor = cpSpaceAddConstraint(space, cpSimpleMotorNew(staticBody, bigGear, 3.0f));

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Pump = {
	"Pump",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

static void
update(int ticks)
{
	int steps = 3;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 30;
	cpSpaceResizeStaticHash(space, 40.0f, 1000);
	cpSpaceResizeActiveHash(space, 40.0f, 1000);
	space->gravity = cpv(0, -100);
	space->sleepTimeThreshold = 0.5f;

	cpBody *body, *staticBody = &space->staticBody;
	cpShape *shape;

	// Create segments around the edge of the screen.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	// Add lots of boxes.
	for(int i=0; i<14; i++){
		for(int j=0; j<=i; j++){
			body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForBox(1.0f, 30.0f, 30.0f)));
			body->p = cpv(j*32 - i*16, 300 - i*32);

			shape = cpSpaceAddShape(space, cpBoxShapeNew(body, 30.0f, 30.0f));
			shape->e = 0.0f; shape->u = 0.8f;
		}
	}

	// Add a ball to make things more interesting
	cpFloat radius = 15.0f;
	body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero)));
	body->p = cpv(0, -240 + radius+5);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
	shape->e = 0.0f; shape->u = 0.9f;

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo PyramidStack = {
	"Pyramid Stack",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

static void
update(int ticks)
{
	int steps = 3;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++)
		cpSpaceStep(space, dt);
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 30;
	cpSpaceResizeActiveHash(space, 30.0f, 2999);
	cpSpaceResizeStaticHash(space, 30.0f, 999);
	space->gravity = cpv(0, -300);
	space->sleepTimeThreshold = 0.5f;

	cpBody *body;

	cpShape *shape;

	// Vertexes for the dominos.
	int num = 4;
	cpVect verts[] = {
		cpv(-3,-20),
		cpv(-3, 20),
		cpv( 3, 20),
		cpv( 3,-20),
	};

	// Add a floor.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(&space->staticBody, cpv(-600,-240), cpv(600,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	// Shared friction constant.
	cpFloat u = 0.6f;

	// Add the dominoes. Skim over this. It doesn't do anything fancy, and it's hard to follow.
	int n = 9;
	for(int i=1; i<=n; i++){
		cpVect offset = cpv(-i*60/2.0f, (n - i)*52);

		for(int j=0; j<i; j++){
			body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero)));
			body->p = cpvadd(cpv(j*60, -220), offset);

			shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
			shape->e = 0.0f; shape->u = u;

			body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero)));
			body->p = cpvadd(cpv(j*60, -197), offset);
			cpBodySetAngle(body, (cpFloat)M_PI/2.0f);

			shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
			shape->e = 0.0f; shape->u = u;

			if(j == (i - 1)) continue;
			body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero)));
			body->p = cpvadd(cpv(j*60 + 30, -191), offset);
			cpBodySetAngle(body, (cpFloat)M_PI/2.0f);

			shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
			shape->e = 0.0f; shape->u = u;
		}

		body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero)));
		body->p = cpvadd(cpv(-17, -174), offset);

		shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
		shape->e = 0.0f; shape->u = u;

		body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero)));
		body->p = cpvadd(cpv((i - 1)*60 + 17, -174), offset);

		shape = cpSpaceAddShape(space, cpPolyShapeNew(body, num, verts, cpvzero));
		shape->e = 0.0f; shape->u = u;
	}

	// Give the last domino a little tap.
//	body->w = -1;
//	body->v = cpv(-body->w*20, 0);
	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo PyramidTopple = {
	"Pyramid Topple",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include "CCCommon.h"
#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

#include "chipmunk_unsafe.h"

static cpSpace *space;
extern cpVect mousePoint;

static cpShape *querySeg = NULL;

static void
update(int ticks)
{
	messageString[0] = '\0';

	cpVect start = cpvzero;
	cpVect end = /*cpv(0, 85);//*/mousePoint;
	cpVect lineEnd = end;

	{
		char infoString[1024];
		sprintf(infoString, "Query: Dist(%f) Point%s, ", cpvdist(start, end), cpvstr(end));
		strcat(messageString, infoString);
	}

	cpSegmentQueryInfo info = {};
	if(cpSpaceSegmentQueryFirst(space, start, end, CP_ALL_LAYERS, CP_NO_GROUP, &info)){
		cpVect point = cpSegmentQueryHitPoint(start, end, info);
		lineEnd = cpvadd(point, cpvzero);//cpvmult(info.n, 4.0f));

		char infoString[1024];
		sprintf(infoString, "Segment Query: Dist(%f) Normal%s", cpSegmentQueryHitDist(start, end, info), cpvstr(info.n));
		strcat(messageString, infoString);
	} else {
		strcat(messageString, "Segment Query (None)");
	}

	cpSegmentShapeSetEndpoints(querySeg, start, lineEnd);
	cpShapeCacheBB(querySeg); // force it to update it's collision detection data so it will draw

	// normal other stuff.
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->elasticIterations = 0;
	space->iterations = 5;

	cpSpaceResizeStaticHash(space, 40.0f, 999);
	cpSpaceResizeActiveHash(space, 30.0f, 2999);

	cpBody *staticBody = &space->staticBody;
	cpShape *shape;

	// add a non-collidable segment as a quick and dirty way to draw the query line
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpvzero, cpv(100.0f, 0.0f), 4.0f));
	shape->layers = 0;
	querySeg = shape;

	{ // add a fat segment
		cpFloat mass = 1.0f;
		cpFloat length = 100.0f;
		cpVect a = cpv(-length/2.0f, 0.0f), b = cpv(length/2.0f, 0.0f);

		cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
		body->p = cpv(0.0f, 100.0f);

		cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 20.0f));
	}

	{ // add a static segment
		cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0, 300), cpv(300, 0), 0.0f));
	}

	{ // add a pentagon
		cpFloat mass = 1.0f;
		const int NUM_VERTS = 5;

		cpVect verts[NUM_VERTS];
		for(int i=0; i<NUM_VERTS; i++){
			cpFloat angle = -2*(cpFloat)M_PI*i/((cpFloat) NUM_VERTS);
			verts[i] = cpv(30*cosf(angle), 30*sinf(angle));
		}

		cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, NUM_VERTS, verts, cpvzero)));
		body->p = cpv(50.0f, 50.0f);

		cpSpaceAddShape(space, cpPolyShapeNew(body, NUM_VERTS, verts, cpvzero));
	}

	{ // add a circle
		cpFloat mass = 1.0f;
		cpFloat r = 20.0f;

		cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, r, cpvzero)));
		body->p = cpv(100.0f, 100.0f);

		cpSpaceAddShape(space, cpCircleShapeNew(body, r, cpvzero));
	}

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Query = {
	"Segment Query",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

enum CollisionTypes {
	BALL_TYPE,
	BLOCKING_SENSOR_TYPE,
	CATCH_SENSOR_TYPE,
};

typedef struct Emitter {
	int queue;
	int blocked;
	cpVect position;
} Emitter;

static Emitter emitterInstance;

static cpBool
blockerBegin(cpArbiter *arb, cpSpace *space, void *unused)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	Emitter *emitter = (Emitter *) a->data;

	emitter->blocked++;

	return cpFalse; // Return values from sensors callbacks are ignored,
}

static void
blockerSeparate(cpArbiter *arb, cpSpace *space, void *unused)
{
	CP_ARBITER_GET_SHAPES(arb, a, b);
	Emitter *emitter = (Emitter *) a->data;

	emitter->blocked--;
}

static void
postStepRemove(cpSpace *space, cpShape *shape, void *unused)
{
	// cocos2d-x: bring cpSpaceRemoveShape here to avoid
	// the crash on win32 platform
	cpSpaceRemoveShape(space, shape);
	cpSpaceRemoveBody(space, shape->body);
	cpBodyFree(shape->body);

	cpShapeFree(shape);
}

static cpBool
catcherBarBegin(cpArbiter *arb, cpSpace *space, void *unused)
{
	cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b);
	Emitter *emitter = (Emitter *) a->data;

	emitter->queue++;
	cpSpaceAddPostStepCallback(space, (cpPostStepFunc)postStepRemove, b, NULL);

	return cpFalse;
}

static cpFloat frand_unit(){return 2.0f*((cpFloat)rand()/(cpFloat)RAND_MAX) - 1.0f;}

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	if(!emitterInstance.blocked && emitterInstance.queue){
		emitterInstance.queue--;

		cpBody *body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 15.0f, 0.0f, cpvzero)));
		body->p = emitterInstance.position;
		body->v = cpvmult(cpv(frand_unit(), frand_unit()), 100.0f);

		cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 15.0f, cpvzero));
		shape->collision_type = BALL_TYPE;
	}

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	space->iterations = 10;
	space->gravity = cpv(0, -100);

	cpBody *staticBody = &space->staticBody;
	cpShape *shape;

	// Data structure for our ball emitter
	// We'll use two sensors for it, one to see if the emitter is blocked
	// a second to catch the balls and add them back to the emitter
	emitterInstance.queue = 5;
	emitterInstance.blocked = 0;
	emitterInstance.position = cpv(0, 150);

	// Create our blocking sensor, so we know when the emitter is clear to emit another ball
	shape = cpSpaceAddShape(space, cpCircleShapeNew(staticBody, 15.0f, emitterInstance.position));
	shape->sensor = 1;
	shape->collision_type = BLOCKING_SENSOR_TYPE;
	shape->data = &emitterInstance;

	// Create our catch sensor to requeue the balls when they reach the bottom of the screen
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-2000, -200), cpv(2000, -200), 15.0f));
	shape->sensor = 1;
	shape->collision_type = CATCH_SENSOR_TYPE;
	shape->data = &emitterInstance;

	cpSpaceAddCollisionHandler(space, BLOCKING_SENSOR_TYPE, BALL_TYPE, blockerBegin, NULL, NULL, blockerSeparate, NULL);
	cpSpaceAddCollisionHandler(space, CATCH_SENSOR_TYPE, BALL_TYPE, catcherBarBegin, NULL, NULL, NULL, NULL);

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Sensors = {
	"Sensors",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

// Init is called by the demo code to set up the demo.
static cpSpace *
init(void)
{
	// Create a space, a space is a simulation world. It simulates the motions of rigid bodies,
	// handles collisions between them, and simulates the joints between them.
	space = cpSpaceNew();

	// Lets set some parameters of the space:
	// More iterations make the simulation more accurate but slower
	space->iterations = 10;
	// These parameters tune the efficiency of the collision detection.
	// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpSpace
	cpSpaceResizeStaticHash(space, 30.0f, 1000);
	cpSpaceResizeActiveHash(space, 30.0f, 1000);
	// Give it some gravity
	space->gravity = cpv(0, -100);

	// Create A ground segment along the bottom of the screen
	// By attaching it to &space->staticBody instead of a body, we make it a static shape.
	cpShape *ground = cpSegmentShapeNew(&space->staticBody, cpv(-320,-240), cpv(320,-240), 0.0f);
	// Set some parameters of the shape.
	// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpShape
	ground->e = 1.0f; ground->u = 1.0f;
	ground->layers = NOT_GRABABLE_MASK; // Used by the Demo mouse grabbing code
	// Add the shape to the space as a static shape
	// If a shape never changes position, add it as static so Chipmunk knows it only needs to
	// calculate collision information for it once when it is added.
	// Do not change the postion of a static shape after adding it.
	cpSpaceAddShape(space, ground);

	// Add a moving circle object.
	cpFloat radius = 15.0f;
	cpFloat mass = 10.0f;
	// This time we need to give a mass and moment of inertia when creating the circle.
	cpBody *ballBody = cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero));
	// Set some parameters of the body:
	// For more info: http://code.google.com/p/chipmunk-physics/wiki/cpBody
	ballBody->p = cpv(0, -240 + radius+50);
	ballBody->v = cpv(0, -20);
	// Add the body to the space so it will be simulated and move around.
	cpSpaceAddBody(space, ballBody);

	// Add a circle shape for the ball.
	// Shapes are always defined relative to the center of gravity of the body they are attached to.
	// When the body moves or rotates, the shape will move with it.
	// Additionally, all of the cpSpaceAdd*() functions return the thing they added so you can create and add in one go.
	cpShape *ballShape = cpSpaceAddShape(space, cpCircleShapeNew(ballBody, radius, cpvzero));
	ballShape->e = 0.0f; ballShape->u = 0.9f;

	return space;
}

// Update is called by the demo code each frame.
static void
update(int ticks)
{
	// Chipmunk allows you to use a different timestep each frame, but it works much better when you use a fixed timestep.
	// An excellent article on why fixed timesteps for game logic can be found here: http://gafferongames.com/game-physics/fix-your-timestep/
	cpSpaceStep(space, 1.0f/60.0f);
}

// destroy is called by the demo code to free all the memory we've allocated
static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Simple = {
	"Simple",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

static cpSpace *space;

static cpFloat
springForce(cpConstraint *spring, cpFloat dist)
{
	cpFloat clamp = 20.0f;
	return cpfclamp(cpDampedSpringGetRestLength(spring) - dist, -clamp, clamp)*cpDampedSpringGetStiffness(spring);
}

static cpConstraint *
new_spring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiff, cpFloat damp)
{
	cpConstraint *spring = cpDampedSpringNew(a, b, anchr1, anchr2, restLength, stiff, damp);
	cpDampedSpringSetSpringForceFunc(spring, springForce);

	return spring;
}

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
}

static cpBody *
add_bar(cpVect a, cpVect b, int group)
{
	cpVect center = cpvmult(cpvadd(a, b), 1.0f/2.0f);
	cpFloat length = cpvlength(cpvsub(b, a));
	cpFloat mass = length/160.0f;

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, mass*length*length/12.0f));
	body->p = center;

	cpShape *shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpvsub(a, center), cpvsub(b, center), 10.0f));
	shape->group = group;

	return body;
}

static cpSpace *
init(void)
{
	space = cpSpaceNew();
	cpBody *staticBody = &space->staticBody;

	cpBody *body1  = add_bar(cpv(-240,  160), cpv(-160,   80), 1);
	cpBody *body2  = add_bar(cpv(-160,   80), cpv( -80,  160), 1);
	cpBody *body3  = add_bar(cpv(   0,  160), cpv(  80,    0), 0);
	cpBody *body4  = add_bar(cpv( 160,  160), cpv( 240,  160), 0);
	cpBody *body5  = add_bar(cpv(-240,    0), cpv(-160,  -80), 2);
	cpBody *body6  = add_bar(cpv(-160,  -80), cpv( -80,    0), 2);
	cpBody *body7  = add_bar(cpv( -80,    0), cpv(   0,    0), 2);
	cpBody *body8  = add_bar(cpv(   0,  -80), cpv(  80,  -80), 0);
	cpBody *body9  = add_bar(cpv( 240,   80), cpv( 160,    0), 3);
	cpBody *body10 = add_bar(cpv( 160,    0), cpv( 240,  -80), 3);
	cpBody *body11 = add_bar(cpv(-240,  -80), cpv(-160, -160), 4);
	cpBody *body12 = add_bar(cpv(-160, -160), cpv( -80, -160), 0);
	cpBody *body13 = add_bar(cpv(   0, -160), cpv(  80, -160), 0);
	cpBody *body14 = add_bar(cpv( 160, -160), cpv( 240, -160), 0);

	cpSpaceAddConstraint(space, cpPivotJointNew2( body1,  body2, cpv( 40,-40), cpv(-40,-40)));
	cpSpaceAddConstraint(space, cpPivotJointNew2( body5,  body6, cpv( 40,-40), cpv(-40,-40)));
	cpSpaceAddConstraint(space, cpPivotJointNew2( body6,  body7, cpv( 40, 40), cpv(-40,  0)));
	cpSpaceAddConstraint(space, cpPivotJointNew2( body9, body10, cpv(-40,-40), cpv(-40, 40)));
	cpSpaceAddConstraint(space, cpPivotJointNew2(body11, body12, cpv( 40,-40), cpv(-40,  0)));

	cpFloat stiff = 100.0f;
	cpFloat damp = 0.5f;
	cpSpaceAddConstraint(space, new_spring(staticBody,  body1, cpv(-320,  240), cpv(-40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody,  body1, cpv(-320,   80), cpv(-40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody,  body1, cpv(-160,  240), cpv(-40, 40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody,  body2, cpv(-160,  240), cpv( 40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody,  body2, cpv(   0,  240), cpv( 40, 40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody,  body3, cpv(  80,  240), cpv(-40, 80), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody,  body4, cpv(  80,  240), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody,  body4, cpv( 320,  240), cpv( 40,  0), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody,  body5, cpv(-320,   80), cpv(-40, 40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody,  body9, cpv( 320,  80), cpv( 40, 40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody, body10, cpv( 320,   0), cpv( 40,-40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody, body10, cpv( 320,-160), cpv( 40,-40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody, body11, cpv(-320,-160), cpv(-40, 40), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody, body12, cpv(-240,-240), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody, body12, cpv(   0,-240), cpv( 40,  0), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody, body13, cpv(   0,-240), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody, body13, cpv(  80,-240), cpv( 40,  0), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv(  80,-240), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv( 240,-240), cpv( 40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv( 320,-160), cpv( 40,  0), 0.0f, stiff, damp));

	cpSpaceAddConstraint(space, new_spring( body1,  body5, cpv( 40,-40), cpv(-40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body1,  body6, cpv( 40,-40), cpv( 40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body2,  body3, cpv( 40, 40), cpv(-40, 80), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body4, cpv(-40, 80), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body4, cpv( 40,-80), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body7, cpv( 40,-80), cpv( 40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body7, cpv(-40, 80), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body8, cpv( 40,-80), cpv( 40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body3,  body9, cpv( 40,-80), cpv(-40,-40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body4,  body9, cpv( 40,  0), cpv( 40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body5, body11, cpv(-40, 40), cpv(-40, 40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body5, body11, cpv( 40,-40), cpv( 40,-40), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body7,  body8, cpv( 40,  0), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body8, body12, cpv(-40,  0), cpv( 40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body8, body13, cpv(-40,  0), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body8, body13, cpv( 40,  0), cpv( 40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring( body8, body14, cpv( 40,  0), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(body10, body14, cpv( 40,-40), cpv(-40,  0), 0.0f, stiff, damp));
	cpSpaceAddConstraint(space, new_spring(body10, body14, cpv( 40,-40), cpv(-40,  0), 0.0f, stiff, damp));

	return space;
}

static void
destroy(void)
{
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Springies = {
	"Springies",
	NULL,
	init,
	update,
	destroy,
};


code:
/* Copyright (c) 2007 Scott Lembcke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "chipmunk.h"
#include "drawSpace.h"
#include "ChipmunkDemo.h"

extern cpVect mousePoint;

static cpSpace *space;

static cpBody *tankBody, *tankControlBody;

static void
update(int ticks)
{
	int steps = 1;
	cpFloat dt = 1.0f/60.0f/(cpFloat)steps;

	for(int i=0; i<steps; i++){
		// turn the control body based on the angle relative to the actual body
		cpVect mouseDelta = cpvsub(mousePoint, tankBody->p);
		cpFloat turn = cpvtoangle(cpvunrotate(tankBody->rot, mouseDelta));
		cpBodySetAngle(tankControlBody, tankBody->a - turn);

		// drive the tank towards the mouse
		if(cpvnear(mousePoint, tankBody->p, 30.0f)){
			tankControlBody->v = cpvzero; // stop
		} else {
			cpFloat direction = (cpvdot(mouseDelta, tankBody->rot) > 0.0f ? 1.0f : -1.0f);
			tankControlBody->v = cpvrotate(tankBody->rot, cpv(30.0f*direction, 0.0f));
		}

		cpSpaceStep(space, dt);
	}
}

static cpBody *
add_box(cpFloat size, cpFloat mass)
{
	cpVect verts[] = {
		cpv(-size,-size),
		cpv(-size, size),
		cpv( size, size),
		cpv( size,-size),
	};

	cpFloat radius = cpvlength(cpv(size, size));

	cpBody *body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts, cpvzero)));
	body->p = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius));

	cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 4, verts, cpvzero));
	shape->e = 0.0f; shape->u = 0.7f;

	return body;
}

static cpSpace *
init(void)
{
	cpResetShapeIdCounter();

	space = cpSpaceNew();
	cpSpaceResizeActiveHash(space, 30.0f, 1000);
	space->iterations = 10;
	space->sleepTimeThreshold = 0.5f;

	cpBody *staticBody = &space->staticBody;
	cpShape *shape;

	// Create segments around the edge of the screen.
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
	shape->e = 1.0f; shape->u = 1.0f;
	shape->layers = NOT_GRABABLE_MASK;

	for(int i=0; i<50; i++){
		cpBody *body = add_box(10.0f, 1.0f);

		cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, body, cpvzero, cpvzero));
		pivot->biasCoef = 0.0f; // disable joint correction
		pivot->maxForce = 1000.0f; // emulate linear friction

		cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(staticBody, body, 0.0f, 1.0f));
		gear->biasCoef = 0.0f; // disable joint correction
		gear->maxForce = 5000.0f; // emulate angular friction
	}

	// We joint the tank to the control body and control the tank indirectly by modifying the control body.
	tankControlBody = cpBodyNew(INFINITY, INFINITY);
	tankBody = add_box(15.0f, 10.0f);

	cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero));
	pivot->biasCoef = 0.0f; // disable joint correction
	pivot->maxForce = 10000.0f; // emulate linear friction

	cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(tankControlBody, tankBody, 0.0f, 1.0f));
	gear->biasCoef = 1.0f; // limit angular correction rate
	gear->maxBias = 1.0f; // limit angular correction rate
	gear->maxForce = 500000.0f; // emulate angular friction

	return space;
}

static void
destroy(void)
{
	cpBodyFree(tankControlBody);
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
}

chipmunkDemo Tank = {
	"Tank",
	NULL,
	init,
	update,
	destroy,
};