Tuto 3 : des acteurs multiples
Un jeu comporte souvent des sprites du même type, comme par exemple les bombes larguées par un vaisseau, les pièces récoltées par un personnage, etc...
Un objet par acteur
Pour chacun de ces acteurs du même type, on créera un objet ayant ses propres attributs.
Voila par exemple une classe Tir, destinée à instancier les multiples objets modélisant des tirs du vaisseau du script précédent.
Un tir est caractérisé par ses coordonnées. Les coordonnées initiales du tir sont déterminées à partir de celles du vaisseau, sachant que ces coordonnées
correspondent au coin en haut à gauche.
On déplace ensuite le tir jusqu’à ce qu’il sorte de l’écran.
class Tir:
def __init__(self, x, y):
self.x = x
self.y = y
self.alive = True # le tir est instancié dans l'état "en vol"
def is_alive(self): # méthode qui permet de savoir si le tir est toujours "en vol".
return self.alive # Renvoie un booléen indiquant l'état.
def move(self):
if self.y > 0: # si il n'a pas atteint le haut de l'écran,
self.y = self.y - 2 # alors on le déplace,
else:
self.alive = False # sinon on indique que le tir n'est plus "en vol".
def draw(self):
pyxel.rect(self.x, self.y, 1, 4, 10)
Utilisation d'une liste d'objets
On utilisera alors une liste Python liste_tirs pour stocker les objets correspondant aux différents tirs "en cours" :
- cette liste sera initialisée vide au lancement du jeu ( constructeur de la classe
Jeu) - lors de l'appui sur la touche ESPACE, la méthode
move()du vaisseau renverra une information qui indiquera au jeu d'ajouter à la liste liste_tirs un objet de typeTir. - dans la méthode
update()de la classeJeu, on parcourra la liste liste_tirs et on appellera la méthodemove()de chacun de ses éléments.
Pour tester si un tir n'est plus "en vol", on utilise sa méthodeis_alive(), qui indiquera au jeu de supprimer l'objet correspondant de la liste. - on fera de même dans la fonction
draw()pour afficher les différents tirs avec la méthodedraw()de la classeTir.
import pyxel
class Vaisseau:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self):
"""déplacement avec les touches de direction"""
if pyxel.btn(pyxel.KEY_RIGHT):
if (self.x < 120) :
self.x = self.x + 1
if pyxel.btn(pyxel.KEY_LEFT):
if (self.x > 0) :
self.x = self.x - 1
if pyxel.btn(pyxel.KEY_DOWN):
if (self.y < 120) :
self.y = self.y + 1
if pyxel.btn(pyxel.KEY_UP):
if (self.y > 0) :
self.y = self.y - 1
if pyxel.btnr(pyxel.KEY_SPACE): # si la touche "ESPACE" a été appuyée :
return self.x + 4, self.y - 2 # on signale un nouveau tir en renvoyant les coordonnées du vaisseau.
return None # Si on renvoie None, c'est qu'aucun nouveau tir n'a été déclenché.
def draw(self):
pyxel.rect(self.x, self.y, 8, 8, 1)
class Tir:
def __init__(self, x, y):
self.x = x
self.y = y
self.alive = True
def is_alive(self):
return self.alive
def move(self):
if self.y > 0:
self.y = self.y - 2
else:
self.alive = False
def draw(self):
pyxel.rect(self.x, self.y, 1, 4, 10)
class Jeu:
def __init__(self, h, l, titre):
pyxel.init(h, l, title = titre)
self.vaisseau = Vaisseau(60, 60)
self.liste_tirs = [] # liste des tirs, initialement vide
# Lancement du jeu
pyxel.run(self.update, self.draw)
def update(self):
v = self.vaisseau.move() # appel de la méthode move() du vaisseau, et récupération de son résultat renvoyé.
if v is not None: # Si ce résultat n'est pas None,
self.liste_tirs.append(Tir(v[0], v[1])) # c'est qu'il faut ajouter un tir à la liste des tirs.
for tir in self.liste_tirs: # Pour chaque tir dans la liste des tirs,
tir.move() # on appelle sa méthode move(),
if not tir.is_alive(): # si le tir n'est plus "en vol",
self.liste_tirs.remove(tir) # on le supprime de la liste des tirs.
def draw(self):
pyxel.cls(0)
self.vaisseau.draw()
for tir in self.liste_tirs:
tir.draw()
########################
# PROGRAMME PRINCIPAL #
########################
Jeu(128, 128, "Super Jeu")
A faire soi-même
A l'aide du même mécanisme, gérer le largage simultané par le vaisseau de bombes ( circulaires ) vers le bas de l'écran.