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 BREAKABLE_TEST_H 20 #define BREAKABLE_TEST_H 21 22 // This is used to test sensor shapes. 23 class Breakable : public Test 24 { 25 public: 26 27 enum 28 { 29 e_count = 7 30 }; 31 Breakable()32 Breakable() 33 { 34 // Ground body 35 { 36 b2BodyDef bd; 37 b2Body* ground = m_world->CreateBody(&bd); 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 // Breakable dynamic body 45 { 46 b2BodyDef bd; 47 bd.type = b2_dynamicBody; 48 bd.position.Set(0.0f, 40.0f); 49 bd.angle = 0.25f * b2_pi; 50 m_body1 = m_world->CreateBody(&bd); 51 52 m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f); 53 m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f); 54 55 m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f); 56 m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f); 57 } 58 59 m_break = false; 60 m_broke = false; 61 } 62 PostSolve(b2Contact * contact,const b2ContactImpulse * impulse)63 void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) 64 { 65 if (m_broke) 66 { 67 // The body already broke. 68 return; 69 } 70 71 // Should the body break? 72 int32 count = contact->GetManifold()->pointCount; 73 74 float32 maxImpulse = 0.0f; 75 for (int32 i = 0; i < count; ++i) 76 { 77 maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); 78 } 79 80 if (maxImpulse > 40.0f) 81 { 82 // Flag the body for breaking. 83 m_break = true; 84 } 85 } 86 Break()87 void Break() 88 { 89 // Create two bodies from one. 90 b2Body* body1 = m_piece1->GetBody(); 91 b2Vec2 center = body1->GetWorldCenter(); 92 93 body1->DestroyFixture(m_piece2); 94 m_piece2 = NULL; 95 96 b2BodyDef bd; 97 bd.type = b2_dynamicBody; 98 bd.position = body1->GetPosition(); 99 bd.angle = body1->GetAngle(); 100 101 b2Body* body2 = m_world->CreateBody(&bd); 102 m_piece2 = body2->CreateFixture(&m_shape2, 1.0f); 103 104 // Compute consistent velocities for new bodies based on 105 // cached velocity. 106 b2Vec2 center1 = body1->GetWorldCenter(); 107 b2Vec2 center2 = body2->GetWorldCenter(); 108 109 b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center); 110 b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center); 111 112 body1->SetAngularVelocity(m_angularVelocity); 113 body1->SetLinearVelocity(velocity1); 114 115 body2->SetAngularVelocity(m_angularVelocity); 116 body2->SetLinearVelocity(velocity2); 117 } 118 Step(Settings * settings)119 void Step(Settings* settings) 120 { 121 if (m_break) 122 { 123 Break(); 124 m_broke = true; 125 m_break = false; 126 } 127 128 // Cache velocities to improve movement on breakage. 129 if (m_broke == false) 130 { 131 m_velocity = m_body1->GetLinearVelocity(); 132 m_angularVelocity = m_body1->GetAngularVelocity(); 133 } 134 135 Test::Step(settings); 136 } 137 Create()138 static Test* Create() 139 { 140 return new Breakable; 141 } 142 143 b2Body* m_body1; 144 b2Vec2 m_velocity; 145 float32 m_angularVelocity; 146 b2PolygonShape m_shape1; 147 b2PolygonShape m_shape2; 148 b2Fixture* m_piece1; 149 b2Fixture* m_piece2; 150 151 bool m_broke; 152 bool m_break; 153 }; 154 155 #endif 156