1 2 // written in the D programming language 3 4 module samples.Planet; 5 6 import dchip.all; 7 8 import samples.ChipmunkDemo; 9 10 static cpSpace *space; 11 static cpBody *planetBody; 12 13 static cpFloat gravityStrength = 5.0e6f; 14 15 static void 16 update(int ticks) 17 { 18 int steps = 1; 19 cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps; 20 21 for(int i=0; i<steps; i++){ 22 cpSpaceStep(space, dt); 23 24 // Update the static body spin so that it looks like it's rotating. 25 cpBodyUpdatePosition(planetBody, dt); 26 } 27 } 28 29 static void 30 planetGravityVelocityFunc(cpBody *_body, cpVect gravity, cpFloat damping, cpFloat dt) 31 { 32 // Gravitational acceleration is proportional to the inverse square of 33 // distance, and directed toward the origin. The central planet is assumed 34 // to be massive enough that it affects the satellites but not vice versa. 35 cpVect p = _body.p; 36 cpFloat sqdist = cpvlengthsq(p); 37 cpVect g = cpvmult(p, -gravityStrength / (sqdist * cpfsqrt(sqdist))); 38 39 cpBodyUpdateVelocity(_body, g, damping, dt); 40 } 41 42 static cpVect 43 rand_pos(cpFloat radius) 44 { 45 cpVect v; 46 do { 47 v = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius)); 48 } while(cpvlength(v) < 85.0f); 49 50 return v; 51 } 52 53 static void 54 add_box() 55 { 56 const cpFloat size = 10.0f; 57 const cpFloat mass = 1.0f; 58 59 cpVect verts[] = [ 60 cpv(-size,-size), 61 cpv(-size, size), 62 cpv( size, size), 63 cpv( size,-size), 64 ]; 65 66 cpFloat radius = cpvlength(cpv(size, size)); 67 68 cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts.ptr, cpvzero))); 69 _body.velocity_func = &planetGravityVelocityFunc; 70 _body.p = rand_pos(radius); 71 72 // Set the box's velocity to put it into a circular orbit from its 73 // starting position. 74 cpFloat r = cpvlength(_body.p); 75 cpFloat v = cpfsqrt(gravityStrength / r) / r; 76 _body.v = cpvmult(cpvperp(_body.p), v); 77 78 // Set the box's angular velocity to match its orbital period and 79 // align its initial angle with its position. 80 _body.w = v; 81 cpBodySetAngle(_body, cpfatan2(_body.p.y, _body.p.x)); 82 83 cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(_body, 4, verts.ptr, cpvzero)); 84 shape.e = 0.0f; shape.u = 0.7f; 85 } 86 87 static cpSpace * 88 init() 89 { 90 planetBody = cpBodyNew(INFINITY, INFINITY); 91 planetBody.w = 0.2f; 92 93 cpResetShapeIdCounter(); 94 95 space = cpSpaceNew(); 96 space.iterations = 20; 97 98 for(int i=0; i<30; i++) 99 add_box(); 100 101 cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(planetBody, 70.0f, cpvzero)); 102 shape.e = 1.0f; shape.u = 1.0f; 103 shape.layers = NOT_GRABABLE_MASK; 104 105 return space; 106 } 107 108 static void 109 destroy() 110 { 111 cpBodyFree(planetBody); 112 ChipmunkDemoFreeSpaceChildren(space); 113 cpSpaceFree(space); 114 } 115 116 chipmunkDemo Planet = { 117 "Planet", 118 null, 119 &init, 120 &update, 121 &destroy, 122 };