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