import poorpyxel as ppx
from random import randint
ppx.init(150, 150)
def update():
global x, y, vitesse
# Déplacement de la bulle vers le haut en tenant compte de sa vitesse;
# Quand la bulle arrive en haut de la fenêtre, on réinitialise ses caractéristiques.
y = y - vitesse
if y < 0:
y = ppx.height
def draw():
# 1. Effacement global de la fenêtre :
ppx.cls(0)
# 2. Dessin de la bulle dans la fenêtre :
ppx.circ(x, y, rayon, couleur)
# initialisation des caractéristiques de la bulle
x = randint(10, 140)
y = ppx.height
couleur = randint(1, 15)
rayon = randint(2 ,5)
vitesse = randint(2, 10)
ppx.run(update, draw)
Deux choses pour gérer le mouvement de la bulle :
update
), modifier l'ordonnée y de la bulle
pour faire "monter" cette dernière : il faut donc décrémenter la variable y ( ligne 11 ).y < 0
, c'est à dire si la bulle "sort" de l'écran par le haut, et, dans ce cas, réinitialiser les caractéristiques la bulle.Une remarque sur la condition à tester pour "savoir" si la bulle atteint le sommet : on ne peut pas utiliser une simple égalité, car, selon la valeur de la variable vitesse, la variable y n'obtiendra peut-être jamais la valeur 0; il faut donc tester une inégalité qui, elle, sera forcément vérifiée à un moment ou un autre, quelle que soit la valeur de vitesse.
Facile : on recopie les variables et les instructions pour gérer le mouvement de la bulle, et on les réutilise avec de nouveaux noms :
import poorpyxel as ppx
from random import randint
ppx.init(150, 150)
def update():
global x, y, vitesse, x2, y2, vitesse2
y = y - vitesse
if y < 0:
y = ppx.height
y2 = y2 - vitesse2
if y2 < 0:
y2 = ppx.height
def draw():
ppx.cls(0)
ppx.circ(x, y, rayon, couleur)
ppx.circ(x2, y2, rayon2, couleur2)
# 1ère bulle
x = randint(10, 140)
y = ppx.height
couleur = randint(1, 15)
rayon = randint(2 ,5)
vitesse = randint(2, 10)
# 2ème bulle
x2 = randint(10, 140)
y2 = ppx.height
couleur2 = randint(1, 15)
rayon2 = randint(2 ,5)
vitesse2 = randint(2, 10)
ppx.run(update, draw)
Argh....
Cette façon d'envisager le programme devient de plus en plus délicate à gérer :
D'où la nécessité de passer, dans cette situation, à une autre façon de concevoir le programme, un autre paradigme de programmation, la Programmation Orientée Objet ( POO ).
Bulle
class Bulle:
# constructeur
def __init__(self,x, y, couleur, taille, vitesse):
self.x = x
self.y = y
self.couleur = couleur
self.rayon = rayon
self.vitesse = vitesse
def afficher(self):
ppx.circ(self.x, self.y, self.taille, self.couleur)
def monter(self):
self.y = self.y - self.vitesse
Pour chaque méthode ou attribut d'un objet, il faut préfixer son nom par self.
import poorpyxel as ppx
from random import randint
...
class Bulle:
...
def update():
bulle.monter()
def draw():
ppx.cls(0) # effacement de l'écran
bulle.afficher() # affichage de la bulle
# instanciation d'un objet de type "Bulle"
x = randint(0, ppx.width)
y = ppx.height
couleur = randint(0, 15)
rayon = randint(2, 10)
vitesse = randint(2, 10)
bulle = Bulle(x, y, couleur, rayon, vitesse) # arguments dans le même ordre que les paramètres du constructeur
ppx.run(update, draw)
Bulle
est instancié; pour le désigner, on lui associe un nom de variable ( ici : bulle ).update
, on appelle alors la méthode monter
à partir de l'objet bulle;draw
, on appelle la méthode afficher
associée à l'objet, en utilisant la syntaxe présentée dans le cours.Dans le programme principal, on crée une liste dont chaque élément sera un objet :
bulles = [] # tableau d'objets de type 'Bulle'
for i in range(50): # 50 bulles
x = randint(0, ppx.width)
y = ppx.height
couleur = randint(1, 15)
rayon = randint(2, 5)
vitesse = randint(2, 5)
bulle = Bulle(x, y, couleur, rayon, vitesse)
bulles.append(bulle)
( on peut bien entendu créer le tableau bulles par compréhension.)
Dans les fonctions update
et draw
, on parcourt alors le tableau de ces objets, en appelant, pour chacun de ces éléments
( qui sont des objets de type Bulle ) leurs méthodes monter
ou afficher
:
def update():
for bulle in bulles: # parcours par valeur du tableau des bulles
bulle.monter()
if bulle.y < 0: # si la bulle arrive en haut de l'écran,
bulle.y = ppx.height # on réinitialise tous ses paramètres !
bulle.x = randint(0, ppx.width)
bulle.couleur = randint(1, 15)
bulle.taille = randint(2, 5)
bulle.vitesse = randint(2, 5)
def draw():
ppx.cls(0)
for bulle in bulles:
bulle.afficher()
Le code complet du script est ici.
La méthode importante est la méthode rebonds
: elle prend comme paramètre un autre objet de type Balle
:
class Balle:
....
def rebonds(self, autre_balle): # le constructeur prend comme paramètre un AUTRE objet de type 'Balle'
dx = autre_balle.x - self.x
dy = autre_balle.y - self.y
distance = sqrt(dx**2 + dy**2)
minDist = autre_balle.taille + self.taille
if (distance < minDist):
self.vx = -self.vx
self.vy = -self.vy
autre_balle.vx = -autre_balle.vx
autre_balle.vy = -autre_balle.vy
Et cette méthode doit être appelée dans la fonction update
( pour une seule des balles ) :
def update():
# déplacement des balles
balle1.move()
balle2.move()
# gestion du rebond éventuel l'une sur l'autre
balle1.rebonds(balle2)
Le code complet du script est ici.
Le code complet du script est ici.
Le code complet du script est ici.