main.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Basiques
  2. # include <iostream>
  3. // SDL
  4. # include <SDL/SDL.h>
  5. # undef main
  6. # include <SDL/SDL_gfxPrimitives.h>
  7. // bBox2D
  8. # include <box2d/box2d.h>
  9. // Missiles
  10. # define MULTI 200.0f
  11. # include "Missiles.h"
  12. // Graphismes
  13. # define SCREEN_H 810
  14. # define SCREEN_W 810
  15. // Weapon
  16. struct Weapon
  17. {
  18. b2Vec2 loc;
  19. Identity missile;
  20. Uint32 prev;
  21. Uint32 del;
  22. };
  23. // Main
  24. int main(int argc, char** argv)
  25. {
  26. /// [1] Démarrage
  27. // [1.1] Démarrages SDL
  28. if ( SDL_Init( SDL_INIT_VIDEO ) < 0)
  29. {
  30. std::cout << "Impossible d'initialiser la SDL: " << SDL_GetError() << std::endl;
  31. return 1;
  32. }
  33. // [1.2] Préparation de fermeture
  34. atexit(SDL_Quit);
  35. // [1.3] Para-fenêtre
  36. SDL_WM_SetCaption("Box2D - Balistique", 0);
  37. /// [2] Préparation des composants SDL
  38. // [2.1] Préparation de la fenêtre
  39. SDL_Surface* screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
  40. if ( !screen )
  41. {
  42. std::cout << "Bug à l'initialisation: " << SDL_GetError() << std::endl;
  43. return 1;
  44. }
  45. SDL_Surface* persistant = SDL_CreateRGBSurface( SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0, 0, 0, 0);
  46. SDL_Surface* blackout = SDL_CreateRGBSurface( SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0, 0, 0, 0);
  47. SDL_SetAlpha(blackout, SDL_SRCALPHA, 25);
  48. bool superVisual( true );
  49. // [2.2] Préparation variables
  50. SDL_Rect mouse({ 400, 200, 0, 0 });
  51. SDL_Rect pxpos({ 400, 200, 0, 0 });
  52. SDL_Rect pxpos2({ 400, 200, 0, 0 });
  53. // [2.4] Préparation du temps
  54. Uint32 frameRate( 60 );
  55. Uint32 tprev(0), twait( 1000 / frameRate );
  56. bool pause( false );
  57. Uint32 weap_wait(500);
  58. // [2.5] Préparation des messages
  59. std::string msg("Victor");
  60. Uint32 vie(30);
  61. /// [3] Box2D
  62. // Trucs
  63. B2_NOT_USED(argc);
  64. B2_NOT_USED(argv);
  65. // Construct a world object
  66. b2Vec2 gravity(0.0f, 0.0f);
  67. b2World world(gravity);
  68. // Define the dynamic body container
  69. std::vector<b2Body*> deadBodies;
  70. // Simulation settings
  71. float timeStep = 1.0f / frameRate;
  72. int32 velocityIterations = 8;
  73. int32 positionIterations = 3;
  74. // Variables
  75. b2Vec2 position, force;
  76. float angle;
  77. Entity* descr( nullptr );
  78. // Define the edge body
  79. b2BodyDef bodyDef;
  80. bodyDef.position.Set(0.0f, 0.0f);
  81. bodyDef.userData.pointer = (uintptr_t) new Entity( {0.0f, LAND} );
  82. b2Body* areaBody = world.CreateBody(&bodyDef);
  83. b2Vec2 vs[4];
  84. float areah( (float)screen->h / MULTI );
  85. float areaw( (float)screen->w / MULTI );
  86. vs[0].Set( 0.0f, 0.0f );
  87. vs[1].Set( 0.0f, areah );
  88. vs[2].Set( areaw, areah );
  89. vs[3].Set( areaw, 0.0f );
  90. b2ChainShape chain;
  91. chain.CreateLoop(vs, 4);
  92. areaBody->CreateFixture(&chain, 0.0f);
  93. // Define the plane body
  94. bodyDef.type = b2_dynamicBody;
  95. bodyDef.position.Set(areaw * 0.5f, areaw * 0.5f );
  96. bodyDef.userData.pointer = (uintptr_t) new Entity( {0.05f, PLANE} );
  97. bodyDef.linearDamping = 0.01f;
  98. bodyDef.fixedRotation = true ;
  99. b2Body* plane = world.CreateBody(&bodyDef);
  100. b2CircleShape dynamicCircle;
  101. dynamicCircle.m_radius = 0.05f ;
  102. b2FixtureDef fixtureDef;
  103. fixtureDef.shape = &dynamicCircle;
  104. fixtureDef.density = 10.0f;
  105. fixtureDef.friction = 0.3f;
  106. fixtureDef.restitution = 0.5f;
  107. plane->CreateFixture(&fixtureDef);
  108. // Define the tourel list
  109. std::vector<Weapon> tourelle;
  110. Identity missile(INERT);
  111. Uint32 weap_color[8] = { 0xffffffff,
  112. 0xffffffff,
  113. 0xff0000ff,
  114. 0x00ff00ff,
  115. 0x0000ffff,
  116. 0xffff00ff,
  117. 0xff00ffff,
  118. 0x00ffffff };
  119. // Define thruster
  120. bool thrust_up(false);
  121. bool thrust_down(false);
  122. bool thrust_left(false);
  123. bool thrust_right(false);
  124. bool foresee(false);
  125. /// [4] Boucle principale
  126. bool done = false;
  127. SDL_Event event;
  128. while (!done)
  129. {
  130. // [4.1] Gestion évènements
  131. while (SDL_PollEvent(&event))
  132. {
  133. switch (event.type)
  134. {
  135. case SDL_QUIT:
  136. done = true;
  137. break;
  138. case SDL_KEYDOWN:
  139. switch( event.key.keysym.sym )
  140. {
  141. case SDLK_ESCAPE :
  142. done = true;
  143. break;
  144. case SDLK_BACKSPACE :
  145. std::cout << std::endl << "Destruction des tourelles." << std::endl << std::endl;
  146. tourelle.clear();
  147. break;
  148. case SDLK_SPACE :
  149. pause = !pause ;
  150. break;
  151. case SDLK_KP1:
  152. case SDLK_1:
  153. std::cout << "Tir basique." << std::endl;
  154. missile = INERT ;
  155. break;
  156. case SDLK_KP2:
  157. case SDLK_2:
  158. std::cout << "Tir d'anticipation rectiligne." << std::endl;
  159. missile = ANG ;
  160. break;
  161. case SDLK_KP3:
  162. case SDLK_3:
  163. std::cout << "Missile d'accélération linéaire." << std::endl;
  164. missile = ARROW ;
  165. break;
  166. case SDLK_KP4:
  167. case SDLK_4:
  168. std::cout << "Missile d'accélération électrique (1/r^2)." << std::endl;
  169. missile = CHARGE ;
  170. break;
  171. case SDLK_a :
  172. superVisual = !superVisual;
  173. std::cout << "Super visual : " << superVisual << std::endl;
  174. break;
  175. case SDLK_z :
  176. weap_wait += 25 ;
  177. std::cout << "weap_wait += 25" << std::endl;
  178. break;
  179. case SDLK_s :
  180. weap_wait -= 25 ;
  181. std::cout << "weap_wait -= 25" << std::endl;
  182. break;
  183. case SDLK_e :
  184. vie = 30;
  185. std::cout << "vie = 30" << std::endl;
  186. break;
  187. case SDLK_r :
  188. foresee = !foresee;
  189. if ( foresee )
  190. std::cout << "Anticipation activée." << std::endl;
  191. else
  192. std::cout << "Les missiles auront du retard." << std::endl;
  193. break;
  194. case SDLK_LEFT :
  195. thrust_left = true ;
  196. break;
  197. case SDLK_RIGHT :
  198. thrust_right = true ;
  199. break;
  200. case SDLK_UP :
  201. thrust_up = true ;
  202. break;
  203. case SDLK_DOWN :
  204. thrust_down = true ;
  205. break;
  206. }
  207. break;
  208. case SDL_KEYUP:
  209. switch( event.key.keysym.sym )
  210. {
  211. case SDLK_LEFT :
  212. thrust_left = false ;
  213. break;
  214. case SDLK_RIGHT :
  215. thrust_right = false ;
  216. break;
  217. case SDLK_UP :
  218. thrust_up = false ;
  219. break;
  220. case SDLK_DOWN :
  221. thrust_down = false ;
  222. break;
  223. }
  224. break;
  225. case SDL_MOUSEMOTION:
  226. mouse.x = event.motion.x ;
  227. mouse.y = event.motion.y ;
  228. break;
  229. case SDL_MOUSEBUTTONDOWN:
  230. std::cout << "Création tourelle." << std::endl;
  231. tourelle.push_back({b2Vec2( (float)mouse.x/MULTI, (float)mouse.y/MULTI),
  232. missile,
  233. SDL_GetTicks(),
  234. weap_wait});
  235. break;
  236. case SDL_MOUSEBUTTONUP:
  237. break;
  238. } // end switch event type
  239. } // end of message processing
  240. // [4.2] Calculs
  241. // Reset graphismes
  242. if ( superVisual ) {
  243. SDL_BlitSurface( blackout, 0x0, persistant, 0x0 );
  244. SDL_BlitSurface( persistant, 0x0, screen, 0x0 );
  245. }
  246. else {
  247. SDL_FillRect( screen, 0x0, 0x00000000 );
  248. }
  249. // Tirs tourelle
  250. for ( unsigned int k(0); k < tourelle.size() && vie > 0; k++ )
  251. {
  252. if ( SDL_GetTicks() - tourelle[k].prev > tourelle[k].del )
  253. {
  254. tourelle[k].prev = SDL_GetTicks();
  255. createInert( tourelle[k].loc, plane, world, tourelle[k].missile );
  256. }
  257. }
  258. // Déplacement
  259. if ( vie > 0 )
  260. {
  261. force = b2Vec2_zero;
  262. if ( thrust_left )
  263. force.x -= 1.0f;
  264. if ( thrust_right )
  265. force.x += 1.0f;
  266. if ( thrust_up )
  267. force.y -= 1.0f;
  268. if ( thrust_down )
  269. force.y += 1.0f;
  270. plane->ApplyLinearImpulseToCenter( 0.004f * force, true );
  271. }
  272. // It is generally best to keep the time step and iterations fixed.
  273. if ( !pause )
  274. world.Step(timeStep, velocityIterations, positionIterations);
  275. // Contact sur plane
  276. position = plane->GetPosition();
  277. pxpos.x = position.x * MULTI ;
  278. pxpos.y = position.y * MULTI ;
  279. for ( b2ContactEdge* ce( plane->GetContactList() ); ce && vie > 0; ce = ce->next )
  280. if ( ce->contact->IsTouching() )
  281. {
  282. vie -- ;
  283. filledCircleRGBA( screen, pxpos.x, pxpos.y, 13, 255, 255, 255, 255 );
  284. circleRGBA( persistant, pxpos.x, pxpos.y, 13, 255, 128, 0, 255 );
  285. }
  286. // Mise à jour des trajectoires
  287. updateMissiles( world, plane, foresee );
  288. // [4.3] Dessin des composants
  289. for ( b2Body* b( world.GetBodyList() ); b; b = b->GetNext() )
  290. {
  291. // Besoin d'afficher ?
  292. descr = (Entity*)b->GetUserData().pointer;
  293. if ( descr == nullptr || descr->id == LAND )
  294. continue ;
  295. // Affichage classique
  296. position = b->GetPosition();
  297. pxpos.x = position.x * MULTI ;
  298. pxpos.y = position.y * MULTI ;
  299. circleColor( screen, pxpos.x, pxpos.y, descr->rayon * MULTI, 0xddddddff );
  300. // Affichage persistant
  301. position -= timeStep * b->GetLinearVelocity();
  302. pxpos2.x = position.x * MULTI ;
  303. pxpos2.y = position.y * MULTI ;
  304. lineColor( persistant, pxpos.x, pxpos.y, pxpos2.x, pxpos2.y, weap_color[descr->id] );
  305. lineColor( screen, pxpos.x, pxpos.y, pxpos2.x, pxpos2.y, weap_color[descr->id] );
  306. }
  307. for ( unsigned int k(0); k < tourelle.size(); k++ )
  308. {
  309. circleColor( screen, tourelle[k].loc.x * MULTI, tourelle[k].loc.y * MULTI, 0.05f * MULTI, weap_color[tourelle[k].missile] );
  310. }
  311. // Messages
  312. msg = "Ratio CPU : " ;
  313. msg += std::to_string( ((float)SDL_GetTicks() - tprev) * 100 / twait ) ;
  314. msg += " pourcents." ;
  315. stringRGBA( screen, 16, 16, msg.c_str(), 0, 255, 0, 255 );
  316. msg = "Vie : " ;
  317. msg += std::to_string( vie ) ;
  318. msg += " | " ;
  319. for ( unsigned int i(0); i < vie ; i ++ )
  320. msg += "#" ;
  321. for ( unsigned int i(vie); i < 30 ; i ++ )
  322. msg += "-" ;
  323. stringRGBA( screen, 16, 25, msg.c_str(), 0, 255, 0, 255 );
  324. msg = "Delai tourelle : " ;
  325. msg += std::to_string( weap_wait ) ;
  326. msg += " ms." ;
  327. stringRGBA( screen, 16, 34, msg.c_str(), 0, 255, 0, 255 );
  328. SDL_Flip(screen);
  329. // [4.4] Temps
  330. while( SDL_GetTicks() - tprev < twait )
  331. {
  332. if ( SDL_GetTicks() - tprev < twait/2 )
  333. SDL_Delay( twait/3 );
  334. }
  335. tprev = SDL_GetTicks();
  336. } //fin bcl principale
  337. ///[5] Destruction des composants
  338. return 0;
  339. }