1 /*
2 * Copyright (c) 2006-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 // Inspired by a contribution by roman_m
20 // Dimensions scooped from APE (http://www.cove.org/ape/index.htm)
21 
22 #ifndef THEO_JANSEN_H
23 #define THEO_JANSEN_H
24 
25 class TheoJansen : public Test
26 {
27 public:
28 
CreateLeg(float32 s,const b2Vec2 & wheelAnchor)29     void CreateLeg(float32 s, const b2Vec2& wheelAnchor)
30     {
31         b2Vec2 p1(5.4f * s, -6.1f);
32         b2Vec2 p2(7.2f * s, -1.2f);
33         b2Vec2 p3(4.3f * s, -1.9f);
34         b2Vec2 p4(3.1f * s, 0.8f);
35         b2Vec2 p5(6.0f * s, 1.5f);
36         b2Vec2 p6(2.5f * s, 3.7f);
37 
38         b2FixtureDef fd1, fd2;
39         fd1.filter.groupIndex = -1;
40         fd2.filter.groupIndex = -1;
41         fd1.density = 1.0f;
42         fd2.density = 1.0f;
43 
44         b2PolygonShape poly1, poly2;
45 
46         if (s > 0.0f)
47         {
48             b2Vec2 vertices[3];
49 
50             vertices[0] = p1;
51             vertices[1] = p2;
52             vertices[2] = p3;
53             poly1.Set(vertices, 3);
54 
55             vertices[0] = b2Vec2_zero;
56             vertices[1] = p5 - p4;
57             vertices[2] = p6 - p4;
58             poly2.Set(vertices, 3);
59         }
60         else
61         {
62             b2Vec2 vertices[3];
63 
64             vertices[0] = p1;
65             vertices[1] = p3;
66             vertices[2] = p2;
67             poly1.Set(vertices, 3);
68 
69             vertices[0] = b2Vec2_zero;
70             vertices[1] = p6 - p4;
71             vertices[2] = p5 - p4;
72             poly2.Set(vertices, 3);
73         }
74 
75         fd1.shape = &poly1;
76         fd2.shape = &poly2;
77 
78         b2BodyDef bd1, bd2;
79         bd1.type = b2_dynamicBody;
80         bd2.type = b2_dynamicBody;
81         bd1.position = m_offset;
82         bd2.position = p4 + m_offset;
83 
84         bd1.angularDamping = 10.0f;
85         bd2.angularDamping = 10.0f;
86 
87         b2Body* body1 = m_world->CreateBody(&bd1);
88         b2Body* body2 = m_world->CreateBody(&bd2);
89 
90         body1->CreateFixture(&fd1);
91         body2->CreateFixture(&fd2);
92 
93         b2DistanceJointDef djd;
94 
95         // Using a soft distance constraint can reduce some jitter.
96         // It also makes the structure seem a bit more fluid by
97         // acting like a suspension system.
98         djd.dampingRatio = 0.5f;
99         djd.frequencyHz = 10.0f;
100 
101         djd.Initialize(body1, body2, p2 + m_offset, p5 + m_offset);
102         m_world->CreateJoint(&djd);
103 
104         djd.Initialize(body1, body2, p3 + m_offset, p4 + m_offset);
105         m_world->CreateJoint(&djd);
106 
107         djd.Initialize(body1, m_wheel, p3 + m_offset, wheelAnchor + m_offset);
108         m_world->CreateJoint(&djd);
109 
110         djd.Initialize(body2, m_wheel, p6 + m_offset, wheelAnchor + m_offset);
111         m_world->CreateJoint(&djd);
112 
113         b2RevoluteJointDef rjd;
114 
115         rjd.Initialize(body2, m_chassis, p4 + m_offset);
116         m_world->CreateJoint(&rjd);
117     }
118 
TheoJansen()119     TheoJansen()
120     {
121         m_offset.Set(0.0f, 8.0f);
122         m_motorSpeed = 2.0f;
123         m_motorOn = true;
124         b2Vec2 pivot(0.0f, 0.8f);
125 
126         // Ground
127         {
128             b2BodyDef bd;
129             b2Body* ground = m_world->CreateBody(&bd);
130 
131             b2EdgeShape shape;
132             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f));
133             ground->CreateFixture(&shape, 0.0f);
134 
135             shape.Set(b2Vec2(-50.0f, 0.0f), b2Vec2(-50.0f, 10.0f));
136             ground->CreateFixture(&shape, 0.0f);
137 
138             shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(50.0f, 10.0f));
139             ground->CreateFixture(&shape, 0.0f);
140         }
141 
142         // Balls
143         for (int32 i = 0; i < 40; ++i)
144         {
145             b2CircleShape shape;
146             shape.m_radius = 0.25f;
147 
148             b2BodyDef bd;
149             bd.type = b2_dynamicBody;
150             bd.position.Set(-40.0f + 2.0f * i, 0.5f);
151 
152             b2Body* body = m_world->CreateBody(&bd);
153             body->CreateFixture(&shape, 1.0f);
154         }
155 
156         // Chassis
157         {
158             b2PolygonShape shape;
159             shape.SetAsBox(2.5f, 1.0f);
160 
161             b2FixtureDef sd;
162             sd.density = 1.0f;
163             sd.shape = &shape;
164             sd.filter.groupIndex = -1;
165             b2BodyDef bd;
166             bd.type = b2_dynamicBody;
167             bd.position = pivot + m_offset;
168             m_chassis = m_world->CreateBody(&bd);
169             m_chassis->CreateFixture(&sd);
170         }
171 
172         {
173             b2CircleShape shape;
174             shape.m_radius = 1.6f;
175 
176             b2FixtureDef sd;
177             sd.density = 1.0f;
178             sd.shape = &shape;
179             sd.filter.groupIndex = -1;
180             b2BodyDef bd;
181             bd.type = b2_dynamicBody;
182             bd.position = pivot + m_offset;
183             m_wheel = m_world->CreateBody(&bd);
184             m_wheel->CreateFixture(&sd);
185         }
186 
187         {
188             b2RevoluteJointDef jd;
189             jd.Initialize(m_wheel, m_chassis, pivot + m_offset);
190             jd.collideConnected = false;
191             jd.motorSpeed = m_motorSpeed;
192             jd.maxMotorTorque = 400.0f;
193             jd.enableMotor = m_motorOn;
194             m_motorJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
195         }
196 
197         b2Vec2 wheelAnchor;
198 
199         wheelAnchor = pivot + b2Vec2(0.0f, -0.8f);
200 
201         CreateLeg(-1.0f, wheelAnchor);
202         CreateLeg(1.0f, wheelAnchor);
203 
204         m_wheel->SetTransform(m_wheel->GetPosition(), 120.0f * b2_pi / 180.0f);
205         CreateLeg(-1.0f, wheelAnchor);
206         CreateLeg(1.0f, wheelAnchor);
207 
208         m_wheel->SetTransform(m_wheel->GetPosition(), -120.0f * b2_pi / 180.0f);
209         CreateLeg(-1.0f, wheelAnchor);
210         CreateLeg(1.0f, wheelAnchor);
211     }
212 
Step(Settings * settings)213     void Step(Settings* settings)
214     {
215         m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, toggle motor = m");
216         m_textLine += 15;
217 
218         Test::Step(settings);
219     }
220 
Keyboard(unsigned char key)221     void Keyboard(unsigned char key)
222     {
223         switch (key)
224         {
225         case 'a':
226             m_motorJoint->SetMotorSpeed(-m_motorSpeed);
227             break;
228 
229         case 's':
230             m_motorJoint->SetMotorSpeed(0.0f);
231             break;
232 
233         case 'd':
234             m_motorJoint->SetMotorSpeed(m_motorSpeed);
235             break;
236 
237         case 'm':
238             m_motorJoint->EnableMotor(!m_motorJoint->IsMotorEnabled());
239             break;
240         }
241     }
242 
Create()243     static Test* Create()
244     {
245         return new TheoJansen;
246     }
247 
248     b2Vec2 m_offset;
249     b2Body* m_chassis;
250     b2Body* m_wheel;
251     b2RevoluteJoint* m_motorJoint;
252     bool m_motorOn;
253     float32 m_motorSpeed;
254 };
255 
256 #endif // THEO_JANSEN_H
257