/* 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; } }
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 RigidBody2D::SetVelocity(const Vector2f& velocity) { cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y)); }
cpSpace *Buoyancy::Init() { ChipmunkDemo::Init(); space = cpSpaceNew(); cpSpaceSetIterations(space, 30); cpSpaceSetGravity(space, cpv(0, -500)); // cpSpaceSetDamping(space, 0.5); cpSpaceSetSleepTimeThreshold(space, 0.5f); cpSpaceSetCollisionSlop(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); { // Add the edges of the bucket cpBB bb = cpBBNew(-300, -200, 100, 0); cpFloat radius = 5.0f; shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.l, bb.b), cpv(bb.l, bb.t), radius)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.r, bb.b), cpv(bb.r, bb.t), radius)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.l, bb.b), cpv(bb.r, bb.b), radius)); cpShapeSetElasticity(shape, 1.0f); cpShapeSetFriction(shape, 1.0f); cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); // Add the sensor for the water. shape = cpSpaceAddShape(space, cpBoxShapeNew2(staticBody, bb, 0.0)); cpShapeSetSensor(shape, cpTrue); cpShapeSetCollisionType(shape, 1); } { cpFloat width = 200.0f; cpFloat height = 50.0f; cpFloat mass = 0.3*FLUID_DENSITY*width*height; cpFloat moment = cpMomentForBox(mass, width, height); body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); cpBodySetPosition(body, cpv(-50, -100)); cpBodySetVelocity(body, cpv(0, -100)); cpBodySetAngularVelocity(body, 1); shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); cpShapeSetFriction(shape, 0.8f); } { cpFloat width = 40.0f; cpFloat height = width*2; cpFloat mass = 0.3*FLUID_DENSITY*width*height; cpFloat moment = cpMomentForBox(mass, width, height); body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); cpBodySetPosition(body, cpv(-200, -50)); cpBodySetVelocity(body, cpv(0, -100)); cpBodySetAngularVelocity(body, 1); shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); cpShapeSetFriction(shape, 0.8f); } cpCollisionHandler *handler = cpSpaceAddCollisionHandler(space, 1, 0); handler->preSolveFunc = (cpCollisionPreSolveFunc)WaterPreSolve; handler->userData = this; return space; }