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 };