|
@@ -0,0 +1,386 @@
|
|
|
+// Basiques
|
|
|
+# include <iostream>
|
|
|
+
|
|
|
+// SDL
|
|
|
+# include <SDL/SDL.h>
|
|
|
+# undef main
|
|
|
+# include <SDL/SDL_gfxPrimitives.h>
|
|
|
+
|
|
|
+// bBox2D
|
|
|
+# include <Box2D/Box2D.h>
|
|
|
+
|
|
|
+// Missiles
|
|
|
+# define MULTI 200.0f
|
|
|
+# include "Missiles.h"
|
|
|
+
|
|
|
+// Graphismes
|
|
|
+# define SCREEN_H 810
|
|
|
+# define SCREEN_W 810
|
|
|
+
|
|
|
+// Weapon
|
|
|
+struct Weapon
|
|
|
+{
|
|
|
+ b2Vec2 loc;
|
|
|
+ Identity missile;
|
|
|
+ Uint32 prev;
|
|
|
+ Uint32 del;
|
|
|
+};
|
|
|
+
|
|
|
+// Main
|
|
|
+int main(int argc, char** argv)
|
|
|
+{
|
|
|
+ /// [1] Démarrage
|
|
|
+ // [1.1] Démarrages SDL
|
|
|
+ if ( SDL_Init( SDL_INIT_VIDEO ) < 0)
|
|
|
+ {
|
|
|
+ std::cout << "Impossible d'initialiser la SDL: " << SDL_GetError() << std::endl;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // [1.2] Préparation de fermeture
|
|
|
+ atexit(SDL_Quit);
|
|
|
+
|
|
|
+ // [1.3] Para-fenêtre
|
|
|
+ SDL_WM_SetCaption("Box2D - Balistique", 0);
|
|
|
+
|
|
|
+ /// [2] Préparation des composants SDL
|
|
|
+ // [2.1] Préparation de la fenêtre
|
|
|
+ SDL_Surface* screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
|
|
|
+ if ( !screen )
|
|
|
+ {
|
|
|
+ std::cout << "Bug à l'initialisation: " << SDL_GetError() << std::endl;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ SDL_Surface* persistant = SDL_CreateRGBSurface( SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0, 0, 0, 0);
|
|
|
+ SDL_Surface* blackout = SDL_CreateRGBSurface( SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0, 0, 0, 0);
|
|
|
+ SDL_SetAlpha(blackout, SDL_SRCALPHA, 25);
|
|
|
+ bool superVisual( true );
|
|
|
+
|
|
|
+ // [2.2] Préparation variables
|
|
|
+ SDL_Rect mouse({ 400, 200, 0, 0 });
|
|
|
+ SDL_Rect pxpos({ 400, 200, 0, 0 });
|
|
|
+ SDL_Rect pxpos2({ 400, 200, 0, 0 });
|
|
|
+
|
|
|
+ // [2.4] Préparation du temps
|
|
|
+ Uint32 frameRate( 60 );
|
|
|
+ Uint32 tprev(0), twait( 1000 / frameRate );
|
|
|
+ bool pause( false );
|
|
|
+ Uint32 weap_wait(500);
|
|
|
+
|
|
|
+ // [2.5] Préparation des messages
|
|
|
+ std::string msg("Victor");
|
|
|
+ Uint32 vie(30);
|
|
|
+
|
|
|
+ /// [3] Box2D
|
|
|
+ // Trucs
|
|
|
+ B2_NOT_USED(argc);
|
|
|
+ B2_NOT_USED(argv);
|
|
|
+
|
|
|
+ // Construct a world object
|
|
|
+ b2Vec2 gravity(0.0f, 0.0f);
|
|
|
+ b2World world(gravity);
|
|
|
+
|
|
|
+ // Define the dynamic body container
|
|
|
+ std::vector<b2Body*> deadBodies;
|
|
|
+
|
|
|
+ // Simulation settings
|
|
|
+ float32 timeStep = 1.0f / frameRate;
|
|
|
+ int32 velocityIterations = 8;
|
|
|
+ int32 positionIterations = 3;
|
|
|
+
|
|
|
+ // Variables
|
|
|
+ b2Vec2 position, force;
|
|
|
+ float32 angle;
|
|
|
+ Entity* descr( nullptr );
|
|
|
+
|
|
|
+ // Define the edge body
|
|
|
+ b2BodyDef bodyDef;
|
|
|
+ bodyDef.position.Set(0.0f, 0.0f);
|
|
|
+ bodyDef.userData = new Entity( {0.0f, LAND} );
|
|
|
+ b2Body* areaBody = world.CreateBody(&bodyDef);
|
|
|
+
|
|
|
+ b2Vec2 vs[4];
|
|
|
+ float32 areah( (float32)screen->h / MULTI );
|
|
|
+ float32 areaw( (float32)screen->w / MULTI );
|
|
|
+ vs[0].Set( 0.0f, 0.0f );
|
|
|
+ vs[1].Set( 0.0f, areah );
|
|
|
+ vs[2].Set( areaw, areah );
|
|
|
+ vs[3].Set( areaw, 0.0f );
|
|
|
+ b2ChainShape chain;
|
|
|
+ chain.CreateLoop(vs, 4);
|
|
|
+ areaBody->CreateFixture(&chain, 0.0f);
|
|
|
+
|
|
|
+ // Define the plane body
|
|
|
+ bodyDef.type = b2_dynamicBody;
|
|
|
+ bodyDef.position.Set(areaw * 0.5f, areaw * 0.5f );
|
|
|
+ bodyDef.userData = new Entity( {0.05f, PLANE} );
|
|
|
+ bodyDef.linearDamping = 0.01f;
|
|
|
+ bodyDef.fixedRotation = true ;
|
|
|
+ b2Body* plane = world.CreateBody(&bodyDef);
|
|
|
+
|
|
|
+ b2CircleShape dynamicCircle;
|
|
|
+ dynamicCircle.m_radius = 0.05f ;
|
|
|
+ b2FixtureDef fixtureDef;
|
|
|
+ fixtureDef.shape = &dynamicCircle;
|
|
|
+
|
|
|
+ fixtureDef.density = 10.0f;
|
|
|
+ fixtureDef.friction = 0.3f;
|
|
|
+ fixtureDef.restitution = 0.5f;
|
|
|
+
|
|
|
+ plane->CreateFixture(&fixtureDef);
|
|
|
+
|
|
|
+ // Define the tourel list
|
|
|
+ std::vector<Weapon> tourelle;
|
|
|
+ Identity missile(INERT);
|
|
|
+ Uint32 weap_color[8] = { 0xffffffff,
|
|
|
+ 0xffffffff,
|
|
|
+ 0xff0000ff,
|
|
|
+ 0x00ff00ff,
|
|
|
+ 0x0000ffff,
|
|
|
+ 0xffff00ff,
|
|
|
+ 0xff00ffff,
|
|
|
+ 0x00ffffff };
|
|
|
+
|
|
|
+ // Define thruster
|
|
|
+ bool thrust_up(false);
|
|
|
+ bool thrust_down(false);
|
|
|
+ bool thrust_left(false);
|
|
|
+ bool thrust_right(false);
|
|
|
+ bool foresee(false);
|
|
|
+
|
|
|
+ /// [4] Boucle principale
|
|
|
+ bool done = false;
|
|
|
+ SDL_Event event;
|
|
|
+ while (!done)
|
|
|
+ {
|
|
|
+ // [4.1] Gestion évènements
|
|
|
+ while (SDL_PollEvent(&event))
|
|
|
+ {
|
|
|
+ switch (event.type)
|
|
|
+ {
|
|
|
+ case SDL_QUIT:
|
|
|
+ done = true;
|
|
|
+ break;
|
|
|
+ case SDL_KEYDOWN:
|
|
|
+ switch( event.key.keysym.sym )
|
|
|
+ {
|
|
|
+ case SDLK_ESCAPE :
|
|
|
+ done = true;
|
|
|
+ break;
|
|
|
+ case SDLK_BACKSPACE :
|
|
|
+ std::cout << std::endl << "Destruction des tourelles." << std::endl << std::endl;
|
|
|
+ tourelle.clear();
|
|
|
+ break;
|
|
|
+ case SDLK_SPACE :
|
|
|
+ pause = !pause ;
|
|
|
+ break;
|
|
|
+ case SDLK_KP1:
|
|
|
+ std::cout << "Tir basique." << std::endl;
|
|
|
+ missile = INERT ;
|
|
|
+ break;
|
|
|
+ case SDLK_KP2:
|
|
|
+ std::cout << "Tir d'anticipation rectiligne." << std::endl;
|
|
|
+ missile = ANG ;
|
|
|
+ break;
|
|
|
+ case SDLK_KP3:
|
|
|
+ std::cout << "Missile d'accélération linéaire." << std::endl;
|
|
|
+ missile = ARROW ;
|
|
|
+ break;
|
|
|
+ case SDLK_KP4:
|
|
|
+ std::cout << "Missile d'accélération électrique (1/r^2)." << std::endl;
|
|
|
+ missile = CHARGE ;
|
|
|
+ break;
|
|
|
+ case SDLK_a :
|
|
|
+ superVisual = !superVisual;
|
|
|
+ std::cout << "Super visual : " << superVisual << std::endl;
|
|
|
+ break;
|
|
|
+ case SDLK_z :
|
|
|
+ weap_wait += 25 ;
|
|
|
+ std::cout << "weap_wait += 25" << std::endl;
|
|
|
+ break;
|
|
|
+ case SDLK_s :
|
|
|
+ weap_wait -= 25 ;
|
|
|
+ std::cout << "weap_wait -= 25" << std::endl;
|
|
|
+ break;
|
|
|
+ case SDLK_e :
|
|
|
+ vie = 30;
|
|
|
+ std::cout << "vie = 30" << std::endl;
|
|
|
+ break;
|
|
|
+ case SDLK_r :
|
|
|
+ foresee = !foresee;
|
|
|
+ if ( foresee )
|
|
|
+ std::cout << "Anticipation activée." << std::endl;
|
|
|
+ else
|
|
|
+ std::cout << "Les missiles auront du retard." << std::endl;
|
|
|
+ break;
|
|
|
+ case SDLK_LEFT :
|
|
|
+ thrust_left = true ;
|
|
|
+ break;
|
|
|
+ case SDLK_RIGHT :
|
|
|
+ thrust_right = true ;
|
|
|
+ break;
|
|
|
+ case SDLK_UP :
|
|
|
+ thrust_up = true ;
|
|
|
+ break;
|
|
|
+ case SDLK_DOWN :
|
|
|
+ thrust_down = true ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case SDL_KEYUP:
|
|
|
+ switch( event.key.keysym.sym )
|
|
|
+ {
|
|
|
+ case SDLK_LEFT :
|
|
|
+ thrust_left = false ;
|
|
|
+ break;
|
|
|
+ case SDLK_RIGHT :
|
|
|
+ thrust_right = false ;
|
|
|
+ break;
|
|
|
+ case SDLK_UP :
|
|
|
+ thrust_up = false ;
|
|
|
+ break;
|
|
|
+ case SDLK_DOWN :
|
|
|
+ thrust_down = false ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case SDL_MOUSEMOTION:
|
|
|
+ mouse.x = event.motion.x ;
|
|
|
+ mouse.y = event.motion.y ;
|
|
|
+ break;
|
|
|
+ case SDL_MOUSEBUTTONDOWN:
|
|
|
+ std::cout << "Création tourelle." << std::endl;
|
|
|
+ tourelle.push_back({b2Vec2( (float32)mouse.x/MULTI, (float32)mouse.y/MULTI),
|
|
|
+ missile,
|
|
|
+ SDL_GetTicks(),
|
|
|
+ weap_wait});
|
|
|
+ break;
|
|
|
+ case SDL_MOUSEBUTTONUP:
|
|
|
+ break;
|
|
|
+ } // end switch event type
|
|
|
+ } // end of message processing
|
|
|
+
|
|
|
+ // [4.2] Calculs
|
|
|
+ // Reset graphismes
|
|
|
+ if ( superVisual ) {
|
|
|
+ SDL_BlitSurface( blackout, 0x0, persistant, 0x0 );
|
|
|
+ SDL_BlitSurface( persistant, 0x0, screen, 0x0 );
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ SDL_FillRect( screen, 0x0, 0x00000000 );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Tirs tourelle
|
|
|
+ for ( unsigned int k(0); k < tourelle.size() && vie > 0; k++ )
|
|
|
+ {
|
|
|
+ if ( SDL_GetTicks() - tourelle[k].prev > tourelle[k].del )
|
|
|
+ {
|
|
|
+ tourelle[k].prev = SDL_GetTicks();
|
|
|
+ createInert( tourelle[k].loc, plane, world, tourelle[k].missile );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Déplacement
|
|
|
+ if ( vie > 0 )
|
|
|
+ {
|
|
|
+ force = b2Vec2_zero;
|
|
|
+
|
|
|
+ if ( thrust_left )
|
|
|
+ force.x -= 1.0f;
|
|
|
+ if ( thrust_right )
|
|
|
+ force.x += 1.0f;
|
|
|
+ if ( thrust_up )
|
|
|
+ force.y -= 1.0f;
|
|
|
+ if ( thrust_down )
|
|
|
+ force.y += 1.0f;
|
|
|
+
|
|
|
+ plane->ApplyLinearImpulseToCenter( 0.004f * force, true );
|
|
|
+ }
|
|
|
+
|
|
|
+ // It is generally best to keep the time step and iterations fixed.
|
|
|
+ if ( !pause )
|
|
|
+ world.Step(timeStep, velocityIterations, positionIterations);
|
|
|
+
|
|
|
+ // Contact sur plane
|
|
|
+ position = plane->GetPosition();
|
|
|
+ pxpos.x = position.x * MULTI ;
|
|
|
+ pxpos.y = position.y * MULTI ;
|
|
|
+
|
|
|
+ for ( b2ContactEdge* ce( plane->GetContactList() ); ce && vie > 0; ce = ce->next )
|
|
|
+ if ( ce->contact->IsTouching() )
|
|
|
+ {
|
|
|
+ vie -- ;
|
|
|
+ filledCircleRGBA( screen, pxpos.x, pxpos.y, 13, 255, 255, 255, 255 );
|
|
|
+ circleRGBA( persistant, pxpos.x, pxpos.y, 13, 255, 128, 0, 255 );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Mise à jour des trajectoires
|
|
|
+ updateMissiles( world, plane, foresee );
|
|
|
+
|
|
|
+ // [4.3] Dessin des composants
|
|
|
+ for ( b2Body* b( world.GetBodyList() ); b; b = b->GetNext() )
|
|
|
+ {
|
|
|
+ // Besoin d'afficher ?
|
|
|
+ descr = (Entity*)b->GetUserData();
|
|
|
+
|
|
|
+ if ( descr == nullptr || descr->id == LAND )
|
|
|
+ continue ;
|
|
|
+
|
|
|
+ // Affichage classique
|
|
|
+ position = b->GetPosition();
|
|
|
+
|
|
|
+ pxpos.x = position.x * MULTI ;
|
|
|
+ pxpos.y = position.y * MULTI ;
|
|
|
+
|
|
|
+ circleColor( screen, pxpos.x, pxpos.y, descr->rayon * MULTI, 0xddddddff );
|
|
|
+
|
|
|
+ // Affichage persistant
|
|
|
+ position -= timeStep * b->GetLinearVelocity();
|
|
|
+
|
|
|
+ pxpos2.x = position.x * MULTI ;
|
|
|
+ pxpos2.y = position.y * MULTI ;
|
|
|
+
|
|
|
+ lineColor( persistant, pxpos.x, pxpos.y, pxpos2.x, pxpos2.y, weap_color[descr->id] );
|
|
|
+ lineColor( screen, pxpos.x, pxpos.y, pxpos2.x, pxpos2.y, weap_color[descr->id] );
|
|
|
+ }
|
|
|
+ for ( unsigned int k(0); k < tourelle.size(); k++ )
|
|
|
+ {
|
|
|
+ circleColor( screen, tourelle[k].loc.x * MULTI, tourelle[k].loc.y * MULTI, 0.05f * MULTI, weap_color[tourelle[k].missile] );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Messages
|
|
|
+ msg = "Ratio CPU : " ;
|
|
|
+ msg += std::to_string( ((float)SDL_GetTicks() - tprev) * 100 / twait ) ;
|
|
|
+ msg += " pourcents." ;
|
|
|
+ stringRGBA( screen, 16, 16, msg.c_str(), 0, 255, 0, 255 );
|
|
|
+
|
|
|
+ msg = "Vie : " ;
|
|
|
+ msg += std::to_string( vie ) ;
|
|
|
+ msg += " | " ;
|
|
|
+ for ( unsigned int i(0); i < vie ; i ++ )
|
|
|
+ msg += "#" ;
|
|
|
+ for ( unsigned int i(vie); i < 30 ; i ++ )
|
|
|
+ msg += "-" ;
|
|
|
+ stringRGBA( screen, 16, 25, msg.c_str(), 0, 255, 0, 255 );
|
|
|
+
|
|
|
+ msg = "Delai tourelle : " ;
|
|
|
+ msg += std::to_string( weap_wait ) ;
|
|
|
+ msg += " ms." ;
|
|
|
+ stringRGBA( screen, 16, 34, msg.c_str(), 0, 255, 0, 255 );
|
|
|
+
|
|
|
+ SDL_Flip(screen);
|
|
|
+
|
|
|
+ // [4.4] Temps
|
|
|
+ while( SDL_GetTicks() - tprev < twait )
|
|
|
+ {
|
|
|
+ if ( SDL_GetTicks() - tprev < twait/2 )
|
|
|
+ SDL_Delay( twait/3 );
|
|
|
+ }
|
|
|
+ tprev = SDL_GetTicks();
|
|
|
+
|
|
|
+ } //fin bcl principale
|
|
|
+
|
|
|
+ ///[5] Destruction des composants
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|