Mouvement
Supposons que nous souhaitions réaliser une application dans laquelle un objet se déplace sur l’écran. Pour que le mouvement de cet objet soit réaliste, il faut connaitre certaines lois de comportement de la physique…
Etude théorique des mouvements
Soit un système matériel (objet) de masse \(m\) et suffisamment « petit » par rapport à l’amplitude de ses mouvements pour qu’il puisse être considéré comme « ponctuel ».
Exemples de systèmes matériels ponctuels : balle de tennis sur un terrain, fusée dans l’espace, …
Position
Pour repérer cet objet dans l’espace (et sur l’écran) on utilise ses coordonnées, notées \((x,y)\). L’ensemble des positions que prend l’objet au cours du temps est une ligne appelée trajectoire.
Remarque : sur un écran, l’origine du repère se situe en haut à gauche, l’axe des \(\vec y\) est par conséquent orienté vers le bas.
Dans un repère \(O(\vec x,\vec y)\), on peut alors définir un vecteur position \(\overrightarrow{OP}\) :
Vitesse
La variation de la position de cet objet au cours du temps \(t\) s’appelle la vitesse, et est représentée par un vecteur vitesse noté \(\vec V\) et défini par :
\(\bbox[10px,border:2px solid black]{\Large{\vec V=\frac{\text{d}\overrightarrow{OP}}{\text{d}t}}}\)
Remarque : « \(\text{d}…\) » signifie « quantité infinitésimale de \(…\) »
En écriture scalaire (nombres réels), cela donne :
\(\bbox[10px,border:1px solid black]{\large{\vec V=
\left\{
\begin{array}{c}
Vx=\frac{\text{d}x}{\text{d}t} \\
Vy=\frac{\text{d}y}{\text{d}t}
\end{array}
\right.
}}\)
Forces
Pour que cet objet ait des mouvements variés, il faut qu’il soit soumis à des actions mécaniques (des forces).
Exemple de forces : pesanteur, contact, forces magnétiques, …
Une force est représentée par un vecteur force, noté \(\vec F\), qui s’écrit :
\(\bbox[10px,border:1px solid black]{\large{\vec F=
\left\{
\begin{array}{c}
Fx \\
Fy
\end{array}
\right.
}}\)
Principe Fondamental de la Dynamique
La loi qui définit le comportement (donc les mouvements) de cet objet dans l’espace est donnée par le Principe Fondamental de la Dynamique (ou 2nde loi de Newton).
\(\bbox[10px,border:2px solid black]{\Large{\displaystyle \sum_{i} \overrightarrow{F_i}=m\frac{\text{d}\overrightarrow{V}}{\text{d}t}}}\)
Remarque : \(\frac{\text{d}\overrightarrow{V}}{\text{d}t}\) est appelé vecteur accélération.
En écriture scalaire :
\(\bbox[10px,border:1px solid black]{\large{
\left\{
\begin{array}{c}
\displaystyle \sum_{i} Fx_i=m\frac{\text{d}Vx}{\text{d}t}\\
\displaystyle \sum_{i} Fy_i=m\frac{\text{d}Vy}{\text{d}t}
\end{array}
\right.
}}\)
Programmation
Si toutes les forces qui s’appliquent à l’objet sont connues d’avance, si la masse de l’objet ne change jamais, alors on peut calculer les lois du mouvement qui donnent la position de l’objet au cours du temps.
\(\overrightarrow{OP(t)}\)
\(\overrightarrow{V(t)}\)
Mais dans un jeu vidéo, les actions de l’utilisateur ne sont pas connues d’avance : on ne peut pas connaitre à l’avance la trajectoire de l’objet !
Il faut donc recalculer la position à chaque instant !!!
En physique, faire un calcul à « chaque instant », c’est impossible : il faudra faire des calculs à intervalle de temps donné, qui devra être suffisamment « petit » pour que le mouvement soit « fluide ».
⇒ A défaut de pouvoir calculer à chaque \(\text{d}t\) (intervalle de temps infinitésimal, on calcule à des intervalles de temps « petits » \(\Delta t\). (en pratique, entre 1/20ème et 1/60ème de seconde).
Ainsi dans le programme, on réalise une boucle dans laquelle on calcule, connaissant la position et la vitesse de la balle à un instant \(t_{n}\), les nouvelles position et vitesse à l’instant \(t_{n+1}\) :
Calcul de la vitesse
Le PFD peut s’écrire sous la forme approchée :
\(\bbox[10px,border:1px solid black]{\large{\displaystyle \sum_{i} \overrightarrow{F_i}\approx m\frac{\Delta\overrightarrow{V}}{\Delta t}}}\)
On en déduit :
\(\left\{
\begin{array}{c}
\Delta Vx=\frac{\Delta t}{m}\displaystyle \sum_{i} Fx_i \\
\Delta Vy=\frac{\Delta t}{m}\displaystyle \sum_{i} Fy_i
\end{array}
\right.\)
\(\bbox[10px,border:2px solid red]{\Large{
\left\{
\begin{array}{c}
Vx_{n+1}=Vx_n+\frac{\Delta t}{m}\displaystyle \sum_{i} Fx_i \\
Vy_{n+1}=Vy_n+\frac{\Delta t}{m}\displaystyle \sum_{i} Fy_i
\end{array}
\right.
}}\)
Calcul de la position
La définition de la vitesse peut s’exprimer sous la forme approchée :
\(\bbox[10px,border:1px solid black]{\large{\vec V\approx \frac{\Delta\overrightarrow{OP}}{\Delta t}}}\)
On en déduit :
\(\left\{
\begin{array}{c}
\Delta x=Vx_{n+1}\cdot\Delta t \\
\Delta y=Vy_{n+1}\cdot\Delta t
\end{array}
\right.\)
\(\bbox[10px,border:2px solid red]{\Large{
\left\{
\begin{array}{c}
x_{n+1}=x_n+Vx_{n+1}\cdot\Delta t \\
y_{n+1}=y_n+Vy_{n+1}\cdot\Delta t
\end{array}
\right.
}}\)
Algorithme complet
# Constantes deltaT masse # Initialisation position = position_initiale vitesse = vitesse_initiale tant que le mouvement continue faire # calcul de la nouvelle vitesse vitesse = vitesse + somme(forces) * deltaT / masse # calcul de la nouvelle position position = position + vitesse * deltaT # recalcul des forces (si elles dépendent de la position et/ou de la vitesse pour chaque force parmi les forces faire calculer(force)
Remarque : pour information, cette méthode de calcul s’appelle méthode d’Euler implicite
Implémentation en Python
On se propose de réaliser un programme en Python, avec l’aide de la bibliothèque pygame, permettant de visualiser les mouvements d’une balle (de tennis).
Télécharger les images utiles au programme :
Programme principal
Voici une base de programme utilisant pygame :
import pygame from pygame.locals import * pygame.init() horloge = pygame.time.Clock() ################################################################################ # Chargement du fond fond = pygame.image.load("tennis_court.png") # Ouverture de la fenêtre Pygame et collage du fond fenetre_size = fond.get_rect().size fenetre = pygame.display.set_mode(fenetre_size) fenetre_rect = pygame.Rect((0, 0), fenetre_size) fond = fond.convert() fenetre.blit(fond, (0,0)) # Rafraîchissement de l'écran pygame.display.flip() # Constantes ################################################################################ fps = 30 # Taux de rafraichissement (fps = frame per second) ################################################################################ # Boucle infinie ... continuer = True while continuer: for event in pygame.event.get(): # Attente des événements if event.type == QUIT: continuer = False # Calcul la nouvelle vitesse ... # Calcul de la nouvelle position ... # Calcul des forces ... # Re-collage des éléments fenetre.blit(fond, (0,0)) # Rafraichissement pygame.display.flip() horloge.tick(fps) pygame.quit()
Structure des données
A ce programme, il faut rajouter la définition, l’initialisation de l’état (position et vitesse) et le premier affichage de la balle.
################################################################################ # La balle ball = {"file" : "balle.png", # Le fichier 'image' "p" : [200, 500], # Position "v" : [0, 0], # Vitesse "m" : 0.1, # Masse "r" : 0 # Rayon } # Chargement et initialisation de la balle def init_objet(obj): objet = pygame.image.load(obj["file"]) obj["r"] = objet.get_rect().size[0]/2 return objet # Objet pygame ball["pg"] = init_objet(ball).convert() # Collage de la balle fenetre.blit(ball["pg"], ball["p"])
A chaque itération de la boucle, il faudra recoller la balle par dessus le fond :
fenetre.blit(fond, (0,0)) fenetre.blit(ball["pg"], ball["p"])
Les forces
On se propose de définir chaque force par une liste de la forme :
[fonction_de_calcul, paramètres_de_calcul, couleur]
Chaque fonction de calcul de force est de la forme :
def calc_force(objet, position_systeme_exterieur, **paramètres): .... return Fx, Fy
- objet désigne la balle ball
- position_systeme_exterieur est un tuple désignant la position du système qui exerce l’effort sur la balle (concrètement, le pointeur de la souris, un autre objet, …)
- paramètres est un dictionnaire de paramètres permettant de réaliser le calcul (raideur d’un ressort, intensité du champ de pesanteur, …)
Gestion des collisions