Voici un exemple plus complet. Ce programme simule des balles qui rebondissent dans un cube, et compte le nombre de rebonds. L’utilisateur peut changer la taille des balles à l’aide des touches “FLECHE HAUT” et “FLECHE BAS”. Le programme s’arrête si l’on appuie sur la touche “ESCAPE”.
#####################################################
#
# REBONDS DE BABALLES DANS LA BOIBOITE
#
# christophe.rigotti (at) insa-lyon.fr
#
#####################################################
# LES IMPORTS
import random
from visual import *
#####################################################
# DEFINITIONS DES FONCTIONS (PAS DE VARIABLES GLOBALES)
#####################################################
# MODELE PHYSIQUE
def randomPosition(balle,maxiAbsolu):
balle.x=random.uniform(-maxiAbsolu,maxiAbsolu)
balle.y=random.uniform(-maxiAbsolu,maxiAbsolu)
balle.z=random.uniform(-maxiAbsolu,maxiAbsolu)
def randomVitesse(balle,moduleVitesse):
# tirage en coordonnees spheriques
theta = random.uniform(0,2*pi)
phi = random.uniform(0,pi)
balle.v = vector(0,0,0) # creation du vecteur
balle.v.x = moduleVitesse*sin(phi)*cos(theta)
balle.v.y = moduleVitesse*sin(phi)*sin(theta)
balle.v.z = moduleVitesse*cos(phi)
def creerBalle(composanteAbsolueMaxi,moduleVitesse, rayon):
nouvelleBalle=sphere(radius=rayon,color=color.red)
randomPosition(nouvelleBalle,composanteAbsolueMaxi)
randomVitesse(nouvelleBalle,moduleVitesse)
return nouvelleBalle
def majPosition(balle,dt):
balle.pos=balle.pos+(balle.v)*dt
def majVitesse(balle,composanteAbsolueMaxi,nbChocs):
if not(-composanteAbsolueMaxi<balle.x<composanteAbsolueMaxi):
balle.v.x=-balle.v.x
nbChocs=nbChocs+1
if not(-composanteAbsolueMaxi<balle.y<composanteAbsolueMaxi):
balle.v.y=-balle.v.y
nbChocs=nbChocs+1
if not(-composanteAbsolueMaxi<balle.z<composanteAbsolueMaxi):
balle.v.z=-balle.v.z
nbChocs=nbChocs+1
return nbChocs
#####################################################
# GESTION AFFICHAGE
def majEcranNbChocsReels(leLabel,valeur):
leLabel.text='rebonds: ' + str(valeur)
def creerMurs(tailleAretesCube,epaisseurParois):
# une face laterale transparente
m1 = box(pos=(tailleAretesCube/2,0,0), length=epaisseurParois, height=tailleAretesCube, width=tailleAretesCube, color=color.blue,opacity=0.2)
m2 = box(pos=(-tailleAretesCube/2,0,0), length=epaisseurParois, height=tailleAretesCube, width=tailleAretesCube, color=color.blue)
m3 = box(pos=(0,tailleAretesCube/2,0), length=tailleAretesCube, height=epaisseurParois, width=tailleAretesCube, color=color.green)
m4 = box(pos=(0,-tailleAretesCube/2,0), length=tailleAretesCube, height=epaisseurParois, width=tailleAretesCube, color=color.green)
m5 = box(pos=(0,0,-tailleAretesCube/2), length=tailleAretesCube, height=tailleAretesCube, width=epaisseurParois, color=color.white)
# avec ce parametrage la face avant est invisible
m6 = box(pos=(0,0,tailleAretesCube/2), length=tailleAretesCube, height=tailleAretesCube, width=epaisseurParois, color=color.white, opacity=0.2, visible=False)
return [m1,m2,m3,m4,m5,m6]
def detruireMurs(listeMurs):
for mur in listeMurs:
mur.visible = False
#####################################################
#####################################################
#DEBUT DU PROGRAMME PRINCIPAL
#####################################################
def main():
#####################################################
# INITIALISATION DES PARAMETRES
tailleAretesCube = 20.0
epaisseurParois = 0.2
delta_t = 0.1
moduleVitesse = 1.5
rayonBalle = 0.2
nbBalles=100
composantePositionAbsolueMaxi = tailleAretesCube/2-epaisseurParois-rayonBalle
#####################################################
# DESSIN ET CADRAGE DES PAROIS
scene.width = 600; scene.height = 600 # 'scene' est la fenetre par defaut de vpython
lesMurs = creerMurs(tailleAretesCube,epaisseurParois)
#####################################################
# DESSIN DU LABEL TEXTUEL
labelNbChocsReels = label(pos=(-15,tailleAretesCube/2+5,-tailleAretesCube/2))
#####################################################
# CREATION DES BALLES
listeBalles=[]
for i in range(nbBalles):
uneBalle=creerBalle(composantePositionAbsolueMaxi, moduleVitesse, rayonBalle)
listeBalles.append(uneBalle)
#####################################################
# BOUCLE PRINCIPALE DE SIMULATION
compteurChocsParois = 0
while True:
# deplacement de chaque balle
for i in range(nbBalles):
uneBalle=listeBalles[i]
nouveauCompteurChocsParois=majVitesse(uneBalle,
composantePositionAbsolueMaxi,compteurChocsParois)
majPosition(uneBalle,delta_t)
# si il y a eu un rebond
if nouveauCompteurChocsParois != compteurChocsParois:
compteurChocsParois = nouveauCompteurChocsParois
majEcranNbChocsReels(labelNbChocsReels,compteurChocsParois)
rate(100)
if scene.kb.keys: # une touche a-t-elle ete appuyee ?
touche = scene.kb.getkey() # de quelle touche s'agit-il ?
if touche == 'up' or touche == 'down':
# la touche fleche vers le haut ou vers le bas
if touche == 'up': # le rayon des balles augmente
rayonBalle = rayonBalle+0.1
else: # le rayon des balles diminue
if rayonBalle > 0.15:
rayonBalle = rayonBalle-0.1
# mise a jour des radius et replacement des balles
composantePositionAbsolueMaxi =\
tailleAretesCube/2-epaisseurParois-rayonBalle
for i in range(nbBalles):
uneBalle=listeBalles[i]
uneBalle.radius = rayonBalle
randomPosition(uneBalle,composantePositionAbsolueMaxi)
# fin traitement touches 'up' ou 'down'
# fin traitement touches clavier
#####################################################
#LANCEMENT
#####################################################
main()