Welt2D.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. #include "Welt2D.h"
  2. #include "Bild.h"
  3. using namespace Framework;
  4. Object2D::Object2D()
  5. {
  6. rSpeed = 0;
  7. rotation = 0;
  8. size = 1;
  9. collision = 1;
  10. ref = 1;
  11. }
  12. Object2D::~Object2D()
  13. {}
  14. void Object2D::explosion( Vertex worldPos, float intensity )
  15. {
  16. intensity /= ( position - worldPos ).getLengthSq();
  17. speed += ( position - worldPos ) * intensity;
  18. }
  19. void Object2D::impuls( Vertex start, Vertex speed, float strength )
  20. {}
  21. void Object2D::setSpeed( Vertex speed )
  22. {
  23. this->speed = speed;
  24. }
  25. void Object2D::setSpeed( float x, float y )
  26. {
  27. speed.x = x, speed.y = y;
  28. }
  29. void Object2D::setPosition( Vertex pos )
  30. {
  31. position = pos;
  32. }
  33. void Object2D::setPosition( float x, float y )
  34. {
  35. position = Vertex( x, y );
  36. }
  37. void Object2D::setDrehungSpeed( float ds )
  38. {
  39. rSpeed = ds;
  40. }
  41. void Object2D::setDrehung( float drehung )
  42. {
  43. rotation = drehung;
  44. while( rotation > PI * 2 )
  45. rotation -= (float)PI * 2;
  46. while( rotation < 0 )
  47. rotation += (float)PI * 2;
  48. }
  49. void Object2D::addDrehung( float drehung )
  50. {
  51. rotation += drehung;
  52. while( rotation > PI * 2 )
  53. rotation -= (float)PI * 2;
  54. while( rotation < 0 )
  55. rotation += (float)PI * 2;
  56. }
  57. void Object2D::setSize( float size )
  58. {
  59. this->size = size;
  60. }
  61. void Object2D::addSize( float size )
  62. {
  63. this->size += size;
  64. }
  65. void Object2D::setCollision( bool handle )
  66. {
  67. collision = handle;
  68. }
  69. bool Object2D::handleCollision( Object2D *obj )
  70. {
  71. Vertex hp;
  72. if( istModelInnen( obj, &hp ) ) // hp wird auf den aufprallpunkt gesetzt
  73. {
  74. // Geschwindigkeit von diesem objekt mit rotation
  75. Vertex v1 = getSpeed() + getWorldDir( getObjectPos( hp ).rotation( rSpeed ) - getObjectPos( hp ) );
  76. // Geschwindigkeit des anderen Objektes mit rotation
  77. Vertex v2 = obj->getSpeed() + getWorldDir( obj->getObjectPos( hp ).rotation( obj->getDrehungSpeed() ) - obj->getObjectPos( hp ) );
  78. if( ( hp - obj->getPosition() ).getLengthSq() > ( hp + v1 * 0.03f - obj->getPosition() ).getLengthSq() ||
  79. ( hp - getPosition() ).getLengthSq() > ( hp + v2 * 0.03f - getPosition() ).getLengthSq() )
  80. { // nur wenn sie sich aufeinander zu bewegen
  81. float m1 = getMasse() * v1.getLength(); // fläche von Objekt 1
  82. float m2 = obj->getMasse() * v2.getLength(); // fläche von Objekt 2
  83. if( m1 == 0 || m2 == 0 )
  84. return 0; // falls ein objekt keine masse hat ignoriere die kollision
  85. float nm1 = m1 / ( m1 + m2 ); // koeffizient für objekt 2
  86. float nm2 = m2 / ( m1 + m2 ); // koeffizient für Objekt 1
  87. //rSpeed *= nm1; // Drehgeschwindigkeit anpassen (objekt 1)
  88. //speed *= nm1; // Bewegungsgeschwindigkeit anpassen (objekt 1)
  89. //obj->setDrehungSpeed( obj->getDrehungSpeed() * nm2 ); // Drehgeschwindigkeit anpassen (objekt 2)
  90. //obj->setSpeed( obj->getSpeed() * nm2 ); // Bewegungsgeschwindigkeit anpassen (objekt 2)
  91. float speedSumLength = getSpeed().getLength() + obj->getSpeed().getLength();
  92. rSpeed = 0;
  93. speed = Vertex();
  94. obj->setDrehungSpeed( 0 );
  95. obj->setSpeed( Vertex() );
  96. if( v2.x || v2.y )
  97. impuls( hp - v2, v2 );
  98. if( getSpeed().getLength() > 0 )
  99. setSpeed( getSpeed().normalize() * speedSumLength * nm2 );
  100. if( v1.x || v1.y )
  101. obj->impuls( hp - v1, v1 );
  102. if( obj->getSpeed().getLength() > 0 )
  103. obj->setSpeed( obj->getSpeed().normalize() * speedSumLength * nm1 );
  104. return 1;
  105. }
  106. }
  107. return 0;
  108. }
  109. bool Object2D::tick( const WeltInfo &info, double zeit )
  110. {
  111. rotation += rSpeed * (float)zeit;
  112. while( rotation > PI * 2 )
  113. rotation -= (float)PI * 2;
  114. while( rotation < 0 )
  115. rotation += (float)PI * 2;
  116. position += speed * (float)zeit;
  117. while( zeit > 1 )
  118. {
  119. rSpeed -= rSpeed - ( rSpeed / ( 1 + info.airResistance * getLuftWiederstand() ) );
  120. speed -= speed - ( speed / ( 1 + info.airResistance * getLuftWiederstand() ) );
  121. zeit -= 1;
  122. }
  123. rSpeed -= ( rSpeed - ( rSpeed / ( 1 + info.airResistance * getLuftWiederstand() ) ) ) * (float)zeit;
  124. speed -= ( speed - ( speed / ( 1 + info.airResistance * getLuftWiederstand() ) ) ) * (float)zeit;
  125. if( info.circular && info.hasSize && info.size.x && info.size.y )
  126. {
  127. while( position.x > info.size.x )
  128. position.x -= (float)info.size.x;
  129. while( position.x < 0 )
  130. position.x += (float)info.size.x;
  131. while( position.y > info.size.y )
  132. position.y -= (float)info.size.y;
  133. while( position.y < 0 )
  134. position.y += (float)info.size.y;
  135. }
  136. return rSpeed != 0 || speed != Vertex( 0, 0 );
  137. }
  138. bool Object2D::istPunktInnen( Vertex p ) const
  139. {
  140. return 0;
  141. }
  142. bool Object2D::istLinieInnen( Vertex a, Vertex b ) const
  143. {
  144. return 0;
  145. }
  146. bool Object2D::istModelInnen( const Object2D *zObj, Vertex *sp, bool end ) const
  147. {
  148. return 0;
  149. }
  150. Mat3< float > Object2D::getObjectMatrix() const
  151. {
  152. return Mat3<float>::translation( position ) * Mat3<float>::rotation( rotation ) * Mat3<float>::scaling( size );
  153. }
  154. Mat3< float > Object2D::getInverseObjectMatrix() const
  155. {
  156. return Mat3<float>::scaling( 1 / size ) * Mat3<float>::rotation( -rotation ) * Mat3<float>::translation( -position );
  157. }
  158. Vertex Object2D::getObjectPos( Vertex worldPos ) const
  159. {
  160. return ( worldPos - position ).rotation( -rotation ) * ( 1 / size );
  161. }
  162. Vertex Object2D::getObjectDir( Vertex worldDir ) const
  163. {
  164. return Vertex( worldDir.x, worldDir.y ).rotation( -rotation ) * ( 1 / size );
  165. }
  166. Vertex Object2D::getWorldPos( Vertex objectPos ) const
  167. {
  168. return ( Vertex( objectPos ) * size ).rotation( rotation ) + position;
  169. }
  170. Vertex Object2D::getWorldDir( Vertex objectDir ) const
  171. {
  172. return ( Vertex( objectDir ) * size ).rotation( rotation );
  173. }
  174. Vertex Object2D::getSpeed() const
  175. {
  176. return speed;
  177. }
  178. Vertex Object2D::getPosition() const
  179. {
  180. return position;
  181. }
  182. float Object2D::getDrehungSpeed() const
  183. {
  184. return rSpeed;
  185. }
  186. float Object2D::getDrehung() const
  187. {
  188. return rotation;
  189. }
  190. float Object2D::getSize() const
  191. {
  192. return size;
  193. }
  194. bool Object2D::calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const
  195. {
  196. return 0;
  197. }
  198. float Object2D::getLuftWiederstand() const
  199. {
  200. return 0;
  201. }
  202. float Object2D::getMasse() const
  203. {
  204. return 0;
  205. }
  206. bool Object2D::canCollide()
  207. {
  208. return collision;
  209. }
  210. Object2D *Object2D::getThis()
  211. {
  212. ref++;
  213. return this;
  214. }
  215. Object2D *Object2D::release()
  216. {
  217. if( !--ref )
  218. delete this;
  219. return 0;
  220. }
  221. Welt2D::Welt2D()
  222. {
  223. objects = new RCArray< Object2D >();
  224. memset( &info, 0, sizeof( WeltInfo ) );
  225. ref = 1;
  226. }
  227. Welt2D::~Welt2D()
  228. {
  229. objects->release();
  230. }
  231. void Welt2D::setAirResistance( float resistance )
  232. {
  233. info.airResistance = resistance;
  234. }
  235. void Welt2D::setSize( int width, int height )
  236. {
  237. info.size.x = width;
  238. info.size.y = height;
  239. }
  240. void Welt2D::setSize( bool hasSize )
  241. {
  242. info.hasSize = hasSize;
  243. }
  244. void Welt2D::setCircular( bool circular )
  245. {
  246. info.circular = circular;
  247. }
  248. Object2D *Welt2D::zObjectAt( int x, int y )
  249. {
  250. for( auto o = objects->getIterator(); o; o++ )
  251. {
  252. if( o->istPunktInnen( Punkt( x, y ) ) )
  253. return o._;
  254. }
  255. return 0;
  256. }
  257. Object2D *Welt2D::getObjectAt( int x, int y )
  258. {
  259. Object2D *tmp = zObjectAt( x, y );
  260. return tmp ? tmp->getThis() : 0;
  261. }
  262. void Welt2D::addObject( Object2D *obj )
  263. {
  264. objects->add( obj );
  265. }
  266. void Welt2D::removeObject( Object2D *zObj )
  267. {
  268. int anz = objects->getEintragAnzahl();
  269. for( int i = 0; i < anz; i++ )
  270. {
  271. if( objects->z( i ) == zObj )
  272. {
  273. objects->remove( i );
  274. i--;
  275. }
  276. }
  277. }
  278. void Welt2D::removeAll()
  279. {
  280. objects->leeren();
  281. }
  282. void Welt2D::explosion( Vertex worldPos, float intensity, float maxRad )
  283. {
  284. maxRad = maxRad * maxRad;
  285. for( auto obj = objects->getIterator(); obj; obj++ )
  286. {
  287. if( info.circular && info.hasSize && info.size.x && info.size.y )
  288. {
  289. Vertex offsets[] = {
  290. Vertex( 0, 0 ),
  291. Vertex( (float)info.size.x, 0 ),
  292. Vertex( 0, (float)info.size.y ),
  293. Vertex( (float)info.size.x, (float)info.size.y ),
  294. Vertex( (float)-info.size.x, 0 ),
  295. Vertex( 0, (float)-info.size.y ),
  296. Vertex( (float)-info.size.x, (float)-info.size.y ),
  297. Vertex( (float)-info.size.x, (float)info.size.y ),
  298. Vertex( (float)info.size.x, (float)-info.size.y ) };
  299. Vertex offset;
  300. float minDist = INFINITY;
  301. for( Vertex p : offsets )
  302. {
  303. float dist = ( obj->getPosition() - (worldPos - p) ).getLengthSq();
  304. if( dist < minDist )
  305. {
  306. minDist = dist;
  307. offset = p;
  308. }
  309. }
  310. if( ( obj->getPosition() - (worldPos - offset) ).getLengthSq() < maxRad )
  311. obj->explosion( worldPos - offset, intensity );
  312. }
  313. else if( ( obj->getPosition() - worldPos ).getLengthSq() < maxRad )
  314. obj->explosion( worldPos, intensity );
  315. }
  316. }
  317. void Welt2D::impuls( Vertex worldPos, Vertex worldDir )
  318. {
  319. Vertex hitPoint;
  320. float dist = INFINITY;
  321. Object2D *o = 0;
  322. for( auto obj = objects->getIterator(); obj; obj++ )
  323. {
  324. if( obj->calcHitPoint( worldPos, worldDir, hitPoint ) )
  325. {
  326. if( ( hitPoint - worldPos ).getLengthSq() < dist )
  327. {
  328. dist = ( hitPoint - worldPos ).getLengthSq();
  329. o = obj;
  330. }
  331. }
  332. }
  333. if( o )
  334. o->impuls( worldPos, worldDir );
  335. }
  336. bool Welt2D::tick( double zeit )
  337. {
  338. bool ret = 0;
  339. for( auto obj = objects->getIterator(); obj; obj++ )
  340. {
  341. if( obj.hasNext() && obj->canCollide() )
  342. {
  343. for( auto obj2 = obj.next(); obj2; obj2++ )
  344. {
  345. if( obj2->canCollide() )
  346. obj->handleCollision( obj2 );
  347. }
  348. }
  349. ret |= obj->tick( info, zeit );
  350. }
  351. return ret;
  352. }
  353. void Welt2D::render( Mat3< float > &kamMat, Punkt size, Bild &zRObj, int xOffset, int yOffset, const char *kamName )
  354. {
  355. for( auto obj = objects->getIterator(); obj; obj++ )
  356. {
  357. Rect2< float > bnd = obj->getBoundingBox();
  358. Vertex topRight = Vertex( bnd.bottomRight.x, bnd.topLeft.y );
  359. Vertex bottomLeft = Vertex( bnd.topLeft.x, bnd.bottomRight.y );
  360. Mat3< float > km = kamMat * Mat3<float>::translation( Vertex( (float)xOffset, (float)yOffset ) );
  361. bnd.bottomRight = km * bnd.bottomRight;
  362. bnd.topLeft = km * bnd.topLeft;
  363. topRight = km * topRight;
  364. bottomLeft = km * bottomLeft;
  365. if( ( bnd.bottomRight.x >= 0 && bnd.bottomRight.x < size.x ) ||
  366. ( bnd.bottomRight.y >= 0 && bnd.bottomRight.y < size.y ) ||
  367. ( bnd.topLeft.x >= 0 && bnd.topLeft.x < size.x ) ||
  368. ( bnd.topLeft.y >= 0 && bnd.topLeft.y < size.y ) ||
  369. ( topRight.x >= 0 && topRight.x < size.x ) ||
  370. ( topRight.y >= 0 && topRight.y < size.y ) ||
  371. ( bottomLeft.x >= 0 && bottomLeft.x < size.x ) ||
  372. ( bottomLeft.y >= 0 && bottomLeft.y < size.y ) )
  373. obj->render( km, zRObj, kamName );
  374. }
  375. }
  376. void Welt2D::render( Mat3< float > &kamMat, Punkt size, Bild &zRObj, const char *kamName )
  377. {
  378. if( !info.hasSize || !info.circular )
  379. {
  380. for( auto obj = objects->getIterator(); obj; obj++ )
  381. {
  382. Rect2< float > bnd = obj->getBoundingBox();
  383. Vertex topRight = Vertex( bnd.topLeft.y, bnd.bottomRight.x );
  384. Vertex bottomLeft = Vertex( bnd.topLeft.x, bnd.bottomRight.y );
  385. bnd.bottomRight = kamMat * bnd.bottomRight;
  386. bnd.topLeft = kamMat * bnd.topLeft;
  387. topRight = kamMat * topRight;
  388. bottomLeft = kamMat * bottomLeft;
  389. if( ( bnd.bottomRight.x >= 0 && bnd.bottomRight.x < size.x ) ||
  390. ( bnd.bottomRight.y >= 0 && bnd.bottomRight.y < size.y ) ||
  391. ( bnd.topLeft.x >= 0 && bnd.topLeft.x < size.x ) ||
  392. ( bnd.topLeft.y >= 0 && bnd.topLeft.y < size.y ) ||
  393. ( topRight.x >= 0 && topRight.x < size.x ) ||
  394. ( topRight.y >= 0 && topRight.y < size.y ) ||
  395. ( bottomLeft.x >= 0 && bottomLeft.x < size.x ) ||
  396. ( bottomLeft.y >= 0 && bottomLeft.y < size.y ) )
  397. obj->render( kamMat, zRObj, kamName );
  398. }
  399. }
  400. else if( info.circular )
  401. {
  402. render( kamMat, size, zRObj, 0, 0, kamName );
  403. render( kamMat, size, zRObj, info.size.x, 0, kamName );
  404. render( kamMat, size, zRObj, 0, info.size.y, kamName );
  405. render( kamMat, size, zRObj, info.size.x, info.size.y, kamName );
  406. render( kamMat, size, zRObj, -info.size.x, 0, kamName );
  407. render( kamMat, size, zRObj, 0, -info.size.y, kamName );
  408. render( kamMat, size, zRObj, -info.size.x, -info.size.y, kamName );
  409. render( kamMat, size, zRObj, -info.size.x, +info.size.y, kamName );
  410. render( kamMat, size, zRObj, +info.size.x, -info.size.y, kamName );
  411. }
  412. }
  413. const WeltInfo &Welt2D::getWorldInfo() const
  414. {
  415. return info;
  416. }
  417. Welt2D *Welt2D::getThis()
  418. {
  419. ref++;
  420. return this;
  421. }
  422. Welt2D *Welt2D::release()
  423. {
  424. if( !--ref )
  425. delete this;
  426. return 0;
  427. }