From 54fe85c5d10e60da6a9c9bbde11f7215723da572 Mon Sep 17 00:00:00 2001 From: Patrik Gornicz Date: Sat, 9 Aug 2008 12:52:30 -0400 Subject: [PATCH] added ball to ball collisions --- src/CollisionInfo.cpp | 31 +++++++++ src/CollisionInfo.h | 38 ++++++++++ src/Entities/Ball.h | 2 +- src/Entities/PhysicsEntity.cpp | 12 +++- src/Entities/PhysicsEntity.h | 9 ++- src/Makefile | 9 ++- src/Vector2.cpp | 11 ++- src/Vector2.h | 3 + src/collisionHandler.cpp | 153 +++++++++++++++++++++++++++++++++++++++++ src/collisionHandler.h | 35 ++++++++++ src/debug.h | 3 + src/entityManager.cpp | 20 ++++-- 12 files changed, 309 insertions(+), 17 deletions(-) create mode 100644 src/CollisionInfo.cpp create mode 100644 src/CollisionInfo.h create mode 100644 src/collisionHandler.cpp create mode 100644 src/collisionHandler.h diff --git a/src/CollisionInfo.cpp b/src/CollisionInfo.cpp new file mode 100644 index 0000000..09e9083 --- /dev/null +++ b/src/CollisionInfo.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CollisionInfo.h" + +/// ***** Constructors/Destructors ***** + +CollisionInfo::CollisionInfo(const Vector2& point, const Vector2& normal) + : point(point), normal(normal) +{ + +} + +CollisionInfo::~CollisionInfo() +{ + +} diff --git a/src/CollisionInfo.h b/src/CollisionInfo.h new file mode 100644 index 0000000..1c0cb19 --- /dev/null +++ b/src/CollisionInfo.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef COLLISIONINFO_H +#define COLLISIONINFO_H + +#include "Vector2.h" + +/// ***** Header Class ***** + +class CollisionInfo +{ + public: + CollisionInfo(const Vector2& point, const Vector2& normal); + ~CollisionInfo(); + + + Vector2 point; + Vector2 normal; +}; + +#endif // COLLISIONINFO_H + diff --git a/src/Entities/Ball.h b/src/Entities/Ball.h index a42d725..d4d43a7 100644 --- a/src/Entities/Ball.h +++ b/src/Entities/Ball.h @@ -34,7 +34,7 @@ class Ball: public PhysicsEntity float getRadius() const; - protected: + //protected: float radius; const float* color; }; diff --git a/src/Entities/PhysicsEntity.cpp b/src/Entities/PhysicsEntity.cpp index 285236e..3354fe2 100644 --- a/src/Entities/PhysicsEntity.cpp +++ b/src/Entities/PhysicsEntity.cpp @@ -70,10 +70,18 @@ Vector2 PhysicsEntity::velocityAt(float time_step) const void PhysicsEntity::applyForce(const Vector2& force) { + applyForce(force, position); +} +void PhysicsEntity::applyForce(const Vector2& force, const Vector2& at) +{ this->force += force; } -void PhysicsEntity::applyImpulse(const Vector2& impluse) +void PhysicsEntity::applyImpulse(const Vector2& impulse) +{ + applyImpulse(impulse, position); +} +void PhysicsEntity::applyImpulse(const Vector2& impulse, const Vector2& at) { - velocity += impluse; + velocity += impulse; } diff --git a/src/Entities/PhysicsEntity.h b/src/Entities/PhysicsEntity.h index 47971a5..a682c9f 100644 --- a/src/Entities/PhysicsEntity.h +++ b/src/Entities/PhysicsEntity.h @@ -37,10 +37,13 @@ class PhysicsEntity: public Entity virtual Vector2 positionAt(float) const; virtual Vector2 velocityAt(float) const; - virtual void applyForce(const Vector2&); - virtual void applyImpulse(const Vector2&); + virtual void applyForce(const Vector2& force); + virtual void applyForce(const Vector2& force, const Vector2& at); - protected: + virtual void applyImpulse(const Vector2& impulse); + virtual void applyImpulse(const Vector2& impulse, const Vector2& at); + + //protected: Vector2 force; float mass; diff --git a/src/Makefile b/src/Makefile index 7964286..1e3e3f5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,9 +13,6 @@ CXXFLAGS := -Wall -pedantic -ansi ${DBGFLAGS} TARGET := ../run_physics SRCS := # simply to keep every line below the same -SRCS += entityManager.cpp -SRCS += effectManager.cpp -SRCS += entityCreator.cpp SRCS += game.cpp SRCS += main.cpp SRCS += mathw.cpp @@ -23,6 +20,12 @@ SRCS += ticks.cpp SRCS += Vector2.cpp SRCS += handleSignal.cpp +SRCS += entityManager.cpp +SRCS += effectManager.cpp +SRCS += entityCreator.cpp +SRCS += collisionHandler.cpp +SRCS += CollisionInfo.cpp + SRCS += Entities/Ball.cpp SRCS += Entities/Entity.cpp SRCS += Entities/Line.cpp diff --git a/src/Vector2.cpp b/src/Vector2.cpp index 2c25375..d13ea95 100644 --- a/src/Vector2.cpp +++ b/src/Vector2.cpp @@ -63,7 +63,16 @@ float Vector2::angle() const } float Vector2::length() const { - return sqrt(x*x + y*y); + return sqrt(sqrLength()); +} +float Vector2::sqrLength() const +{ + return x*x + y*y; +} + +float Vector2::dot(const Vector2& v) const +{ + return x*v.x + y*v.y; } diff --git a/src/Vector2.h b/src/Vector2.h index 00b921b..13ffd88 100644 --- a/src/Vector2.h +++ b/src/Vector2.h @@ -39,6 +39,9 @@ class Vector2 float angle() const; float length() const; + float sqrLength() const; + + float dot(const Vector2&) const; Vector2 add(const Vector2&) const; Vector2 subtract(const Vector2&) const; diff --git a/src/collisionHandler.cpp b/src/collisionHandler.cpp new file mode 100644 index 0000000..08dc904 --- /dev/null +++ b/src/collisionHandler.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "collisionHandler.h" +#include "debug.h" + +#include "Vector2.h" + +#include "Entities/Ball.h" +#include "Entities/PhysicsEntity.h" + +#include "CollisionInfo.h" + +/// ***** Private Class Header ***** + +/// ***** Private Method Headers ***** + +void applyCollisionAt(PhysicsEntity* p1, PhysicsEntity* p2, float time_step); +void applyCollisionAt(Ball* b1, Ball* b2, float time_step); + +CollisionInfo* getInfoAt(Ball* b1, Ball* b2, float time_step); + +/// ***** Private Variables ***** + +/// ***** Initializers/Cleaners ***** + +void collision::init() +{ + +} +void collision::clean() +{ + +} + +/// ***** Public Methods ***** + +void collision::update(setPhys sp, float time_step) +{ + for( setPhys::iterator it1 = sp.begin(); + it1 != sp.end(); + it1++ ) + { + for( setPhys::iterator it2 = sp.begin(); + it2 != sp.end(); + it2++ ) + { + if( *it1 != *it2 ) + { + applyCollisionAt(*it1, *it2, time_step); + } + } + } + +} + +/// ***** Private Methods ***** + +void applyCollisionAt(PhysicsEntity* p1, PhysicsEntity* p2, float time_step) +{ + Ball* b1 = dynamic_cast(p1); + Ball* b2 = dynamic_cast(p2); + + if( b1 != NULL && b2 != NULL ) + { + applyCollisionAt(b1, b2, time_step); + return; + } + +#ifdef WARNINGS + cerr << "ENTITY TYPE NOT SUPPORTED BY applyCollisionAt()!!" << endl; +#endif +} + +void applyCollisionAt(Ball* b1, Ball* b2, float time_step) +{ + // /* + CollisionInfo* info = getInfoAt(b1, b2, time_step); + + if(info == NULL) + return; + + // a few values to simplify the equations + Vector2 normal = info->normal; + Vector2 point = info->point; + + delete info; + + float m1 = b1->mass; + float m2 = b2->mass; + + float e = (b1->CoR + b2->CoR) / 2; + + Vector2 v1 = b1->velocityAt(time_step); + Vector2 v2 = b2->velocityAt(time_step); + + + float iTop = -(e + 1) * (v1 - v2).dot(normal); + + // otherwise the collision happened and we do the math the below assumes + // collisions have no friction + + float impulse = iTop / (normal.dot(normal) * (1 / m1 + 1 / m2)); + + b1->applyImpulse(impulse / m1 * normal, point); + b2->applyImpulse(-impulse / m2 * normal, point); + // */ +} + +CollisionInfo* getInfoAt(Ball* b1, Ball* b2, float time_step) +{ + // a few values to simplify the equations + float r1 = b1->radius; + float r2 = b2->radius; + + Vector2 p1 = b1->positionAt(time_step); + Vector2 p2 = b2->positionAt(time_step); + Vector2 v1 = b1->velocityAt(time_step); + Vector2 v2 = b2->velocityAt(time_step); + + // quick binding box check + if (p1.x - r1 > p2.x + r2 + || p1.x + r1 < p2.x - r2 + || p1.y - r1 > p2.y + r2 + || p1.y + r1 < p2.y - r2) + return NULL; + + // test if not touching + if ((p1 - p2).sqrLength() >= (r1 + r2)*(r1 + r2)) + return NULL; + + // test if they are moving apart in some way if they aren't it's likely + // that they collided last frame and are still overlapping + + if ((v1 - v2).dot(p1 - p2) >= 0) + return NULL; + + return new CollisionInfo(p1 - (p1 - p2) * r1 / (r1 + r2), p1 - p2); +} diff --git a/src/collisionHandler.h b/src/collisionHandler.h new file mode 100644 index 0000000..27940c2 --- /dev/null +++ b/src/collisionHandler.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef COLLISIONHANDLER_H +#define COLLISIONHANDLER_H + +#include "Entities/PhysicsEntity.h" + +#include +typedef std::set setPhys; + +/// ***** Header Methods ***** +namespace collision +{ + void init(); + void clean(); + + void update(setPhys, float); +} + +#endif // COLLISIONHANDLER_H diff --git a/src/debug.h b/src/debug.h index 5fc114b..9460055 100644 --- a/src/debug.h +++ b/src/debug.h @@ -27,6 +27,9 @@ using std::endl; // comment out when not debugging #define DEBUGGING +// comment out to supress warnings +#define WARNINGS + // comment out to prevent FPS and UPS printing #define FPSUPS diff --git a/src/entityManager.cpp b/src/entityManager.cpp index 82dc6d8..c7fc78b 100644 --- a/src/entityManager.cpp +++ b/src/entityManager.cpp @@ -19,12 +19,13 @@ #include "debug.h" #include -#include #include "Entities/Entity.h" #include "Entities/Particle.h" #include "Entities/PhysicsEntity.h" +#include "collisionHandler.h" + /// ***** Private Method Headers ***** void updateParticles(float); @@ -46,11 +47,11 @@ setPhys physics_To_Remove; void manager::init() { - + collision::init(); } void manager::clean() { - + collision::clean(); } /// ***** Public Methods ***** @@ -75,8 +76,9 @@ void manager::add(Entity* e) } } - std::cerr << "ENTITY TYPE NOT SUPPORTED BY addEntity()!!"; - std::cerr << std::endl; +#ifdef WARNINGS + cerr << "ENTITY TYPE NOT SUPPORTED BY addEntity()!!" << endl; +#endif } void manager::remove(Entity* e) { @@ -98,8 +100,9 @@ void manager::remove(Entity* e) } } - std::cerr << "ENTITY TYPE NOT SUPPORTED BY deleteEntity()!!"; - std::cerr << std::endl; +#ifdef WARNINGS + cerr << "ENTITY TYPE NOT SUPPORTED BY deleteEntity()!!" << endl; +#endif } void manager::handleInput() @@ -180,6 +183,9 @@ void updatePhysics(float time_step) } physics_To_Remove.clear(); + // apply collision math + collision::update(active_Physics, time_step); + // update active PhysicsEntity*s for( setPhys::iterator it = active_Physics.begin(); it != active_Physics.end(); -- 2.10.2