To fix the problem, what I want to do is pick an arbitrary safe threshold along the x-axis (say 1000) and once the environment moves past that point, take everything in the Chipmunk space (area of anywhere from 950 - 1050) and shift it back to 0. I'm happy and comfortable to lightly hack into the Chipmunk source code (6.1.1) to make this happen. To that effect, I've added a new cpSpace function (below) that attempts to shift the entire space by a given offset.
Code: Select all
void cpSpaceOffset(cpSpace* space, cpVect offset) {
// Shift all bodies (secretly)
for (int i=0; i<space->bodies->num; i++) {
cpBody* body = space->bodies->arr[i];
// Update body position without waking it up if it was sleeping
cpBodyPlaceBody(body, cpvadd(body->p, offset), body->a, body->v, body->w);
cpSpaceReindexShapesForBody(space, body);
}
// Shift all static shapes (manually)
::pseudo code: loop through all static shapes in the space and for each::
cpShape* shape = ...;
switch(shape->klass->type){
case CP_CIRCLE_SHAPE: {
cpCircleShape *circle = (cpCircleShape *)shape;
circle->c = cpvadd(circle->c, offset);
break;
}
case CP_SEGMENT_SHAPE: {
cpSegmentShape *seg = (cpSegmentShape *)shape;
seg->a = cpvadd(seg->a, offset);
seg->b = cpvadd(seg->b, offset);
break;
}
case CP_POLY_SHAPE: {
cpPolyShape *poly = (cpPolyShape *)shape;
for (int i=0; i<poly->numVerts; i++) {
poly->verts[i] = cpvadd(poly->verts[i], offset);
}
break;
}
default: break;
}
:: end loop ::
cpSpaceReindexStatic(space);
// Shift all contact points in a desperate attempt to preserve collisions
for (int i=0; i<space->arbiters->num; i++) {
cpArbiter* arb = space->arbiters->arr[i];
int c = cpArbiterGetCount(arb);
for (int j=0; j<c; j++) {
cpContact* ct = &arb->contacts[j];
ct->p = cpvadd(ct->p, offset);
}
}
}