PolyPhysicsScreen.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * PolyPhysicsScreen.cpp
  3. * Poly
  4. *
  5. * Created by Ivan Safrin on 5/8/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #include "PolyPhysicsScreen.h"
  10. using namespace Polycode;
  11. /*
  12. void PhysicsScreen::Add(const b2ContactPoint* point) {
  13. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  14. return;
  15. }
  16. ContactPoint* cp = m_points + numContactPoints;
  17. cp->shape1 = point->shape1;
  18. cp->shape2 = point->shape2;
  19. cp->position = point->position;
  20. cp->normal = point->normal;
  21. cp->id = point->id;
  22. cp->state = e_contactAdded;
  23. ++numContactPoints;
  24. }
  25. void PhysicsScreen::Persist(const b2ContactPoint* point) {
  26. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  27. return;
  28. }
  29. ContactPoint* cp = m_points + numContactPoints;
  30. cp->shape1 = point->shape1;
  31. cp->shape2 = point->shape2;
  32. cp->position = point->position;
  33. cp->normal = point->normal;
  34. cp->id = point->id;
  35. cp->state = e_contactPersisted;
  36. ++numContactPoints;
  37. }
  38. void PhysicsScreen::Remove(const b2ContactPoint* point) {
  39. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  40. return;
  41. }
  42. ContactPoint* cp = m_points + numContactPoints;
  43. cp->shape1 = point->shape1;
  44. cp->shape2 = point->shape2;
  45. cp->position = point->position;
  46. cp->normal = point->normal;
  47. cp->id = point->id;
  48. cp->state = e_contactRemoved;
  49. ++numContactPoints;
  50. }
  51. */
  52. void PhysicsScreen::BeginContact (b2Contact *contact) {
  53. }
  54. void PhysicsScreen::EndContact (b2Contact *contact) {
  55. }
  56. PhysicsScreen::PhysicsScreen() : Screen() {
  57. init(10.0f, 1.0f/60.0f,10,Vector2(0.0f, 10.0f));
  58. }
  59. PhysicsScreen::PhysicsScreen(float worldScale, float freq) : Screen() {
  60. init(worldScale, 1.0f/freq,10,Vector2(0.0f, 10.0f));
  61. }
  62. void PhysicsScreen::init(float worldScale, float physicsTimeStep, int physicsIterations, Vector2 physicsGravity) {
  63. this->worldScale = worldScale;
  64. numContactPoints = 0;
  65. timeStep = physicsTimeStep;
  66. iterations = physicsIterations;
  67. b2Vec2 gravity(physicsGravity.x,physicsGravity.y);
  68. bool doSleep = true;
  69. world = new b2World(gravity, doSleep);
  70. world->SetContactListener(this);
  71. updateTimer = new Timer(true, 3);
  72. updateTimer->addEventListener(this, Timer::EVENT_TRIGGER);
  73. }
  74. void PhysicsScreen::setGravity(Vector2 newGravity) {
  75. world->SetGravity(b2Vec2(newGravity.x, newGravity.y));
  76. }
  77. PhysicsScreenEntity *PhysicsScreen::getPhysicsByScreenEntity(ScreenEntity *ent) {
  78. for(int i=0; i<physicsChildren.size();i++) {
  79. if(physicsChildren[i]->getScreenEntity() == ent)
  80. return physicsChildren[i];
  81. }
  82. return NULL;
  83. }
  84. b2RevoluteJoint *PhysicsScreen::createRevoluteJoint(ScreenEntity *ent1, ScreenEntity *ent2, float ax, float ay, bool enableLimit, float lowerLimit, float upperLimit, bool motorEnabled, float motorSpeed, float maxTorque) {
  85. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  86. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  87. if(pEnt1 == NULL || pEnt2 == NULL)
  88. return NULL;
  89. b2Vec2 anchor((ent1->getPosition()->x+ax)/worldScale, (ent1->getPosition()->y+ay)/worldScale);
  90. b2RevoluteJointDef *jointDef = new b2RevoluteJointDef();
  91. jointDef->collideConnected = false;
  92. jointDef->lowerAngle = lowerLimit * (PI/180.0f);
  93. jointDef->upperAngle = upperLimit * (PI/180.0f);
  94. jointDef->enableLimit = enableLimit;
  95. jointDef->motorSpeed = motorSpeed;
  96. jointDef->maxMotorTorque = maxTorque;
  97. jointDef->enableMotor = motorEnabled;
  98. jointDef->Initialize(pEnt1->body, pEnt2->body, anchor);
  99. b2RevoluteJoint *joint = (b2RevoluteJoint*)world->CreateJoint(jointDef);
  100. return joint;
  101. }
  102. void PhysicsScreen::createPrismaticJoint(ScreenEntity *ent1, ScreenEntity *ent2, bool collideConnected) {
  103. }
  104. void PhysicsScreen::wakeUp(ScreenEntity *ent) {
  105. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  106. if(pEnt == NULL)
  107. return;
  108. pEnt->body->SetAwake(true);
  109. }
  110. void PhysicsScreen::setVelocity(ScreenEntity *ent, float fx, float fy) {
  111. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  112. if(pEnt == NULL)
  113. return;
  114. pEnt->body->SetAwake(true);
  115. b2Vec2 f = pEnt->body->GetLinearVelocity();
  116. if(fx != 0)
  117. f.x = fx;
  118. if(fy != 0)
  119. f.y = fy;
  120. pEnt->body->SetLinearVelocity(f);
  121. }
  122. void PhysicsScreen::setVelocityX(ScreenEntity *ent, float fx) {
  123. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  124. if(pEnt == NULL)
  125. return;
  126. pEnt->body->SetAwake(true);
  127. b2Vec2 f = pEnt->body->GetLinearVelocity();
  128. f.x = fx;
  129. pEnt->body->SetLinearVelocity(f);
  130. }
  131. void PhysicsScreen::setVelocityY(ScreenEntity *ent, float fy) {
  132. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  133. if(pEnt == NULL)
  134. return;
  135. pEnt->body->SetAwake(true);
  136. b2Vec2 f = pEnt->body->GetLinearVelocity();
  137. f.y = fy;
  138. pEnt->body->SetLinearVelocity(f);
  139. }
  140. PhysicsScreenEntity *PhysicsScreen::addCollisionChild(ScreenEntity *newEntity, int entType) {
  141. PhysicsScreenEntity *ret;
  142. ret = addPhysicsChild(newEntity, entType, 0,0.1,0, true);
  143. ret->collisionOnly = true;
  144. return ret;
  145. }
  146. void PhysicsScreen::applyForce(ScreenEntity *ent, float fx, float fy) {
  147. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  148. if(pEnt == NULL)
  149. return;
  150. pEnt->body->SetAwake(true);
  151. b2Vec2 f = b2Vec2(fx,fy);
  152. b2Vec2 p = pEnt->body->GetWorldPoint(b2Vec2(0.0f, 0.0f));
  153. pEnt->body->ApplyForce(f, p);
  154. }
  155. void PhysicsScreen::applyImpulse(ScreenEntity *ent, float fx, float fy) {
  156. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  157. if(pEnt == NULL)
  158. return;
  159. pEnt->body->SetAwake(true);
  160. b2Vec2 f = b2Vec2(fx,fy);
  161. b2Vec2 p = pEnt->body->GetWorldPoint(b2Vec2(0.0f, 0.0f));
  162. pEnt->body->ApplyLinearImpulse(f, p);
  163. }
  164. void PhysicsScreen::createDistanceJoint(ScreenEntity *ent1, ScreenEntity *ent2, bool collideConnected) {
  165. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  166. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  167. if(pEnt1 == NULL || pEnt2 == NULL)
  168. return;
  169. b2Vec2 a1(ent1->getPosition()->x/worldScale, ent1->getPosition()->y/worldScale);
  170. b2Vec2 a2(ent2->getPosition()->x/worldScale, ent2->getPosition()->y/worldScale);
  171. b2DistanceJointDef *jointDef = new b2DistanceJointDef();
  172. jointDef->Initialize(pEnt1->body, pEnt2->body, a1, a2);
  173. jointDef->collideConnected = collideConnected;
  174. world->CreateJoint(jointDef);
  175. }
  176. /*
  177. b2MouseJoint *PhysicsScreen::createMouseJoint(ScreenEntity *ent1, Vector2 *mp) {
  178. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  179. if(pEnt1 == NULL)
  180. return NULL;
  181. b2MouseJointDef *mj = new b2MouseJointDef();
  182. mj->bodyA = world->GetGroundBody();
  183. mj->bodyB = pEnt1->body;
  184. b2Vec2 mpos(mp->x/10.0f, mp->y/10.0f);
  185. mj->target = mpos;
  186. #ifdef TARGET_FLOAT32_IS_FIXED
  187. mj->maxForce = (pEnt1->body->GetMass() < 16.0)? (1000.0f * pEnt1->body->GetMass()) : float32(16000.0);
  188. #else
  189. mj->maxForce = 1000.0f * pEnt1->body->GetMass();
  190. #endif
  191. b2MouseJoint *m_mouseJoint = (b2MouseJoint*)world->CreateJoint(mj);
  192. pEnt1->body->SetAwake(true);
  193. Logger::log("OK %d!\n", m_mouseJoint);
  194. return m_mouseJoint;
  195. }
  196. */
  197. Vector2 PhysicsScreen::getEntityCollisionNormal(ScreenEntity *ent1, ScreenEntity *ent2) {
  198. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  199. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  200. if(pEnt1 == NULL || pEnt2 == NULL)
  201. return Vector2(0,0);
  202. PhysicsScreenEntity *rEnt1;
  203. PhysicsScreenEntity *rEnt2;
  204. for (int32 i = 0; i < numContactPoints; ++i)
  205. {
  206. ContactPoint* point = m_points + i;
  207. if (point->state == 0 || point->state == 1) {
  208. rEnt1= getPhysicsEntityByShape(point->shape1);
  209. rEnt2 = getPhysicsEntityByShape(point->shape2);
  210. if((rEnt1 == pEnt1 && rEnt2 == pEnt2) ||
  211. (rEnt1 == pEnt2 && rEnt2 == pEnt1)) {
  212. return Vector2(point->normal.x,point->normal.y);
  213. }
  214. }
  215. }
  216. return Vector2(0,0);
  217. }
  218. bool PhysicsScreen::areEntitiesColliding(ScreenEntity *ent1, ScreenEntity *ent2) {
  219. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  220. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  221. if(pEnt1 == NULL || pEnt2 == NULL)
  222. return false;
  223. PhysicsScreenEntity *rEnt1;
  224. PhysicsScreenEntity *rEnt2;
  225. for (int32 i = 0; i < numContactPoints; ++i)
  226. {
  227. ContactPoint* point = m_points + i;
  228. if (point->state == 0 || point->state == 1) {
  229. rEnt1= getPhysicsEntityByShape(point->shape1);
  230. rEnt2 = getPhysicsEntityByShape(point->shape2);
  231. if((rEnt1 == pEnt1 && rEnt2 == pEnt2) ||
  232. (rEnt1 == pEnt2 && rEnt2 == pEnt1)) {
  233. return true;
  234. }
  235. }
  236. }
  237. return false;
  238. }
  239. ScreenEntity *PhysicsScreen::getEntityAtPosition(float x, float y) {
  240. ScreenEntity *ret = NULL;
  241. b2Vec2 mousePosition;
  242. mousePosition.x = x/worldScale;
  243. mousePosition.y = y/worldScale;
  244. for(int i=0;i<physicsChildren.size();i++) {
  245. PhysicsScreenEntity *ent = physicsChildren[i];
  246. if(ent->shape->TestPoint(ent->body->GetTransform(), mousePosition))
  247. return ent->getScreenEntity();
  248. }
  249. return ret;
  250. }
  251. bool PhysicsScreen::testEntityAtPosition(ScreenEntity *ent, float x, float y) {
  252. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  253. if(pEnt == NULL)
  254. return false;
  255. b2Vec2 mousePosition;
  256. mousePosition.x = x/worldScale;
  257. mousePosition.y = y/worldScale;
  258. if(pEnt->shape->TestPoint(pEnt->body->GetTransform(), mousePosition))
  259. return true;
  260. else
  261. return false;
  262. }
  263. void PhysicsScreen::destroyMouseJoint(b2MouseJoint *mJoint) {
  264. world->DestroyJoint(mJoint);
  265. mJoint = NULL;
  266. }
  267. PhysicsScreenEntity *PhysicsScreen::addPhysicsChild(ScreenEntity *newEntity, int entType, float friction, float density, float restitution, bool isSensor, bool fixedRotation) {
  268. addChild(newEntity);
  269. newEntity->setPositionMode(ScreenEntity::POSITION_CENTER);
  270. PhysicsScreenEntity *newPhysicsEntity = new PhysicsScreenEntity(newEntity, world, worldScale, entType, friction, density, restitution, isSensor,fixedRotation);
  271. physicsChildren.push_back(newPhysicsEntity);
  272. newPhysicsEntity->body->SetAwake(true);
  273. return newPhysicsEntity;
  274. }
  275. void PhysicsScreen::removePhysicsChild(PhysicsScreenEntity *entityToRemove) {
  276. world->DestroyBody(entityToRemove->body);
  277. removeChild(entityToRemove->getScreenEntity());
  278. for(int i=0;i<physicsChildren.size();i++) {
  279. if(physicsChildren[i] == entityToRemove) {
  280. physicsChildren.erase(physicsChildren.begin()+i);
  281. }
  282. }
  283. }
  284. void PhysicsScreen::Shutdown() {
  285. }
  286. PhysicsScreen::~PhysicsScreen() {
  287. delete world;
  288. for(int i=0; i<physicsChildren.size();i++) {
  289. delete physicsChildren[i];
  290. }
  291. }
  292. PhysicsScreenEntity *PhysicsScreen::getPhysicsEntityByShape(b2Shape *shape) {
  293. for(int i=0; i < physicsChildren.size(); i++) {
  294. if(physicsChildren[i]->shape == shape)
  295. return physicsChildren[i];
  296. }
  297. return NULL;
  298. }
  299. void PhysicsScreen::handleEvent(Event *event) {
  300. numContactPoints = 0;
  301. if(event->getDispatcher() == updateTimer) {
  302. world->Step(timeStep, iterations,iterations);
  303. }
  304. for (int32 i = 0; i < numContactPoints; ++i)
  305. {
  306. ContactPoint* point = m_points + i;
  307. if (point->state == 0) {
  308. PhysicsScreenEvent *newEvent = new PhysicsScreenEvent();
  309. newEvent->entity1 = getPhysicsEntityByShape(point->shape1);
  310. newEvent->entity2 = getPhysicsEntityByShape(point->shape2);
  311. dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_NEW_SHAPE_COLLISION);
  312. } else if (point->state == 1) {
  313. // Persist
  314. // DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
  315. } else {
  316. // Remove
  317. // DrawPoint(point->position, 10.0f, b2Color(0.95f, 0.3f, 0.3f));
  318. dispatchEvent(new PhysicsScreenEvent(), PhysicsScreenEvent::EVENT_END_SHAPE_COLLISION);
  319. }
  320. }
  321. Screen::handleEvent(event);
  322. }
  323. void PhysicsScreen::Update() {
  324. // unsigned int elapsed = updateTimer->getTicks();
  325. // if(updateTimer->hasElapsed()) {
  326. // world->Step(timeStep, iterations);
  327. for(int i=0; i<physicsChildren.size();i++) {
  328. physicsChildren[i]->Update();
  329. }
  330. // }
  331. }