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.OneWay;
23 
24 import core.stdc.stdlib;
25 
26 import std.math;
27 
28 alias M_PI_2 = PI_2;
29 
30 import demo.dchip;
31 
32 import demo.ChipmunkDebugDraw;
33 import demo.ChipmunkDemo;
34 import demo.types;
35 
36 struct OneWayPlatform
37 {
38     cpVect n;     // direction objects may pass through
39 }
40 
41 OneWayPlatform platformInstance;
42 
43 cpBool preSolve(cpArbiter* arb, cpSpace* space, void* ignore)
44 {
45     mixin(CP_ARBITER_GET_SHAPES!("arb", "a", "b"));
46     OneWayPlatform* platform = cast(OneWayPlatform*)cpShapeGetUserData(a);
47 
48     if (cpvdot(cpArbiterGetNormal(arb, 0), platform.n) < 0)
49     {
50         cpArbiterIgnore(arb);
51         return cpFalse;
52     }
53 
54     return cpTrue;
55 }
56 
57 void update(cpSpace* space, double dt)
58 {
59     cpSpaceStep(space, dt);
60 }
61 
62 cpSpace* init()
63 {
64     ChipmunkDemoMessageString = "One way platforms are trivial in Chipmunk using a very simple collision callback.".dup;
65 
66     cpSpace* space = cpSpaceNew();
67     cpSpaceSetIterations(space, 10);
68     cpSpaceSetGravity(space, cpv(0, -100));
69 
70     cpBody * body_;
71     cpBody * staticBody = cpSpaceGetStaticBody(space);
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     cpShapeSetElasticity(shape, 1.0f);
77     cpShapeSetFriction(shape, 1.0f);
78     cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
79 
80     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f));
81     cpShapeSetElasticity(shape, 1.0f);
82     cpShapeSetFriction(shape, 1.0f);
83     cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
84 
85     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f));
86     cpShapeSetElasticity(shape, 1.0f);
87     cpShapeSetFriction(shape, 1.0f);
88     cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
89 
90     // Add our one way segment
91     shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160, -100), cpv(160, -100), 10.0f));
92     cpShapeSetElasticity(shape, 1.0f);
93     cpShapeSetFriction(shape, 1.0f);
94     cpShapeSetCollisionType(shape, 1);
95     cpShapeSetLayers(shape, NOT_GRABABLE_MASK);
96 
97     // We'll use the data pointer for the OneWayPlatform struct
98     platformInstance.n = cpv(0, 1);     // let objects pass upwards
99     cpShapeSetUserData(shape, &platformInstance);
100 
101     // Add a ball to make things more interesting
102     cpFloat radius = 15.0f;
103     body_ = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero)));
104     cpBodySetPos(body_, cpv(0, -200));
105     cpBodySetVel(body_, cpv(0, 170));
106 
107     shape = cpSpaceAddShape(space, cpCircleShapeNew(body_, radius, cpvzero));
108     cpShapeSetElasticity(shape, 0.0f);
109     cpShapeSetFriction(shape, 0.9f);
110     cpShapeSetCollisionType(shape, 2);
111 
112     cpSpaceAddCollisionHandler(space, 1, 2, null, &preSolve, null, null, null);
113 
114     return space;
115 }
116 
117 void destroy(cpSpace* space)
118 {
119     ChipmunkDemoFreeSpaceChildren(space);
120     cpSpaceFree(space);
121 }
122 
123 ChipmunkDemo OneWay = {
124     "One Way Platforms",
125     1.0 / 60.0,
126     &init,
127     &update,
128     &ChipmunkDemoDefaultDrawImpl,
129     &destroy,
130 };