oujood.com

Pymunk - Bibliothèque Python pour la simulation de la physique 2D: Les formes

Dans ce tutoriel, nous explorerons comment développer des applications en adoptant une approche orientée objet avec le framework de physique 2D Pymunk.

Les Fondements des Formes en Pymunk : Comprendre les Principes de la Simulation Physique

La simulation physique est un domaine fascinant et complexe qui permet de modéliser le comportement des objets dans le monde réel. Pymunk est une bibliothèque Python qui facilite la création de simulations physiques en 2D. Dans cet article, nous allons explorer les notions de base des formes en Pymunk, qui sont essentielles pour comprendre comment créer des simulations physiques réalistes.

Corps Rigides

Un corps rigide en Pymunk est un objet qui représente un objet physique dans votre simulation. Il peut être statique ou dynamique. Les corps rigides statiques sont immobiles et ne sont pas affectés par les forces. Les corps rigides dynamiques sont soumis à des forces et peuvent se déplacer en réponse à ces forces.

Formes de Collision

Les formes de collision sont associées aux corps rigides et définissent leur forme géométrique pour la détection de collisions. Pymunk prend en charge divers types de formes, notamment les cercles, les polygones et les segments. Lorsqu'une collision se produit, Pymunk utilise ces formes pour calculer les détails de la collision, tels que le point d'impact et la normale de la collision.

Contraintes/Articulations

Les contraintes et les articulations sont des moyens de définir des relations entre les corps rigides. Les contraintes permettent de limiter les mouvements des corps, tandis que les articulations permettent de créer des connexions entre les corps. Par exemple, une articulation de type "charnière" permet à deux corps de pivoter autour d'un point fixe.

Espaces

Les espaces sont des conteneurs qui regroupent les corps rigides et les formes de collision dans une simulation. Ils sont essentiels pour gérer la détection de collisions et la résolution de collisions. Chaque simulation Pymunk doit avoir au moins un espace.

