1 /* 2 * Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 module demo.Plink; 23 24 import core.stdc.stdlib; 25 26 import std.math; 27 28 import demo.dchip; 29 30 import demo.ChipmunkDebugDraw; 31 import demo.ChipmunkDemo; 32 import demo.types; 33 34 cpFloat pentagon_mass = 0.0f; 35 cpFloat pentagon_moment = 0.0f; 36 37 // Iterate over all of the bodies and reset the ones that have fallen offscreen. 38 void eachBody(cpBody* body_, void* unused) 39 { 40 cpVect pos = cpBodyGetPos(body_); 41 42 if (pos.y < -260 || cpfabs(pos.x) > 340) 43 { 44 cpFloat x = rand() / cast(cpFloat)RAND_MAX * 640 - 320; 45 cpBodySetPos(body_, cpv(x, 260)); 46 } 47 } 48 49 void update(cpSpace* space, double dt) 50 { 51 if (ChipmunkDemoRightDown) 52 { 53 cpShape* nearest = cpSpaceNearestPointQueryNearest(space, ChipmunkDemoMouse, 0.0, GRABABLE_MASK_BIT, CP_NO_GROUP, null); 54 55 if (nearest) 56 { 57 cpBody* body_ = cpShapeGetBody(nearest); 58 59 if (cpBodyIsStatic(body_)) 60 { 61 cpSpaceConvertBodyToDynamic(space, body_, pentagon_mass, pentagon_moment); 62 cpSpaceAddBody(space, body_); 63 } 64 else 65 { 66 cpSpaceRemoveBody(space, body_); 67 cpSpaceConvertBodyToStatic(space, body_); 68 } 69 } 70 } 71 72 cpSpaceStep(space, dt); 73 cpSpaceEachBody(space, &eachBody, null); 74 } 75 76 enum NUM_VERTS = 5; 77 78 cpSpace* init() 79 { 80 ChipmunkDemoMessageString = "Right click to make pentagons static/dynamic.\0".dup; 81 82 cpSpace* space = cpSpaceNew(); 83 cpSpaceSetIterations(space, 5); 84 cpSpaceSetGravity(space, cpv(0, -100)); 85 86 cpBody * body_; 87 cpBody * staticBody = cpSpaceGetStaticBody(space); 88 cpShape* shape; 89 90 // Vertexes for a triangle shape. 91 cpVect tris[3] = [ 92 cpv(-15, -15), 93 cpv(0, 10), 94 cpv(15, -15), 95 ]; 96 97 // Create the static triangles. 98 for (int i = 0; i < 9; i++) 99 { 100 for (int j = 0; j < 6; j++) 101 { 102 cpFloat stagger = (j % 2) * 40; 103 cpVect offset = cpv(i * 80 - 320 + stagger, j * 70 - 240); 104 shape = cpSpaceAddShape(space, cpPolyShapeNew(staticBody, 3, tris.ptr, offset)); 105 cpShapeSetElasticity(shape, 1.0f); 106 cpShapeSetFriction(shape, 1.0f); 107 cpShapeSetLayers(shape, NOT_GRABABLE_MASK); 108 } 109 } 110 111 // Create vertexes for a pentagon shape. 112 cpVect verts[NUM_VERTS]; 113 114 for (int i = 0; i < NUM_VERTS; i++) 115 { 116 cpFloat angle = -2 * M_PI * i / (cast(cpFloat)NUM_VERTS); 117 verts[i] = cpv(10 * cos(angle), 10 * sin(angle)); 118 } 119 120 pentagon_mass = 1.0; 121 pentagon_moment = cpMomentForPoly(1.0f, NUM_VERTS, verts.ptr, cpvzero); 122 123 // Add lots of pentagons. 124 for (int i = 0; i < 300; i++) 125 { 126 body_ = cpSpaceAddBody(space, cpBodyNew(pentagon_mass, pentagon_moment)); 127 cpFloat x = rand() / cast(cpFloat)RAND_MAX * 640 - 320; 128 cpBodySetPos(body_, cpv(x, 350)); 129 130 shape = cpSpaceAddShape(space, cpPolyShapeNew(body_, NUM_VERTS, verts.ptr, cpvzero)); 131 cpShapeSetElasticity(shape, 0.0f); 132 cpShapeSetFriction(shape, 0.4f); 133 } 134 135 return space; 136 } 137 138 void destroy(cpSpace* space) 139 { 140 ChipmunkDemoFreeSpaceChildren(space); 141 cpSpaceFree(space); 142 } 143 144 ChipmunkDemo Plink = { 145 "Plink", 146 1.0 / 60.0, 147 &init, 148 &update, 149 &ChipmunkDemoDefaultDrawImpl, 150 &destroy, 151 };