1 /*
2 * Copyright (c) 2008-2009 Erin Catto http://www.box2d.org
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty.  In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
17 */
18 
19 #ifndef SENSOR_TEST_H
20 #define SENSOR_TEST_H
21 
22 // This is used to test sensor shapes.
23 class SensorTest : public Test
24 {
25 public:
26 
27     enum
28     {
29         e_count = 7
30     };
31 
SensorTest()32     SensorTest()
33     {
34         {
35             b2BodyDef bd;
36             b2Body* ground = m_world->CreateBody(&bd);
37 
38             {
39                 b2EdgeShape shape;
40                 shape.Set(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
41                 ground->CreateFixture(&shape, 0.0f);
42             }
43 
44 #if 0
45             {
46                 b2FixtureDef sd;
47                 sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f);
48                 sd.isSensor = true;
49                 m_sensor = ground->CreateFixture(&sd);
50             }
51 #else
52             {
53                 b2CircleShape shape;
54                 shape.m_radius = 5.0f;
55                 shape.m_p.Set(0.0f, 10.0f);
56 
57                 b2FixtureDef fd;
58                 fd.shape = &shape;
59                 fd.isSensor = true;
60                 m_sensor = ground->CreateFixture(&fd);
61             }
62 #endif
63         }
64 
65         {
66             b2CircleShape shape;
67             shape.m_radius = 1.0f;
68 
69             for (int32 i = 0; i < e_count; ++i)
70             {
71                 b2BodyDef bd;
72                 bd.type = b2_dynamicBody;
73                 bd.position.Set(-10.0f + 3.0f * i, 20.0f);
74                 bd.userData = m_touching + i;
75 
76                 m_touching[i] = false;
77                 m_bodies[i] = m_world->CreateBody(&bd);
78 
79                 m_bodies[i]->CreateFixture(&shape, 1.0f);
80             }
81         }
82     }
83 
84     // Implement contact listener.
BeginContact(b2Contact * contact)85     void BeginContact(b2Contact* contact)
86     {
87         b2Fixture* fixtureA = contact->GetFixtureA();
88         b2Fixture* fixtureB = contact->GetFixtureB();
89 
90         if (fixtureA == m_sensor)
91         {
92             void* userData = fixtureB->GetBody()->GetUserData();
93             if (userData)
94             {
95                 bool* touching = (bool*)userData;
96                 *touching = true;
97             }
98         }
99 
100         if (fixtureB == m_sensor)
101         {
102             void* userData = fixtureA->GetBody()->GetUserData();
103             if (userData)
104             {
105                 bool* touching = (bool*)userData;
106                 *touching = true;
107             }
108         }
109     }
110 
111     // Implement contact listener.
EndContact(b2Contact * contact)112     void EndContact(b2Contact* contact)
113     {
114         b2Fixture* fixtureA = contact->GetFixtureA();
115         b2Fixture* fixtureB = contact->GetFixtureB();
116 
117         if (fixtureA == m_sensor)
118         {
119             void* userData = fixtureB->GetBody()->GetUserData();
120             if (userData)
121             {
122                 bool* touching = (bool*)userData;
123                 *touching = false;
124             }
125         }
126 
127         if (fixtureB == m_sensor)
128         {
129             void* userData = fixtureA->GetBody()->GetUserData();
130             if (userData)
131             {
132                 bool* touching = (bool*)userData;
133                 *touching = false;
134             }
135         }
136     }
137 
Step(Settings * settings)138     void Step(Settings* settings)
139     {
140         Test::Step(settings);
141 
142         // Traverse the contact results. Apply a force on shapes
143         // that overlap the sensor.
144         for (int32 i = 0; i < e_count; ++i)
145         {
146             if (m_touching[i] == false)
147             {
148                 continue;
149             }
150 
151             b2Body* body = m_bodies[i];
152             b2Body* ground = m_sensor->GetBody();
153 
154             b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape();
155             b2Vec2 center = ground->GetWorldPoint(circle->m_p);
156 
157             b2Vec2 position = body->GetPosition();
158 
159             b2Vec2 d = center - position;
160             if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON)
161             {
162                 continue;
163             }
164 
165             d.Normalize();
166             b2Vec2 F = 100.0f * d;
167             body->ApplyForce(F, position);
168         }
169     }
170 
Create()171     static Test* Create()
172     {
173         return new SensorTest;
174     }
175 
176     b2Fixture* m_sensor;
177     b2Body* m_bodies[e_count];
178     bool m_touching[e_count];
179 };
180 
181 #endif
182