void RCPBody::applyImpulse(RVector const & impulse) { if (mBody) { cpBodyApplyImpulseAtWorldPoint(mBody, cpv(impulse.x(), impulse.y()), cpBodyLocalToWorld(mBody, cpBodyGetCenterOfGravity(mBody))); } }
void Slice::ClipPoly(cpSpace *space, cpShape *shape, cpVect n, cpFloat dist) { cpBody *body = cpShapeGetBody(shape); int count = cpPolyShapeGetCount(shape); int clippedCount = 0; cpVect *clipped = (cpVect *)alloca((count + 1)*sizeof(cpVect)); for(int i=0, j=count-1; i<count; j=i, i++){ cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, j)); cpFloat a_dist = cpvdot(a, n) - dist; if(a_dist < 0.0){ clipped[clippedCount] = a; clippedCount++; } cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, i)); cpFloat b_dist = cpvdot(b, n) - dist; if(a_dist*b_dist < 0.0f){ cpFloat t = cpfabs(a_dist)/(cpfabs(a_dist) + cpfabs(b_dist)); clipped[clippedCount] = cpvlerp(a, b, t); clippedCount++; } } cpVect centroid = cpCentroidForPoly(clippedCount, clipped); cpFloat mass = cpAreaForPoly(clippedCount, clipped, 0.0f)*DENSITY; cpFloat moment = cpMomentForPoly(mass, clippedCount, clipped, cpvneg(centroid), 0.0f); cpBody *new_body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); cpBodySetPosition(new_body, centroid); cpBodySetVelocity(new_body, cpBodyGetVelocityAtWorldPoint(body, centroid)); cpBodySetAngularVelocity(new_body, cpBodyGetAngularVelocity(body)); cpTransform transform = cpTransformTranslate(cpvneg(centroid)); cpShape *new_shape = cpSpaceAddShape(space, cpPolyShapeNew(new_body, clippedCount, clipped, transform, 0.0)); // Copy whatever properties you have set on the original shape that are important cpShapeSetFriction(new_shape, cpShapeGetFriction(shape)); }
int applykeys(Ship* s, bool* keylist) { if (keylist[0]) cpBodyApplyForceAtLocalPoint(s->body, cpv(0, 1e7), cpv(0.5, 0)); if (keylist[1]) cpBodyApplyForceAtLocalPoint(s->body, cpv(0, -1e6), cpv(0.5, 3)); if (keylist[2]) { cpBodyApplyForceAtLocalPoint(s->body, cpv(1e6, 0), cpv(0, 0)); cpBodyApplyForceAtLocalPoint(s->body, cpv(-1e6, 0), cpv(1, 3)); } if (keylist[3]) { cpBodyApplyForceAtLocalPoint(s->body, cpv(1e6, 0), cpv(0, 3)); cpBodyApplyForceAtLocalPoint(s->body, cpv(-1e6, 0), cpv(1, 0)); } if (keylist[4]) { cpBodyApplyForceAtLocalPoint(s->body, cpv(-1e6, 0), cpv(1, 3)); cpBodyApplyForceAtLocalPoint(s->body, cpv(-1e6, 0), cpv(1, 0)); } if (keylist[5]) { cpBodyApplyForceAtLocalPoint(s->body, cpv(1e6, 0), cpv(0, 3)); cpBodyApplyForceAtLocalPoint(s->body, cpv(1e6, 0), cpv(0, 0)); } if (keylist[6] && last_time_updated - s->last_fired > 1) { cpVect tip = cpBodyLocalToWorld(s->body, nosev + cpv(0, 0.1)); cpVect base = cpBodyLocalToWorld(s->body, cpv(0.5, 0)); cpVect newvel = cpvnormalize(tip - base) * shell_muzzle_vel + cpBodyGetVelocityAtLocalPoint(s->body, nosev); Shell* newshell = addshell(tip, newvel, cpBodyGetAngle(s->body)); cpBodyApplyImpulseAtLocalPoint(s->body, cpv(0, -1)*cpBodyGetMass(newshell->body)*shell_muzzle_vel, cpv(0.5, 3)); s->last_fired = last_time_updated; } return 0; }
Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const { cpVect cog = cpBodyGetCenterOfGravity(m_handle); switch (coordSys) { case CoordSys_Global: cog = cpBodyLocalToWorld(m_handle, cog); break; case CoordSys_Local: break; // Nothing to do } return Vector2f(static_cast<float>(cog.x), static_cast<float>(cog.y)); }
Vec2 PhysicsBody::local2World(const Vec2& point) { return PhysicsHelper::cpv2point(cpBodyLocalToWorld(_cpBody, PhysicsHelper::point2cpv(point))); }
struct gun instantiate_gun(struct obj *owner, const char *gunType, const char *bulletType) { // fprintf(stderr, "\n\n\n%s\n\n\n", bulletType); struct gun ret = {.bulletType = strdup(bulletType), .owner = owner, .cooldown = owner->room->ticks}; ret.fire = guntbl_find(&fires, gunType); return ret; } void machinegun_fire(struct gun *self) { if (self->owner->room->ticks - self->cooldown > 1) { struct obj *bullet = instantiate_object(self->bulletType, self->owner->objectVect, self->owner->room); cpBodySetPosition(bullet->body, cpBodyLocalToWorld(self->owner->body, cpv(0, -self->owner->radius - bullet->radius - 2))); cpBodySetMoment(bullet->body, cpMomentForCircle(10000.0, 0.0, bullet->radius*2, cpvzero)); cpBodySetAngle(bullet->body, cpBodyGetAngle(self->owner->body) + M_PI); ((struct bullet_extra*)bullet->extra)->speed = 20.0; ((struct bullet_extra*)bullet->extra)->owner = self->owner; cpBodyApplyImpulseAtLocalPoint(self->owner->body, cpv(0, 50.0), cpv(0, -(self->owner->radius * 2))); self->cooldown = self->owner->room->ticks; } } struct gunpair { const char *name; const gunmethod method; }; void register_guns(void) { struct gunpair pairs[] = {{"machine gun", machinegun_fire}}; for (size_t i = 0; i < ARRAY_LENGTH(pairs); i++) { char *currentName = pairs[i].name; gunmethod currentMethod = pairs[i].method; if ((!currentName && currentMethod) || (currentName && !currentMethod)) { CROAK("Unevenly sized methodpair array"); } guntbl_insert(&fires, currentName, currentMethod); } } void guntbl_insert(struct guntbl *table, const char *key, gunmethod method) { int offset = hash(key) % 32; if (table->keys[offset]) { if (strcmp(table->keys[offset], key) == 0 ) { table->methods[offset] = method; } else { if (!table->next) { table->next = malloc(sizeof(struct guntbl)); *table->next = (struct guntbl){.next = NULL}; } guntbl_insert(table->next, key, method); } } else {
cpBool Buoyancy::WaterPreSolve(cpArbiter *arb, cpSpace *space, void *ptr) { CP_ARBITER_GET_SHAPES(arb, water, poly); cpBody *body = cpShapeGetBody(poly); // Get the top of the water sensor bounding box to use as the water level. cpFloat level = cpShapeGetBB(water).t; // Clip the polygon against the water level int count = cpPolyShapeGetCount(poly); int clippedCount = 0; #ifdef _MSC_VER // MSVC is pretty much the only compiler in existence that doesn't support variable sized arrays. cpVect clipped[10]; #else cpVect clipped[count + 1]; #endif for(int i=0, j=count-1; i<count; j=i, i++){ cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, j)); cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, i)); if(a.y < level){ clipped[clippedCount] = a; clippedCount++; } cpFloat a_level = a.y - level; cpFloat b_level = b.y - level; if(a_level*b_level < 0.0f){ cpFloat t = cpfabs(a_level)/(cpfabs(a_level) + cpfabs(b_level)); clipped[clippedCount] = cpvlerp(a, b, t); clippedCount++; } } // Calculate buoyancy from the clipped polygon area cpFloat clippedArea = cpAreaForPoly(clippedCount, clipped, 0.0f); cpFloat displacedMass = clippedArea*FLUID_DENSITY; cpVect centroid = cpCentroidForPoly(clippedCount, clipped); cpDataPointer data = ptr; DrawPolygon(clippedCount, clipped, 0.0f, RGBAColor(0, 0, 1, 1), RGBAColor(0, 0, 1, 0.1f), data); DrawDot(5, centroid, RGBAColor(0, 0, 1, 1), data); cpFloat dt = cpSpaceGetCurrentTimeStep(space); cpVect g = cpSpaceGetGravity(space); // Apply the buoyancy force as an impulse. cpBodyApplyImpulseAtWorldPoint(body, cpvmult(g, -displacedMass*dt), centroid); // Apply linear damping for the fluid drag. cpVect v_centroid = cpBodyGetVelocityAtWorldPoint(body, centroid); cpFloat k = k_scalar_body(body, centroid, cpvnormalize(v_centroid)); cpFloat damping = clippedArea*FLUID_DRAG*FLUID_DENSITY; cpFloat v_coef = cpfexp(-damping*dt*k); // linear drag // cpFloat v_coef = 1.0/(1.0 + damping*dt*cpvlength(v_centroid)*k); // quadratic drag cpBodyApplyImpulseAtWorldPoint(body, cpvmult(cpvsub(cpvmult(v_centroid, v_coef), v_centroid), 1.0/k), centroid); // Apply angular damping for the fluid drag. cpVect cog = cpBodyLocalToWorld(body, cpBodyGetCenterOfGravity(body)); cpFloat w_damping = cpMomentForPoly(FLUID_DRAG*FLUID_DENSITY*clippedArea, clippedCount, clipped, cpvneg(cog), 0.0f); cpBodySetAngularVelocity(body, cpBodyGetAngularVelocity(body)*cpfexp(-w_damping*dt/cpBodyGetMoment(body))); return cpTrue; }