Ejemplo n.º 1
0
static void
make_leg(cpSpace *space, cpFloat side, cpFloat offset, cpBody *chassis, cpBody *crank, cpVect anchor)
{
	cpVect a, b;
	cpShape *shape;
	
	cpFloat leg_mass = 1.0f;

	// make leg
	a = cpvzero, b = cpv(0.0f, side);
	cpBody *upper_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f)));
	cpBodySetPosition(upper_leg, cpv(offset, 0.0f));
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(upper_leg, a, b, seg_radius));
	cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES));
	
	cpSpaceAddConstraint(space, cpPivotJointNew2(chassis, upper_leg, cpv(offset, 0.0f), cpvzero));
	
	// lower leg
	a = cpvzero, b = cpv(0.0f, -1.0f*side);
	cpBody *lower_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f)));
	cpBodySetPosition(lower_leg, cpv(offset, -side));
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(lower_leg, a, b, seg_radius));
	cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES));
	
	shape = cpSpaceAddShape(space, cpCircleShapeNew(lower_leg, seg_radius*2.0f, b));
	cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 1.0f);
	
	cpSpaceAddConstraint(space, cpPinJointNew(chassis, lower_leg, cpv(offset, 0.0f), cpvzero));
	
	cpSpaceAddConstraint(space, cpGearJointNew(upper_leg, lower_leg, 0.0f, 1.0f));
	
	cpConstraint *constraint;
	cpFloat diag = cpfsqrt(side*side + offset*offset);
	
	constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, upper_leg, anchor, cpv(0.0f, side)));
	cpPinJointSetDist(constraint, diag);
	
	constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, lower_leg, anchor, cpvzero));
	cpPinJointSetDist(constraint, diag);
}
Ejemplo n.º 2
0
SGPhysicsConstraint* SG_CALL sgPhysicsConstraintCreatePin(SGPhysicsBody* body1, SGPhysicsBody* body2, float x1, float y1, float x2, float y2)
{
    SGPhysicsConstraint* constr = sgPhysicsConstraintCreate(body1, body2, SG_CONSTRAINT_PIN);
    if(!constr) return NULL;

    constr->handle = cpPinJointNew(body1->handle, body2->handle, cpv(x1, y1), cpv(x2, y2));
    _postCreate(constr);

    return constr;
}
Ejemplo n.º 3
0
WorldConstraint_t *worldConstr_createPinJoint(WorldEntity_t *a, WorldEntity_t *b, vec2_t aAnchorA, vec2_t aAnchorB)
{
    dynamo_assert(a->world == b->world, "Entities are not in the same world");
    WorldConstraint_t *ret = obj_create_autoreleased(&Class_WorldConstraint);
    ret->world = a->world;
    ret->a = obj_retain(a);
    ret->b = obj_retain(b);
    ret->type = kWorldJointType_Pin;
    ret->cpConstraint = cpPinJointNew(a->cpBody, b->cpBody, VEC2_TO_CPV(aAnchorA), VEC2_TO_CPV(aAnchorB));
    cpSpaceAddConstraint(ret->world->cpSpace, ret->cpConstraint);
    return ret;
}
Ejemplo n.º 4
0
bool PhysicsJointDistance::createConstraints()
{
    do
    {
        auto joint = cpPinJointNew(_bodyA->getCPBody(),
            _bodyB->getCPBody(),
            PhysicsHelper::point2cpv(_anchr1),
            PhysicsHelper::point2cpv(_anchr2));
        CC_BREAK_IF(joint == nullptr);
        _cpConstraints.push_back(joint);

        return true;
    } while (false);

    return false;
}
Ejemplo n.º 5
0
cpConstraint *cpSpaceSerializer::createPinJoint(TiXmlElement *elm)
{
	cpConstraint *constraint;
	
	cpVect anchr1 = createPoint("anchr1", elm);
	cpVect anchr2 = createPoint("anchr2", elm);
	
	cpBody *a;
	cpBody *b;
	createBodies(elm, &a, &b);
	
	constraint = cpPinJointNew(a, b, anchr1, anchr2);
	
	((cpPinJoint*)constraint)->dist = createValue<cpFloat>("dist", elm);
	//((cpPinJoint*)constraint)->jnAcc = createValue<cpFloat>("jnAcc", elm);
	
	return constraint;
}
Ejemplo n.º 6
0
bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2)
{
    do
    {
        CC_BREAK_IF(!PhysicsJoint::init(a, b));
        
        auto constraint = cpPinJointNew(a->getCPBody(),
                                            b->getCPBody(),
                                            PhysicsHelper::point2cpv(anchr1),
                                            PhysicsHelper::point2cpv(anchr2));
        
        CC_BREAK_IF(constraint == nullptr);
        
        _cpConstraints.push_back(constraint);
        
        return true;
    } while (false);
    
    return false;
}
bool PhysicsJointDistance::init(PhysicsBody* a, PhysicsBody* b, const Point& anchr1, const Point& anchr2)
{
    do
    {
        CC_BREAK_IF(!PhysicsJoint::init(a, b));
        
        cpConstraint* joint = cpPinJointNew(getBodyInfo(a)->getBody(),
                                            getBodyInfo(b)->getBody(),
                                            PhysicsHelper::point2cpv(anchr1),
                                            PhysicsHelper::point2cpv(anchr2));
        
        CC_BREAK_IF(joint == nullptr);
        
        m_pInfo->add(joint);
        
        return true;
    } while (false);
    
    return false;
}
Ejemplo n.º 8
0
cpJoint * bmx_cppinjoint_create(BBObject * handle, cpBody * bodyA, cpBody * bodyB, cpVect * anchor1, cpVect * anchor2) {
	cpJoint * joint = cpPinJointNew(bodyA, bodyB, *anchor1, *anchor2);
	cpbind(joint, handle);
	return joint;
}
Ejemplo n.º 9
0
static cpSpace *
init(void)
{
	ChipmunkDemoMessageString = "Use the arrow keys to control the machine.";
	
	space = cpSpaceNew();
	cpSpaceSetGravity(space, cpv(0, -600));
	
	cpBody *staticBody = cpSpaceGetStaticBody(space);
	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));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256,16), cpv(-192,0), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,0), cpv(-192, -64), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,-64), cpv(-128,144), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,80), cpv(-192,176), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192,176), cpv(-128,240), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);

	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128,144), cpv(192,64), 2.0f));
	cpShapeSetElasticity(shape, 0.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, 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));
	cpBodySetPos(plunger, cpv(-160,-80));
	
	shape = cpSpaceAddShape(space, cpPolyShapeNew(plunger, 4, verts, cpvzero));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 0.5f);
	cpShapeSetLayers(shape, 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)));
	cpBodySetPos(smallGear, cpv(-160,-160));
	cpBodySetAngle(smallGear, -M_PI_2);

	shape = cpSpaceAddShape(space, cpCircleShapeNew(smallGear, 80.0f, cpvzero));
	cpShapeSetLayers(shape, 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)));
	cpBodySetPos(bigGear, cpv(80,-160));
	cpBodySetAngle(bigGear, M_PI_2);
	
	shape = cpSpaceAddShape(space, cpCircleShapeNew(bigGear, 160.0f, cpvzero));
	cpShapeSetLayers(shape, 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, -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))));
	cpBodySetPos(feeder, 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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
static cpSpace *
init(void)
{
	space = cpSpaceNew();
	cpSpaceSetIterations(space, 10);
	cpSpaceSetGravity(space, cpv(0, -100));
	cpSpaceSetSleepTimeThreshold(space, 0.5f);
	
	cpBody *staticBody = cpSpaceGetStaticBody(space);
	cpShape *shape;
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,120), cpv(320,120), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,0), cpv(320,0), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-120), cpv(320,-120), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160,-240), cpv(-160,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0,-240), cpv(0,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(160,-240), cpv(160,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
	
	shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
	cpShapeSetElasticity(shape, 1.0f);
	cpShapeSetFriction(shape, 1.0f);
	cpShapeSetLayers(shape, 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, -M_PI_2, 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, 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, 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, 10.0f));
	cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel2, cpv( 30, 0), cpvzero, 50.0f, 20.0f, 10.0f));
	
	return space;
}