void NaiveRotationAlgorithm::stepSystem(SystemInfo *individual) { MachineSystem *oldSystem = individual->system; individual->system = new MachineSystem(*oldSystem); // copy it to stop all the damn bouncing about delete oldSystem; cpBody *inputBody = individual->system->partAtPosition(individual->system->inputMachinePosition)->body; cpBody *outputBody = individual->system->partAtPosition(individual->system->outputMachinePosition)->body; cpSpace *systemSpace = individual->system->getSpace(); cpConstraint *motor = cpSimpleMotorNew(cpSpaceGetStaticBody(systemSpace), inputBody, M_PI); cpSpaceAddConstraint(systemSpace, motor); cpConstraintSetMaxForce(motor, 50000); for (int i=0; i<simSteps; i++) { individual->inputValues[i] = (cpBodyGetAngle(inputBody)); cpSpaceStep(systemSpace, 0.1); individual->outputValues[i] = (cpBodyGetAngle(outputBody)); } cpSpaceRemoveConstraint(systemSpace, motor); cpBodySetAngVel(outputBody, 0); cpBodySetAngle(inputBody, 0); }
static void update(int ticks) { cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y)/3.0f; cpFloat rate = ChipmunkDemoKeyboard.x*30.0f*coef; cpSimpleMotorSetRate(motor, rate); cpConstraintSetMaxForce(motor, 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]; cpVect pos = cpBodyGetPos(ball); if(pos.x > 320.0f){ cpBodySetVel(ball, cpvzero); cpBodySetPos(ball, cpv(-224.0f, 200.0f)); } } } }
static void update(cpSpace *space, double dt) { cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y)/3.0f; cpFloat rate = ChipmunkDemoKeyboard.x*10.0f*coef; cpSimpleMotorSetRate(motor, rate); cpConstraintSetMaxForce(motor, (rate) ? 100000.0f : 0.0f); cpSpaceStep(space, dt); }
/* * Chipmunk2d::Constraint#max_force=(max_force) * @param [Float] max_force */ static mrb_value constraint_set_max_force(mrb_state *mrb, mrb_value self) { cpConstraint *constraint; mrb_float max_force; mrb_get_args(mrb, "f", &max_force); constraint = mrb_data_get_ptr(mrb, self, &mrb_cp_constraint_type); cpConstraintSetMaxForce(constraint, (cpFloat)max_force); return mrb_nil_value(); }
static cpBool StickyPreSolve(cpArbiter *arb, cpSpace *space, void *data) { // We want to fudge the collisions a bit to allow shapes to overlap more. // This simulates their squishy sticky surface, and more importantly // keeps them from separating and destroying the joint. // Track the deepest collision point and use that to determine if a rigid collision should occur. cpFloat deepest = INFINITY; // Grab the contact set and iterate over them. cpContactPointSet contacts = cpArbiterGetContactPointSet(arb); for(int i=0; i<contacts.count; i++){ // Increase the distance (negative means overlaping) of the // collision to allow them to overlap more. // This value is used only for fixing the positions of overlapping shapes. cpFloat dist = contacts.points[i].dist + 2.0f*STICK_SENSOR_THICKNESS; contacts.points[i].dist = cpfmin(0.0f, dist); deepest = cpfmin(deepest, dist); } // Set the new contact point data. cpArbiterSetContactPointSet(arb, &contacts); // If the shapes are overlapping enough, then create a // joint that sticks them together at the first contact point. if(!cpArbiterGetUserData(arb) && deepest <= 0.0f){ CP_ARBITER_GET_BODIES(arb, bodyA, bodyB); // Create a joint at the contact point to hold the body in place. cpConstraint *joint = cpPivotJointNew(bodyA, bodyB, contacts.points[0].point); // Give it a finite force for the stickyness. cpConstraintSetMaxForce(joint, 3e3); // Schedule a post-step() callback to add the joint. cpSpaceAddPostStepCallback(space, PostStepAddJoint, joint, NULL); // Store the joint on the arbiter so we can remove it later. cpArbiterSetUserData(arb, joint); } // Position correction and velocity are handled separately so changing // the overlap distance alone won't prevent the collision from occuring. // Explicitly the collision for this frame if the shapes don't overlap using the new distance. return (deepest <= 0.0f); // Lots more that you could improve upon here as well: // * Modify the joint over time to make it plastic. // * Modify the joint in the post-step to make it conditionally plastic (like clay). // * Track a joint for the deepest contact point instead of the first. // * Track a joint for each contact point. (more complicated since you only get one data pointer). }
void physics_add_top_down_friction(cpBody *body, cpBody *control, float friction, cpConstraint **out_pivot, cpConstraint **out_gear) { //emulates linear friction cpConstraint *pivot = cpSpaceAddConstraint(game.space, cpPivotJointNew2( control, body, cpvzero, cpvzero )); cpConstraintSetErrorBias(pivot, cpBodyGetMass(body) * friction); cpConstraintSetMaxForce(pivot, cpBodyGetMass(body) * friction); //emulates angular friction cpConstraint *gear = cpSpaceAddConstraint(game.space, cpGearJointNew( control, body, 0, 1 )); cpConstraintSetMaxBias(gear, 0); cpConstraintSetMaxForce(gear, friction / cpBodyGetMass(body) / 10); if (out_pivot) *out_pivot = pivot; if (out_gear) *out_gear = gear; }
static void update(int ticks) { cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y)/3.0f; cpFloat rate = ChipmunkDemoKeyboard.x*10.0f*coef; cpSimpleMotorSetRate(motor, rate); cpConstraintSetMaxForce(motor, (rate) ? 100000.0f : 0.0f); int steps = 3; cpFloat dt = 1.0f/60.0f/(cpFloat)steps; for(int i=0; i<steps; i++){ cpSpaceStep(space, dt); } }
static void StickySeparate(cpArbiter *arb, cpSpace *space, void *data) { cpConstraint *joint = (cpConstraint *)cpArbiterGetUserData(arb); if(joint){ // The joint won't be removed until the step is done. // Need to disable it so that it won't apply itself. // Setting the force to 0 will do just that cpConstraintSetMaxForce(joint, 0.0f); // Perform the removal in a post-step() callback. cpSpaceAddPostStepCallback(space, PostStepRemoveJoint, joint, NULL); // NULL out the reference to the joint. // Not required, but it's a good practice. cpArbiterSetUserData(arb, NULL); } }
static void update(cpSpace *space, double dt) { cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y)/3.0f; cpFloat rate = ChipmunkDemoKeyboard.x*30.0f*coef; cpSimpleMotorSetRate(motor, rate); cpConstraintSetMaxForce(motor, rate ? 1000000.0f : 0.0f); cpSpaceStep(space, dt); for(int i=0; i<numBalls; i++){ cpBody *ball = balls[i]; cpVect pos = cpBodyGetPosition(ball); if(pos.x > 320.0f){ cpBodySetVelocity(ball, cpvzero); cpBodySetPosition(ball, cpv(-224.0f, 200.0f)); } } }
/* Mouse handling is a bit tricky. We want the user to move * tiles using the mouse but because tiles are dynamic bodies * managed by Chipmunk2D, we cannot directly control them. * This is resolved by creating a pivot joint between an * invisible mouse body that we can control and the tile body * that we cannot directly control. */ static void apply_mouse_motion(struct state* state) { struct mouse m; update_mouse(&m); int w, h; get_screen_size(&w, &h); int x = m.x_position * w; int y = m.y_position * h; cpVect mouse_pos = cpv(x, y); cpVect new_point = cpvlerp(cpBodyGetPosition(state->mouse_body), mouse_pos, 0.25f); cpBodySetVelocity( state->mouse_body, cpvmult(cpvsub(new_point, cpBodyGetPosition(state->mouse_body)), 60.0f)); cpBodySetPosition(state->mouse_body, new_point); if (m.left_click && state->mouse_joint == NULL) { cpFloat radius = 5.0; cpPointQueryInfo info = { 0 }; cpShape* shape = cpSpacePointQueryNearest(state->space, mouse_pos, radius, GRAB_FILTER, &info); if (shape && cpBodyGetMass(cpShapeGetBody(shape)) < INFINITY) { cpVect nearest = (info.distance > 0.0f ? info.point : mouse_pos); cpBody* body = cpShapeGetBody(shape); state->mouse_joint = cpPivotJointNew2(state->mouse_body, body, cpvzero, cpBodyWorldToLocal(body, nearest)); cpConstraintSetMaxForce(state->mouse_joint, 5000000.0f); cpConstraintSetErrorBias(state->mouse_joint, cpfpow(1.0f - 0.15f, 60.0f)); cpSpaceAddConstraint(state->space, state->mouse_joint); } } if (m.left_click == false && state->mouse_joint != NULL) { cpSpaceRemoveConstraint(state->space, state->mouse_joint); cpConstraintFree(state->mouse_joint); state->mouse_joint = NULL; } }
static cpSpace * init(void) { ChipmunkDemoMessageString = "Control the crane by moving the mouse. Press the down arrow to release."; space = cpSpaceNew(); cpSpaceSetIterations(space, 30); cpSpaceSetGravity(space, cpv(0, -100)); cpSpaceSetDamping(space, 0.8); 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); // Add a body for the dolly. dollyBody = cpSpaceAddBody(space, cpBodyNew(10, INFINITY)); cpBodySetPos(dollyBody, cpv(0, 100)); // Add a block so you can see it. cpSpaceAddShape(space, cpBoxShapeNew(dollyBody, 30, 30)); // Add a groove joint for it to move back and forth on. cpSpaceAddConstraint(space, cpGrooveJointNew(staticBody, dollyBody, cpv(-250, 100), cpv(250, 100), cpvzero)); // Add a pivot joint to act as a servo motor controlling it's position // By updating the anchor points of the pivot joint, you can move the dolly. dollyServo = cpSpaceAddConstraint(space, cpPivotJointNew(staticBody, dollyBody, cpBodyGetPos(dollyBody))); // Max force the dolly servo can generate. cpConstraintSetMaxForce(dollyServo, 10000); // Max speed of the dolly servo cpConstraintSetMaxBias(dollyServo, 100); // You can also change the error bias to control how it slows down. //cpConstraintSetErrorBias(dollyServo, 0.2); // Add the crane hook. cpBody *hookBody = cpSpaceAddBody(space, cpBodyNew(1, INFINITY)); cpBodySetPos(hookBody, cpv(0, 50)); // Add a sensor shape for it. This will be used to figure out when the hook touches a box. shape = cpSpaceAddShape(space, cpCircleShapeNew(hookBody, 10, cpvzero)); cpShapeSetSensor(shape, cpTrue); cpShapeSetCollisionType(shape, HOOK_SENSOR); // Add a slide joint to act as a winch motor // By updating the max length of the joint you can make it pull up the load. winchServo = cpSpaceAddConstraint(space, cpSlideJointNew(dollyBody, hookBody, cpvzero, cpvzero, 0, INFINITY)); // Max force the dolly servo can generate. cpConstraintSetMaxForce(winchServo, 30000); // Max speed of the dolly servo cpConstraintSetMaxBias(winchServo, 60); // TODO cleanup // Finally a box to play with cpBody *boxBody = cpSpaceAddBody(space, cpBodyNew(30, cpMomentForBox(30, 50, 50))); cpBodySetPos(boxBody, cpv(200, -200)); // Add a block so you can see it. shape = cpSpaceAddShape(space, cpBoxShapeNew(boxBody, 50, 50)); cpShapeSetFriction(shape, 0.7); cpShapeSetCollisionType(shape, CRATE); cpSpaceAddCollisionHandler(space, HOOK_SENSOR, CRATE, (cpCollisionBeginFunc)HookCrate, NULL, NULL, NULL, NULL); return space; }
cpSpace *Chains::Init() { ChipmunkDemo::Init(); space = cpSpaceNew(); cpSpaceSetIterations(space, 30); cpSpaceSetGravity(space, cpv(0, -100)); cpSpaceSetSleepTimeThreshold(space, 0.5f); cpBody *body, *staticBody = cpSpaceGetStaticBody(space); cpShape *shape; // Create segments around the edge of the screen. shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); cpFloat mass = 1; cpFloat width = 20; cpFloat height = 30; cpFloat spacing = width*0.3; // Add lots of boxes. for(int i=0; i<CHAIN_COUNT; i++){ cpBody *prev = NULL; for(int j=0; j<LINK_COUNT; j++){ cpVect pos = cpv(40*(i - (CHAIN_COUNT - 1)/2.0), 240 - (j + 0.5)*height - (j + 1)*spacing); body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); cpBodySetPosition(body, pos); shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpv(0, (height - width)/2.0), cpv(0, (width - height)/2.0), width/2.0)); cpShapeSetFriction(shape, 0.8f); cpFloat breakingForce = 80000; cpConstraint *constraint = NULL; if(prev == NULL){ constraint = cpSpaceAddConstraint(space, cpSlideJointNew(body, staticBody, cpv(0, height/2), cpv(pos.x, 240), 0, spacing)); } else { constraint = cpSpaceAddConstraint(space, cpSlideJointNew(body, prev, cpv(0, height/2), cpv(0, -height/2), 0, spacing)); } cpConstraintSetMaxForce(constraint, breakingForce); cpConstraintSetPostSolveFunc(constraint, BreakableJointPostSolve); cpConstraintSetCollideBodies(constraint, cpFalse); prev = body; } } cpFloat radius = 15.0f; body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); cpBodySetPosition(body, cpv(0, -240 + radius+5)); cpBodySetVelocity(body, cpv(0, 300)); shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); cpShapeSetElasticity(shape, 0.0f); cpShapeSetFriction(shape, 0.9f); return space; }
void SG_CALL sgPhysicsConstraintSetMaxForce(SGPhysicsConstraint* constr, float max) { cpConstraintSetMaxForce(constr->handle, max); }
void CCJoint::setMaxForce(cpFloat maxForce) { cpConstraintSetMaxForce(this->m_constraint, maxForce); }