1 
2 // written in the D programming language
3 
4 module samples.Tank;
5 
6 import dchip.all;
7 
8 import samples.ChipmunkDemo;
9 
10 import gameApp;
11 
12 static cpSpace *space;
13 
14 static cpBody *tankBody;
15 static cpBody *tankControlBody;
16 
17 static void
18 update(int ticks)
19 {
20     enum int steps = 1;
21     enum cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
22 
23     for(int i=0; i<steps; i++){
24         // turn the control _body based on the angle relative to the actual _body
25         cpVect mouseDelta = cpvsub(mousePos, tankBody.p);
26         cpFloat turn = cpvtoangle(cpvunrotate(tankBody.rot, mouseDelta));
27         cpBodySetAngle(tankControlBody, tankBody.a - turn);
28 
29         // drive the tank towards the mouse
30         if(cpvnear(mousePos, tankBody.p, 30.0)){
31             tankControlBody.v = cpvzero; // stop
32         } else {
33             cpFloat direction = (cpvdot(mouseDelta, tankBody.rot) > 0.0 ? 1.0 : -1.0);
34             tankControlBody.v = cpvrotate(tankBody.rot, cpv(30.0f*direction, 0.0f));
35         }
36 
37         cpSpaceStep(space, dt);
38     }
39 }
40 
41 static cpBody *
42 add_box(cpFloat size, cpFloat mass)
43 {
44     cpVect verts[] = [
45         cpv(-size,-size),
46         cpv(-size, size),
47         cpv( size, size),
48         cpv( size,-size),
49     ];
50 
51     cpFloat radius = cpvlength(cpv(size, size));
52 
53     cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts.ptr, cpvzero)));
54     _body.p = cpv(frand()*(640 - 2*radius) - (320 - radius), frand()*(480 - 2*radius) - (240 - radius));
55 
56     cpShape *shape = cpSpaceAddShape(space, cpPolyShapeNew(_body, 4, verts.ptr, cpvzero));
57     shape.e = 0.0f; shape.u = 0.7f;
58 
59     return _body;
60 }
61 
62 static cpSpace *
63 init()
64 {
65     cpResetShapeIdCounter();
66 
67     space = cpSpaceNew();
68     space.iterations = 10;
69     space.sleepTimeThreshold = 0.5f;
70 
71     cpBody *staticBody = space.staticBody;
72     cpShape *shape;
73 
74     // Create segments around the edge of the screen.
75     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(-320,240), 0.0f));
76     shape.e = 1.0f; shape.u = 1.0f;
77     shape.layers = NOT_GRABABLE_MASK;
78 
79     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320,-240), cpv(320,240), 0.0f));
80     shape.e = 1.0f; shape.u = 1.0f;
81     shape.layers = NOT_GRABABLE_MASK;
82 
83     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f));
84     shape.e = 1.0f; shape.u = 1.0f;
85     shape.layers = NOT_GRABABLE_MASK;
86 
87     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320,240), cpv(320,240), 0.0f));
88     shape.e = 1.0f; shape.u = 1.0f;
89     shape.layers = NOT_GRABABLE_MASK;
90 
91     for(int i=0; i<50; i++){
92         cpBody *_body = add_box(10.0, 1.0);
93 
94         cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, _body, cpvzero, cpvzero));
95         pivot.errorBias = 1.0f; // disable joint correction
96         pivot.maxForce = 1000.0f; // emulate linear friction
97 
98         cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(staticBody, _body, 0.0f, 1.0f));
99         gear.errorBias = 1.0f; // disable joint correction
100         gear.maxForce = 5000.0f; // emulate angular friction
101     }
102 
103     // We joint the tank to the control _body and control the tank indirectly by modifying the control _body.
104     tankControlBody = cpBodyNew(INFINITY, INFINITY);
105     tankBody = add_box(15.0, 10.0);
106 
107     cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero));
108     pivot.errorBias = 1.0f; // disable joint correction
109     pivot.maxForce = 10000.0f; // emulate linear friction
110 
111     cpConstraint *gear = cpSpaceAddConstraint(space, cpGearJointNew(tankControlBody, tankBody, 0.0f, 1.0f));
112     gear.errorBias = 0.0f; // attempt to fully correct the joint each step
113     gear.maxBias = 1.0f; // but limit it's angular correction rate
114     gear.maxForce = 500000.0f; // emulate angular friction
115 
116     return space;
117 }
118 
119 static void
120 destroy()
121 {
122     cpBodyFree(tankControlBody);
123     ChipmunkDemoFreeSpaceChildren(space);
124     cpSpaceFree(space);
125 }
126 
127 chipmunkDemo Tank = {
128     "Tank",
129     null,
130     &init,
131     &update,
132     &destroy,
133 };