2 * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "collisionManager.h"
23 #include "Entities/Ball.h"
24 #include "Entities/PhysicsEntity.h"
26 #include "CollisionInfo.h"
28 /// ***** Private Class Header *****
30 /// ***** Private Method Headers *****
32 void applyCollisionAt(PhysicsEntity* p1, PhysicsEntity* p2);
33 void applyCollisionAt(Ball* b1, Ball* b2);
35 bool getInfoAt(Ball* b1, Ball* b2, CollisionInfo* cInfo);
37 /// ***** Private Variables *****
39 /// ***** Initializers/Cleaners *****
41 void collision::init()
45 void collision::clean()
50 /// ***** Public Methods *****
52 void collision::update(setPhys& sp)
54 for( setPhys::iterator it1 = sp.begin();
58 for( setPhys::iterator it2 = sp.begin();
64 applyCollisionAt(*it1, *it2);
71 /// ***** Private Methods *****
73 void applyCollisionAt(PhysicsEntity* p1, PhysicsEntity* p2)
75 Ball* b1 = dynamic_cast<Ball*>(p1);
76 Ball* b2 = dynamic_cast<Ball*>(p2);
78 if( b1 != NULL && b2 != NULL )
80 applyCollisionAt(b1, b2);
84 DPF(0, "ENTITY TYPE NOT SUPPORTED BY applyCollisionAt()!!");
87 void applyCollisionAt(Ball* b1, Ball* b2)
91 if(!getInfoAt(b1, b2, &cInfo))
94 // a few values to simplify the equations
95 const Vector2& normal = cInfo.normal;
96 const Vector2& point = cInfo.point;
101 float e = (b1->CoR + b2->CoR) / 2;
103 Vector2 v1 = b1->velocityRaw();
104 Vector2 v2 = b2->velocityRaw();
107 float iTop = -(e + 1) * (v1 - v2).dot(normal);
109 // otherwise the collision happened and we do the math the below assumes
110 // collisions have no friction
112 float impulse = iTop / (normal.dot(normal) * (1 / m1 + 1 / m2));
114 b1->applyImpulse(impulse / m1 * normal, point);
115 b2->applyImpulse(-impulse / m2 * normal, point);
118 bool getInfoAt(Ball* b1, Ball* b2, CollisionInfo* pcInfo)
120 // a few values to simplify the equations
121 float r1 = b1->radius;
122 float r2 = b2->radius;
124 Vector2 p1 = b1->positionRaw();
125 Vector2 p2 = b2->positionRaw();
126 Vector2 v1 = b1->velocityRaw();
127 Vector2 v2 = b2->velocityRaw();
129 // quick binding box check
130 if (p1.x - r1 > p2.x + r2
131 || p1.x + r1 < p2.x - r2
132 || p1.y - r1 > p2.y + r2
133 || p1.y + r1 < p2.y - r2)
136 // test if not touching
137 if ((p1 - p2).sqrLength() >= (r1 + r2)*(r1 + r2))
140 // test if they are moving apart in some way if they aren't it's likely
141 // that they collided last frame and are still overlapping
143 if ((v1 - v2).dot(p1 - p2) >= 0)
146 pcInfo->point = p1 - (p1 - p2) * r1 / (r1 + r2);
147 pcInfo->normal = p1 - p2;