Welt2D.cpp 12 KB

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