Laboratoire 3
=============

Les nouvelles notions abordées dans ce laboratoire sont les suivantes:

* Mathématique:

  - Les coniques.
  - La résolution d'équations du second degré.

* Physique:

  - Le mouvement uniformément accéléré dans un espace à deux dimensions.

Programme 6: Tir balistique
---------------------------

Ce projet est une variante du jeu de tir implémenté dans le programme 2.
Le canon est maintenant orientable, et tire des projectiles qui sont
soumis à l'accélération de la gravité. La vitesse de ces projectiles est
également réglable. La fenêtre du jeu ressemble à celle-ci:

.. figure:: figures/prog-6-screenshot.png
   :scale: 50%
   :align: center
   :alt: Fenêtre du programme 6.

   Fenêtre du programme 6.

L'angle du canon peut être réglé en appuyant sur les flèches gauche et
droite. La vitesse linéaire des projectiles à la sortie du canon est
affichée sur l'indicateur qui figure dans le coin inférieur gauche de
la fenêtre. Cette vitesse peut être modifiée en pressant les flèches
haute et basse.

Mouvement des projectiles
~~~~~~~~~~~~~~~~~~~~~~~~~

La première étape consiste à écrire la fonction responsable de calculer
le mouvement des projectiles. La démarche est très proche de celle des
programmes 2 et 3. Dans le cas présent, le projectile se déplace en deux
dimensions en étant uniquement soumis à l'accélération de la gravité.
La fonction ``mua_2d()`` que vous devez développer est chargée de calculer
la position d'un projectile à un instant donné. Cette fonction doit:

* accepter 5 arguments:

  - un tuple d'entiers ``depart`` contenant les coordonnées :math:`(x_0, y_0)`
    du canon (qui est le point de départ des projectiles). Ces coordonnées
    sont exprimées en pixels. Pour simplifier, on considère que le canon
    se résume à un seul point.

  - un entier ``temps_depart`` donnant l'instant où le projectile a été
    émis par le canon, exprimé en millisecondes.

  - un tuple de réels ``vitesse_initiale`` donnant le vecteur vitesse
    :math:`(v_{0x}, v_{0y})` du projectile à la sortie du canon. Les
    composantes de ce vecteur sont exprimées en pixels par milliseconde.

  - un réel ``acceleration_verticale`` correspondant à l'accélération
    :math:`g` de la gravité, exprimée en pixels par milliseconde au carré,
    et (bien sûr) dirigée vers le bas. (Comme l'axe :math:`Y` du repère
    de la fenêtre est orienté de haut en bas, on a donc :math:`g > 0`.)

  - un entier ``temps_maintenant`` donnant l'instant présent :math:`t`,
    exprimé en millisecondes. Ce temps peut être supposé supérieur ou égal
    à  ``temps_depart``.

* retourner un tuple fournissant les coordonnées :math:`(x_t, y_t)` du
  projectile à l'instant :math:`t`.

Procédure à suivre:

1. Ecrire des formules exprimant :math:`x_t` et :math:`y_t` en fonction de
   :math:`x_0`, :math:`y_0`, :math:`v_{0x}`, :math:`v_{0y}`, :math:`g`
   et :math:`t`.

2. Télécharger le programme `prog-6.py
   <https://people.montefiore.uliege.be/boigelot/cours/labmp/prog/prog-6.py>`_.

3. Dans ce programme, remplacer la fonction ``mua_2d()`` par votre propre
   implémentation des formules obtenues au point 1.

4. Vérifier que le programme fonctionne correctement. Un clic gauche de
   la souris permet de tirer un projectile. Un clic droit affiche une cible
   (que vous pouvez effacer en pressant la touche 'C').

5. Reporter les formules obtenues au point 1 sur votre feuille de
   laboratoire (**Code P6-1**).

Tir automatique
~~~~~~~~~~~~~~~

L'objectif est maintenant de calculer automatiquement la vitesse que doit
avoir le projectile à la sortie du canon, afin de toucher la cible.
Ce calcul sera implémenté dans une fonction ``calculer_vitesse()``
possédant les caractéristiques suivantes. Cette fonction doit:

