1 
2 // written in the D programming language
3 
4 module samples.PyramidTopple;
5 
6 import dchip.all;
7 
8 import samples.ChipmunkDemo;
9 
10 import std.math:PI;
11 
12 static cpSpace *space;
13 
14 static void
15 update(int ticks)
16 {
17     int steps = 3;
18     cpFloat dt = 1.0f/60.0f/cast(cpFloat)steps;
19 
20     for(int i=0; i<steps; i++)
21         cpSpaceStep(space, dt);
22 }
23 
24 enum WIDTH = 4.0f;
25 enum HEIGHT = 30.0f;
26 
27 static void
28 add_domino(cpSpace *space, cpVect pos, cpBool flipped)
29 {
30     cpFloat mass = 1.0f;
31     cpFloat moment = cpMomentForBox(mass, WIDTH, HEIGHT);
32 
33     cpBody *_body = cpSpaceAddBody(space, cpBodyNew(mass, moment));
34     _body.p = pos;
35 
36     cpShape *shape = (flipped ? cpBoxShapeNew(_body, HEIGHT, WIDTH) : cpBoxShapeNew(_body, WIDTH, HEIGHT));
37     cpSpaceAddShape(space, shape);
38     shape.e = 0.0f; shape.u = 0.6f;
39 }
40 
41 static cpSpace *
42 init()
43 {
44     cpResetShapeIdCounter();
45 
46     space = cpSpaceNew();
47     space.iterations = 30;
48     space.gravity = cpv(0, -300);
49     space.sleepTimeThreshold = 0.5f;
50     space.collisionSlop = 0.5f;
51 
52     // Add a floor.
53     cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(space.staticBody, cpv(-600,-240), cpv(600,-240), 0.0f));
54     shape.e = 1.0f; shape.u = 1.0f;
55     shape.layers = NOT_GRABABLE_MASK;
56 
57     // Shared friction constant.
58     cpFloat u = 0.6f;
59 
60     // Add the dominoes.
61     int n = 12;
62     for(int i=0; i<n; i++){
63         for(int j=0; j<(n - i); j++){
64             cpVect offset = cpv((j - (n - 1 - i)*0.5f)*1.5f*HEIGHT, (i + 0.5f)*(HEIGHT + 2*WIDTH) - WIDTH - 240);
65             add_domino(space, offset, cpFalse);
66             add_domino(space, cpvadd(offset, cpv(0, (HEIGHT + WIDTH)/2.0f)), cpTrue);
67 
68             if(j == 0){
69                 add_domino(space, cpvadd(offset, cpv(0.5f*(WIDTH - HEIGHT), HEIGHT + WIDTH)), cpFalse);
70             }
71 
72             if(j != n - i - 1){
73                 add_domino(space, cpvadd(offset, cpv(HEIGHT*0.75f, (HEIGHT + 3*WIDTH)/2.0f)), cpTrue);
74             } else {
75                 add_domino(space, cpvadd(offset, cpv(0.5f*(HEIGHT - WIDTH), HEIGHT + WIDTH)), cpFalse);
76             }
77         }
78     }
79 
80     return space;
81 }
82 
83 static void
84 destroy()
85 {
86     ChipmunkDemoFreeSpaceChildren(space);
87     cpSpaceFree(space);
88 }
89 
90 chipmunkDemo PyramidTopple = {
91     "Pyramid Topple",
92     null,
93     &init,
94     &update,
95     &destroy,
96 };