// Basiques # include // SDL # include # undef main # include // bBox2D # include // 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 deadBodies; // Simulation settings float timeStep = 1.0f / frameRate; int32 velocityIterations = 8; int32 positionIterations = 3; // Variables b2Vec2 position, force; float angle; Entity* descr( nullptr ); // Define the edge body b2BodyDef bodyDef; bodyDef.position.Set(0.0f, 0.0f); bodyDef.userData.pointer = (uintptr_t) new Entity( {0.0f, LAND} ); b2Body* areaBody = world.CreateBody(&bodyDef); b2Vec2 vs[4]; float areah( (float)screen->h / MULTI ); float areaw( (float)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.pointer = (uintptr_t) 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 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: case SDLK_1: std::cout << "Tir basique." << std::endl; missile = INERT ; break; case SDLK_KP2: case SDLK_2: std::cout << "Tir d'anticipation rectiligne." << std::endl; missile = ANG ; break; case SDLK_KP3: case SDLK_3: std::cout << "Missile d'accélération linéaire." << std::endl; missile = ARROW ; break; case SDLK_KP4: case SDLK_4: 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( (float)mouse.x/MULTI, (float)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().pointer; 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; }