Modélisation des Objets Physiques (Forme de l'Objet et Centre de Gravité)

Pour créer une simulation réaliste, il est important de modéliser correctement les objets physiques. La forme de l'objet est définie par sa forme géométrique, tandis que le centre de gravité représente le point autour duquel l'objet pivote en réponse aux forces appliquées.

Masse, Poids et Unités

La masse d'un corps rigide en Pymunk définit sa résistance aux forces. Le poids d'un objet est le produit de sa masse par la gravité. Pymunk utilise généralement des unités arbitraires, ce qui signifie que vous devez équilibrer les valeurs de masse et de gravité pour obtenir un comportement réaliste dans votre simulation.

Tunneling d'Objets

Le tunneling d'objets se produit lorsqu'un objet traverse un autre en raison de la grande vitesse ou d'intervalles de simulation trop longs. Pymunk offre des mécanismes pour détecter et corriger le tunneling, tels que les formes de collision convexes, les joints articulés et la détection de collisions en continu.

Simulation Instable

Une simulation peut devenir instable si les paramètres tels que la masse, la gravité ou les contraintes ne sont pas correctement réglés. Une simulation instable peut provoquer des comportements inattendus ou des explosions physiques. Il est important de surveiller et d'ajuster ces paramètres pour maintenir la stabilité de la simulation.

Performance (Conseils pour Améliorer les Performances)

Les simulations physiques peuvent être gourmandes en ressources. Pour améliorer les performances de votre simulation en Pymunk, vous pouvez utiliser des techniques telles que l'optimisation des formes de collision, la désactivation des objets en dehors de l'écran, ou l'ajustement des intervalles de simulation.

Copier et Charger/Enregistrer des Objets Pymunk

Pour sauvegarder ou restaurer des simulations Pymunk, vous pouvez utiliser des méthodes de copie et de sauvegarde. Cela permet de conserver l'état de la simulation pour une utilisation future ou de partager des simulations avec d'autres utilisateurs.

Les formes en Pymunk

Pymunk est une bibliothèque Python pour la simulation de physique 2D. Elle fournit une variété de classes de formes qui peuvent être utilisées pour créer des objets physiques. Dans ce tutoriel, nous allons couvrir les trois classes de formes de base : cercle, segment et polygone.

La classe Boxe

Pour afficher notre simulation nous aurons besoin d'une boite 'BOXE'

.

De nombreuses simulations nécessitent une boîte statique pour contenir les éléments dynamiques. Définissons donc la classe Box qui prend 2 points d'extrémité diagonaux pour définir une boîte :

Le cercle 'circle' en pymunk

Un cercle est une forme fermée avec un centre et un rayon. En Pymunk, la classe de forme cercle est appelée Circle.

Définition

Un cercle est défini par son centre, son rayon et sa masse.

Syntaxe

 
from pymunk import Circle

# Créer un cercle avec un centre (0, 0) et un rayon de 10
circle = Circle(space, 0, 0, 10)

Exemple pratique

code python :       Copier le code

import matplotlib.pyplot as plt
import numpy as np

# Définition de la fonction pour tracer un segment du cercle
def plot_circle(x0, y0, r, theta):
# Calcul des coordonnées du point sur le cercle à partir de l'angle theta
x1 = x0 + r * np.cos(theta)
y1 = y0 + r * np.sin(theta)

# Tracer le segment de ligne du centre (x0, y0) au point calculé (x1, y1)
plt.plot([x0, x1], [y0, y1], color="#B22222", linewidth=2.5)

# Création d'une série de valeurs d'angle allant de 0 à 2π (un cercle complet)
theta_values = np.linspace(0, 2 * np.pi, 360)

# Boucle pour tracer le cercle en utilisant la fonction plot_circle
for theta in theta_values:
plot_circle(10, 10, 5, theta)  # Appel de la fonction avec les coordonnées du cercle et l'angle theta

# Définition des limites des axes X et Y pour définir la plage de valeurs affichées
plt.xlim(0, 20)
plt.ylim(0, 20)

# Assurer que l'aspect du graphique est égal pour que le cercle apparaisse correctement
plt.axis('equal')

# Affichage du graphique
plt.show()

Ce code Python utilise la bibliothèque matplotlib pour tracer un cercle statique avec un rayon donné à partir de coordonnées (x0, y0) spécifiées. Il crée ensuite un cercle complet en faisant varier l'angle theta dans une boucle for et en appelant la fonction plot_circle à chaque itération. Enfin, il définit les limites des axes, s'assure que l'aspect du graphique est égal (pour que le cercle apparaisse comme un cercle), et affiche le graphique.

En réalité dans une simulation physique, nous avons en générale besoin de créer des corps en mouvement donc dynamique. C'est pour quoi nous optons ici pour une approche orienté objet

Approche orienté objet : utilisation des classes

Pour simplifier et eviter d'écrire une grande partie de code à chaque fois que nous voulons créer un cercle,nous allons créer des classes que nous stockons dans un fichier auquel on va faire appel lors de la création de cercles.
Donc nous allons créer une fonction info(), une classe boxe et une classe App comme suit:

Commencez par créer un fichier python et nommez le 'classeForme.py', ce fichier doit être mis dans le même répertoire que notre application.

Mais avant, nous devons importer les modules nécessaires dans le fichier "classeForme.py"

Pour celà ajouter les ignes de code suivante au fichier 'classeForme.py' comme suit:

Code python:       Copier le code

import pymunk
import pymunk.pygame_util
import pygame

space = pymunk.Space()
space.gravity = 0, -900

Explication du code Python

  • 1.import pymunk: Cette ligne importe la bibliothèque Pymunk, qui est une bibliothèque Python utilisée pour la simulation physique en 2D. Pymunk est couramment utilisée pour créer des simulations de physique dans les jeux et les applications interactives.
  • 2.import pymunk.pygame_util: Cette ligne importe un module spécifique de Pymunk qui facilite l'intégration de Pymunk avec Pygame, une bibliothèque populaire pour le développement de jeux en Python.
  • 3.import pygame: Cette ligne importe la bibliothèque Pygame, qui est utilisée pour créer des applications multimédias, y compris des jeux. Pygame est souvent utilisée en conjonction avec Pymunk pour créer des jeux 2D.
  • 4.import classeForme: Cette ligne importe un module ou une classe appelée classeForme à partir d'un fichier Python externe. La nature précise de ce module dépend de son contenu et n'est pas explicite dans le code donné.
  • 5.space = pymunk.Space(): Cette ligne crée une instance de la classe Space de Pymunk, qui représente l'espace physique où les objets et les simulations de physique vont se dérouler. Un objet Space est essentiel pour gérer la simulation physique dans Pymunk.
  • 6.space.gravity = 0, -900: Cette ligne définit la gravité dans l'espace Pymunk. La gravité est un vecteur qui détermine la force avec laquelle les objets sont attirés vers le bas. Dans ce cas, la gravité est définie avec une composante horizontale de 0 (pas de gravité horizontale) et une composante verticale de -900, ce qui signifie que les objets seront attirés vers le bas avec une force de 900 unités par seconde au carré. Cela simule une gravité vers le bas dans un environnement 2D.

Il est important de noter que le code donné ne contient que l'initialisation de Pymunk et la définition de la gravité.

Donc on doit ajouter les définitions des différentes classes.

Définition de la classe Box :

Ajouter au fichier 'classeForme.py' le code suivant qui définit la classe Box :

code python :       Copier le code

class Box:
def __init__(self, p0=(10, 10), p1=(690, 230), d=2):
	x0, y0 = p0
	x1, y1 = p1
	pts = [(x0, y0), (x1, y0), (x1, y1), (x0, y1)]
	for i in range(4):
		segment = pymunk.Segment(space.static_body, pts[i], pts[(i+1)%4], d)
		segment.elasticity = 1
		segment.friction = 1
		space.add(segment)

Cette classe permet de créer une boîte statique dans l'espace de simulation. Elle prend trois arguments optionnels :

  • p0 pour les coordonnées du coin supérieur gauche de la boîte
  • p1 pour les coordonnées du coin inférieur droit de la boîte
  • d pour la largeur de la bordure de la boîte (par défaut, 2)

Les coordonnées p0 et p1 sont utilisées pour définir les coins de la boîte pts, qui sont stockés dans la liste pts.

Une boucle for parcourt les quatre coins de la boîte, et pour chaque paire de coins consécutifs, un segment (pymunk.Segment) est créé pour représenter un côté de la boîte. Les segments créés sont ajoutés à l'espace de simulation space.

Les propriétés elasticity et friction des segments sont définies à 1, ce qui signifie qu'ils sont élastiques et ont une friction maximale.

Définition de la classe App :

Puis ajouter aussi le code qui définit la classe App :

code python :       Copier le code

class App:
def __init__(self):
	pygame.init()
	self.screen = pygame.display.set_mode((700, 240))
	self.draw_options = pymunk.pygame_util.DrawOptions(self.screen)
	self.running = True

	def run(self):
		while self.running:
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					self.running = False
					pygame.image.save(self.screen, 'shape.png')

			self.screen.fill((220, 220, 220))
			space.debug_draw(self.draw_options)
			pygame.display.update()
			space.step(0.01)

		pygame.quit()

if __name__ == '__main__':
    Box()

Ce code définit la classe App qui est conçue pour gérer l'affichage de la simulation, détecter les événements de l'utilisateur et exécuter la simulation en utilisant la boucle principale.

  • pygame.init(): Cette ligne initialise la bibliothèque pygame. C'est une étape essentielle pour pouvoir utiliser pygame.
  • self.screen = pygame.display.set_mode((700, 240)): Cette ligne crée une fenêtre graphique d'une taille de 700 pixels de largeur et 240 pixels de hauteur et la stocke dans l'attribut self.screen.
  • self.draw_options = pymunk.pygame_util.DrawOptions(self.screen): Cette ligne crée un objet DrawOptions à partir de pymunk.pygame_util qui sera utilisé pour dessiner les objets de la simulation sur l'écran.
  • self.running = True: Cela initialise une variable self.running à True, ce qui signifie que la boucle principale de l'application est en cours d'exécution.

La méthode run est responsable de l'exécution de la boucle principale de l'application :

  • while self.running:: C'est une boucle while qui s'exécute tant que la variable self.running est True.
  • La boucle parcourt les événements pygame et détecte la fermeture de la fenêtre pour terminer l'application.
  • Elle remplit l'écran avec une couleur gris clair à chaque itération pour effacer le contenu précédent, puis dessine les objets de la simulation et met à jour l'affichage.
  • Enfin, la boucle fait progresser la simulation physique d'un pas de temps de 0.01 seconde.
  • Après la boucle, pygame est quitté et la fenêtre se ferme proprement.

if __name__ == '__main__': : Cette ligne vérifie si le script Python est exécuté en tant que programme principal ou s'il est importé en tant que module dans un autre script. Le code indenté sous cette condition sera exécuté uniquement si le script est le programme principal.

Box() : Cette ligne crée une instance de la classe Box. Cela suppose que la classe Box a été définie dans le même fichier Python ou importée depuis un autre fichier.

Toutes ces classes seront stockées dans le fichier que nous nommons "classeForme.py".

La dernière partie est le code qui:
1. Crée un objet physique circulaire (un cercle) dans un environnement de simulation 2D en utilisant Pymunk.
2. Applique à cet objet (le cercle) une impulsion pour le faire bouger.
3. Configure des propriétés telles que la masse, l'élasticité et la friction du cercle.

Voici le code :

code python :       Copier le code


# Crée un corps (body) avec une masse de 1 et un moment d'inertie de 10.
body = pymunk.Body(mass=1, moment=10)

# Définit la position initiale du corps à (100, 200) dans l'espace 2D.
body.position = (100, 200)

# Applique une impulsion au corps au point local (200, 0).
body.apply_impulse_at_local_point((200, 0))

# Crée un cercle lié avec le corps précédemment créé comme corps parent avec un rayon de 20.
circle = pymunk.Circle(body, radius=20)

# Définit l'élasticité du cercle à 0.95.
circle.elasticity = 0.95

# Définit le coefficient de friction du cercle à 1.
circle.friction = 1

# Ajoute le corps et le cercle à l'espace physique (simulateur).
space.add(body, circle)

# Lance l'application Pymunk, ce qui démarre la simulation physique.
App().run()

Explication du Code Pymunk

1. `body = pymunk.Body(mass=1, moment=10)`: Cette ligne crée un objet `Body` (corps) dans Pymunk. Un `Body` représente un objet physique dans l'espace 2D. Il a une masse de 1 et un moment d'inertie de 10. Le moment d'inertie (moment of inertia) est une mesure de la façon dont la masse d'un objet est répartie autour de son axe de rotation. Il détermine la facilité ou la difficulté avec laquelle un objet peut être mis en rotation. Plus le moment d'inertie est élevé, plus l'objet résiste à la rotation..

2. `body.position = (100, 200)`: Cette ligne définit la position initiale du corps à (100, 200) dans le système de coordonnées 2D. Cela signifie que le corps sera initialement situé à 100 pixels à droite et 200 pixels vers le bas à partir de l'origine du système de coordonnées.

3. apply_impulse_at_local_point: C'est une méthode qui permet d'appliquer une impulsion à l'objet "body". Une impulsion est une quantité de mouvement, qui peut être considérée comme une force appliquée pendant une très courte période de temps. Appliquer une impulsion à un objet provoque un changement dans sa vitesse ou son mouvement.

(200, 0): C'est le point local auquel l'impulsion est appliquée par rapport au centre du corps. Dans ce cas, l'impulsion est appliquée à un point situé à 200 unités à droite (horizontalement) et 0 unités vers le haut ou le bas (verticalement) par rapport au centre du corps. Cela signifie qu'une impulsion est appliquée pour déplacer le corps vers la droite avec une force de 200 unités.

4. `circle = pymunk.Circle(body, radius=20)`: Cette ligne crée un objet de forme circulaire (un cercle) attaché au corps que nous avons créé précédemment. Le cercle a un rayon de 20 pixels et est lié au corps 'body' que nous avons défini, de sorte que le corps représente maintenant un cercle physique.

5. `circle.elasticity = 0.95`: Cette ligne définit la propriété d'élasticité du cercle à 0,95. L'élasticité détermine à quel point les collisions de l'objet seront élastiques. Une élasticité de 1 signifie que les collisions sont parfaitement élastiques (rebondissent complètement), tandis qu'une élasticité de 0 signifie que les collisions sont parfaitement inélastiques (pas de rebond).

6. `circle.friction = 1`: Cette ligne définit la friction du cercle à 1. La friction contrôle la résistance au glissement lorsqu'un objet se déplace sur une surface. Une valeur plus élevée signifie une friction plus importante.

7. `space.add(body, circle)`: Cette ligne ajoute à l'espace de simulation les objets que nous avons créés, à savoir le corps et le cercle. L'espace de simulation est l'environnement où les lois de la physique sont appliquées aux objets.

8. `info(body)`: Cette ligne est une fonction personnalisée pour afficher des informations sur le corps, nous l'avons définie prècidement lors de la création des classes.

9. De même pour la fonction `App().run()`: Elle est liée à l'exécution de application définie prècedement lors de la création des classes.

Et voila tout ce qui nous reste à faire est de rassembler touts ces bouts de code ensemble pour obtenir notre code final au complet. ce qui donne:

Enregistrer ce code dans un fichier dans le même répertoie que notre fichier 'classeForme.py'

code python :       Copier le code

from classeForme import pymunk, space, App, Box

Box()

# Crée un corps (body) avec une masse de 1 et un moment d'inertie de 10.
body = pymunk.Body(mass=1, moment=10)

# Définit la position initiale du corps à (100, 200) dans l'espace 2D.
body.position = (100, 200)

# Applique une impulsion au corps au point local (200, 0).
body.apply_impulse_at_local_point((200, 0))

# Crée un cercle lié avec le corps précédemment créé comme corps parent avec un rayon de 20.
circle = pymunk.Circle(body, radius=20)

# Définit l'élasticité du cercle à 0.95.
circle.elasticity = 0.95

# Définit le coefficient de friction du cercle à 1.
circle.friction = 1

# Ajoute le corps et le cercle à l'espace physique (simulateur).
space.add(body, circle)

# Lance l'application Pymunk, ce qui démarre la simulation physique.
App().run()

exemple pratique: Une forme composée simple

Ici, nous allons apprendre à créer une forme composée simple en Pymunk de Python. Une forme composée est une forme qui est composée de deux ou plusieurs formes simples. Dans ce cas, nous allons combiner deux cercles pour.

Exemple :       Copier le code

 
from classeForme import pymunk, space, App, Box

Box()
body = pymunk.Body(mass=1, moment=20)
body.position = (100, 200)
body.apply_impulse_at_local_point((100, 0))

cercle1 = pymunk.Circle(body, radius=20, offset=(-20, 0))
cercle1.elasticity = 0.999
cercle1.color = (0, 0,250, 0)

cercle2 = pymunk.Circle(body, radius=30, offset=(30, 0))
cercle2.elasticity = 0.999
cercle2.color = (255, 0, 0, 0)

space.add(body, cercle1, cercle2)
App().run()

Explication du Code

  1. from classeForme import pymunk, space, App, Box:: Cette ligne importe les modules et classes nécessaires depuis le fichier classeForme.py.
  2. Box(): Cela crée une instance de la classe Box définie dans classeForme.py.
  3. body = pymunk.Body(mass=1, moment=20): Ici, vous créez une instance de pymunk.Body. Un corps est un objet physique auquel vous pouvez attacher des formes géométriques. Vous définissez la masse du corps sur 1 et son moment sur 20.
  4. body.position = (100, 200): Vous définissez la position initiale du corps à (100, 200).
  5. body.apply_impulse_at_local_point((100, 0)): Vous appliquez une impulsion au corps au point local (100, 0). Cela signifie que vous appliquez une force pour pousser le corps vers la droite.
  6. cercle1 = pymunk.Circle(body, radius=20, offset=(-20, 0)): Vous créez une instance de pymunk.Circle et l'attachez au corps body. Cette forme est un cercle avec un rayon de 20 et un décalage (offset) de (-20, 0) par rapport au centre du corps.
  7. cercle1.elasticity = 0.999: Vous définissez la valeur de l'élasticité de la première forme de cercle.
  8. cercle1.color = (0, 0, 250, 0): Vous définissez la couleur de la forme de cercle en utilisant un tuple RGB.
  9. cercle2 = pymunk.Circle(body, radius=30, offset=(30, 0)): Vous créez une deuxième instance de pymunk.Circle attachée au même corps. Cette fois, le cercle a un rayon de 30 et un décalage de (30, 0) par rapport au centre du corps.
  10. cercle2.elasticity = 0.999: Vous définissez également l'élasticité de la deuxième forme de cercle.
  11. cercle2.color = (255, 0, 0, 0): Vous définissez la couleur de la deuxième forme de cercle.
  12. space.add(body, cercle1, cercle2): Vous ajoutez le corps body ainsi que les deux formes de cercle (cercle1 et cercle2) à l'espace PyMunk, ce qui les rend physiquement interactifs.
  13. App().run(): Vous créez une instance de la classe App et exécutez la méthode run() pour lancer l'application Pygame.

Dans le chapitre suivant nous allons voir les autres classes des formes de base en Pymunk, à savoir les segments et les polygones




Voir aussi nos tutoriel :

fonction microtime

Renvoie les microsecondes pour le temps courant

php fonction date

La fonction date

Les tableaux dans bootstrap

Comment créer des tableaux élégants avec Bootstrap.