* accepter quatre arguments:

  - un tuple d'entiers ``depart`` contenant les coordonnées
    :math:`(x_0, y_0)` du canon, exprimées en pixels.

  - un réel ``angle`` donnant l'angle :math:`\theta` que fait le canon
    avec l'horizontale.  Cet angle est exprimé en radians. Il suit la
    convention trigonométrique dans le repère de la fenêtre. (Rappel:
    l'axe :math:`Y` est orienté de haut en bas.)  Selon cette convention, un
    angle positif correspond à un tir vers le bas (en supposant
    :math:`|\theta| < \pi`), et un angle négatif à un tir vers le haut.

  - un tuple d'entiers ``cible`` contenant les coordonnées
    :math:`(x_c, y_c)` de la cible, exprimées en pixels.

  - un réel ``acceleration_verticale`` correspondant à l'accélération
    :math:`g` de la gravité, exprimée en pixels par milliseconde au carré.

* retourner une paire de valeurs:

  - un booléen ``tir_est_possible`` indiquant s'il est possible
    ou non de tirer un projectile qui touchera la cible.
  - dans le cas où ``tir_est_possible`` est vrai, la vitesse linéaire
    :math:`v_0` que doit avoir le projectile en sortie du canon pour
    toucher la cible. Cette vitesse doit naturellement être strictement
    positive.
    Elle doit être exprimée en pixels par milliseconde.

Procédure à suivre:

1. Ecrire la condition déterminant la valeur de ``tir_est_possible`` en
   fonction des paramètres du problème.

2. Ecrire une formule exprimant, lorsque ``tir_est_possible`` est
   vrai, la valeur de :math:`v_0` en fonction des paramètres
   du problème.

3. Dans votre version courante du programme ``prog-6.py``, remplacer
   la fonction ``calculer_vitesse()`` par votre propre implémentation des
   formules obtenues aux points 1 et 2.

4. Vérifier le bon fonctionnement du programme. Le calcul automatique
   de la vitesse peut être activé en pressant la touche 'A', après avoir
   désigné une cible.

   *Note:* Si le calcul réussit, l'indicateur de vitesse devient
   rouge.  A partir de cette situation, tous les projectiles tirés
   devraient atteindre leur cible (si les calculs effectués sont
   corrects!). Si l'on modifie une donnée du problème (angle du canon,
   vitesse, position de la cible), l'indicateur reprend sa couleur
   d'origine pour signifier que le calcul doit à nouveau être
   effectué. Lorsque le calcul échoue, l'indicateur garde sa couleur
   de base.

5. Reporter les formules obtenues aux points 1 et 2 sur votre feuille de
   laboratoire (**Code P6-2**).

Calcul du point d'impact
~~~~~~~~~~~~~~~~~~~~~~~~

La dernière étape consiste à déterminer, dans le cas où la vitesse du
projectile a été calculée automatiquement, à quel endroit se situera
le point d'impact de celui-ci avec le sol. La fonction
``calculer_impact()`` chargée de cette opération doit:

* accepter cinq arguments:

  - un tuple d'entiers ``depart`` contenant les coordonnées
    :math:`(x_0, y_0)` du canon, exprimées en pixels.

  - un réel ``angle`` donnant l'angle :math:`\theta` du canon
    avec l'horizontale, exprimé en radians.

  - un entier ``hauteur_sol`` contenant la coordonnée verticale
    :math:`y_s` du sol, exprimée en pixels.

  - un réel ``vitesse`` donnant la vitesse linéaire :math:`v_0`
    du projectile à la sortie du canon, exprimée en pixels par
    milliseconde.

  - un réel ``acceleration_verticale`` correspondant à l'accélération
    :math:`g` de la gravité, exprimée en pixels par milliseconde au carré.

* retourner la position horizontale :math:`x_s` de l'impact du projectile
  avec le sol, exprimé en pixels.

Procédure à suivre:

1. Ecrire une équation cartésienne de la courbe suivie par le projectile,
   dont les inconnues sont les coordonnées :math:`(x, y)` de celui-ci.

2. Calculer l'intersection de cette équation avec le sol. Si votre
   raisonnement aboutit à plusieurs solutions, déterminer laquelle
   d'entre elles correspond au point d'impact recherché. Le résultat
   doit prendre la forme d'une formule exprimant :math:`x_s` en
   fonction des paramètres du problème.

3. Dans votre version courante du programme ``prog-6.py``, remplacer
   la fonction ``calculer_impact()`` par votre propre implémentation de
   la formule obtenue au point 2.

4. Vérifier le bon fonctionnement du programme. Lors d'un tir automatique,
   le point d'impact prévu doit être indiqué par un fanion (s'il appartient
   à l'intervalle visible dans la fenêtre).

5. Reporter l'équation et la formule obtenues au points 1 et 2 sur
   votre feuille de laboratoire (**Codes P6-3 et P6-4**).