16
|
1
|
|
2 // written in the D programming language
|
|
3
|
|
4 module samples.Planet;
|
|
5
|
|
6 import chipmunkd.chipmunk;
|
|
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 cpSpaceResizeActiveHash(space, 30.0f, 10000);
|
|
97 space.iterations = 20;
|
|
98
|
|
99 for(int i=0; i<30; i++)
|
|
100 add_box();
|
|
101
|
|
102 cpShape *shape = cpSpaceAddShape(space, cpCircleShapeNew(planetBody, 70.0f, cpvzero));
|
|
103 shape.e = 1.0f; shape.u = 1.0f;
|
|
104 shape.layers = NOT_GRABABLE_MASK;
|
|
105
|
|
106 return space;
|
|
107 }
|
|
108
|
|
109 static void
|
|
110 destroy()
|
|
111 {
|
|
112 cpBodyFree(planetBody);
|
|
113 cpSpaceFreeChildren(space);
|
|
114 cpSpaceFree(space);
|
|
115 }
|
|
116
|
|
117 chipmunkDemo Planet = {
|
|
118 "Planet",
|
|
119 null,
|
|
120 &init,
|
|
121 &update,
|
|
122 &destroy,
|
|
123 };
|