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.PyramidTopple; 23 24 import core.stdc.stdlib; 25 26 import demo.dchip; 27 28 import demo.ChipmunkDebugDraw; 29 import demo.ChipmunkDemo; 30 import demo.types; 31 32 void update(cpSpace* space, double dt) 33 { 34 cpSpaceStep(space, dt); 35 } 36 37 enum WIDTH = 4.0f; 38 enum HEIGHT = 30.0f; 39 40 void add_domino(cpSpace* space, cpVect pos, cpBool flipped) 41 { 42 cpFloat mass = 1.0f; 43 cpFloat moment = cpMomentForBox(mass, WIDTH, HEIGHT); 44 45 cpBody* body_ = cpSpaceAddBody(space, cpBodyNew(mass, moment)); 46 cpBodySetPos(body_, pos); 47 48 cpShape* shape = (flipped ? cpBoxShapeNew(body_, HEIGHT, WIDTH) : cpBoxShapeNew(body_, WIDTH, HEIGHT)); 49 cpSpaceAddShape(space, shape); 50 cpShapeSetElasticity(shape, 0.0f); 51 cpShapeSetFriction(shape, 0.6f); 52 } 53 54 cpSpace* init() 55 { 56 cpSpace* space = cpSpaceNew(); 57 cpSpaceSetIterations(space, 30); 58 cpSpaceSetGravity(space, cpv(0, -300)); 59 cpSpaceSetSleepTimeThreshold(space, 0.5f); 60 cpSpaceSetCollisionSlop(space, 0.5f); 61 62 // Add a floor. 63 cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(-600, -240), cpv(600, -240), 0.0f)); 64 cpShapeSetElasticity(shape, 1.0f); 65 cpShapeSetFriction(shape, 1.0f); 66 cpShapeSetLayers(shape, NOT_GRABABLE_MASK); 67 68 // Add the dominoes. 69 int n = 12; 70 71 for (int i = 0; i < n; i++) 72 { 73 for (int j = 0; j < (n - i); j++) 74 { 75 cpVect offset = cpv((j - (n - 1 - i) * 0.5f) * 1.5f * HEIGHT, (i + 0.5f) * (HEIGHT + 2 * WIDTH) - WIDTH - 240); 76 add_domino(space, offset, cpFalse); 77 add_domino(space, cpvadd(offset, cpv(0, (HEIGHT + WIDTH) / 2.0f)), cpTrue); 78 79 if (j == 0) 80 { 81 add_domino(space, cpvadd(offset, cpv(0.5f * (WIDTH - HEIGHT), HEIGHT + WIDTH)), cpFalse); 82 } 83 84 if (j != n - i - 1) 85 { 86 add_domino(space, cpvadd(offset, cpv(HEIGHT * 0.75f, (HEIGHT + 3 * WIDTH) / 2.0f)), cpTrue); 87 } 88 else 89 { 90 add_domino(space, cpvadd(offset, cpv(0.5f * (HEIGHT - WIDTH), HEIGHT + WIDTH)), cpFalse); 91 } 92 } 93 } 94 95 return space; 96 } 97 98 void destroy(cpSpace* space) 99 { 100 ChipmunkDemoFreeSpaceChildren(space); 101 cpSpaceFree(space); 102 } 103 104 ChipmunkDemo PyramidTopple = { 105 "Pyramid Topple", 106 1.0 / 180.0, 107 &init, 108 &update, 109 &ChipmunkDemoDefaultDrawImpl, 110 &destroy, 111 };