Favicon
NSI Terminale

Connexion élèves

Choisir le(s) module(s) à installer :

Salut à toi, élève de NSI, comment puis-je t'aider ?

Mini-Projets en POO

Vous avez terminé le TP "Champagne !" ?. Très bien ! Vous savez maintenant ( presque ) tout sur la POO...

Vous avez encore du temps ? Ok, voici deux autres projets possibles...

La fontaine colorée

Des balles colorées jaillissent du bas de la fenêtre avec une vitesse plus ou moins grande, décrivent ensuite une trajectoire parabolique avant de retomber au sol.

Sans entrer dans les explications, la grosse différence est que la composante verticale de la vitesse vy doit évoluer au cours du temps, selon l'équation : vy = vy + 10*dt, où dt représente la durée entre deux positions successives d'une balle.

On peut prendre dt égale à la durée entre deux frames de la boucle d'animation; cette valeur est par défaut de 60 ms ( 60e-3 s ).
N'hésitez pas cependant à modifier ce paramètre pour rendre l'animation plus fluide.

La composante horizontale vx ne change elle jamais ( pour les personnes concernées, vous verrez en SPC pourquoi, et aussi d'où sort le "10"...).

Compléter le code ci-dessous pour réaliser cette animation :

SOLUTION

Rebonds

Et un p'tit dernier pour la route : les classiques balles rebondissantes. Adaptez le code précédent pour créer cette animation :

Compléter le script ci-dessous pour réaliser cette animation.

Quelques conseils pour la gestion des rebonds

Un premier conseil : confiez la gestion des rebonds à une autre méthode ( testRebond() par exemple... ) de la classe Balle, méthode que vous appellerez à la suite des deux autres dans la boucle d'animation anim().
Cette méthode gérera aussi le cas où il faut réinitialiser les attributs de la balle ( lorsqu'elle sort sur les côtés de l'écran ).

Un rebond doit être déclenché au moment où une balle atteint le bas de la fenêtre; à ce moment les balles se déplaçant horizontalement de manière uniforme, c'est donc uniquement la valeur de vy qu'il faudra réinitialiser ( vx elle ne change pas...).
Cette modification devra "inverser" le sens de déplacement, mais aussi tenir compte de l'amortissement; pour cela, vous pouvez simplement multiplier à ce moment la valeur de la vitesse verticale vy de la balle lors de son "impact" au "sol" par un coefficient inférieur à 1 ( plus ce coefficient sera petit, plus le rebond sera "mou".).

SOLUTION

En conclusion...

J'ai bien travaillé...j'ai droit de jouer à ce petit jeu écrit en POO; utilisez la souris pour déplacer le vaisseau, et le clic gauche pour abattre les ennemis. Vous n'avez que 5 vies !

from random import randint import poorpyxel as pyxel class Vaisseau: def __init__(self, x, y): self.x = x self.y = y def move(self): """déplacement avec les touches de direction""" self.x, self.y = pyxel.mouse_x, pyxel.mouse_y if pyxel.btn(pyxel.MOUSE_BUTTON_LEFT): return self.x + 4, self.y - 2 return None def draw(self): pyxel.rect(self.x, self.y, 8, 8, 5) 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 Ennemi: 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 < 128: self.y = self.y + 2 else: self.alive = False def draw(self): pyxel.rect(self.x, self.y, 8, 8, 8) class Explosion: def __init__(self, x, y, r): self.x = x self.y = y self.r = r self.alive = True def is_alive(self): return self.alive def move(self): if self.r<5: # si le rayon de l'explosion ( 3ème élement ) n'a pas atteint 5 unités, self.r = self.r + 1 # alors on augmente ce rayon, else: self.alive = False def draw(self): pyxel.circb(self.x, self.y, self.r, 8 + (self.r)%5) class Jeu: def __init__(self, h, l, titre): pyxel.init(h, l) self.vaisseau = Vaisseau(60, 60) self.liste_tirs = [] self.liste_ennemis = [] self.liste_explosions = [] self.score = 0 self.vies = 5 # Lancement du jeu pyxel.run(self.update, self.draw) def update(self): v = self.vaisseau.move() if v is not None: self.liste_tirs.append(Tir(v[0], v[1])) if pyxel.frame_count % 30 == 0: self.liste_ennemis.append(Ennemi(randint(0, 120), 0)) for ennemi in self.liste_ennemis: ennemi.move() if not ennemi.is_alive(): self.score -= 1 self.liste_ennemis.remove(ennemi) for tir in self.liste_tirs: tir.move() if not tir.is_alive(): self.liste_tirs.remove(tir) for ennemi in self.liste_ennemis: for tir in self.liste_tirs: xt = tir.x yt = tir.y xe = ennemi.x ye = ennemi.y if yt <= ye+8 and ( xt >= xe and xt <= xe + 8): self.liste_tirs.remove(tir) self.liste_ennemis.remove(ennemi) self.liste_explosions.append(Explosion(xe+4, ye+4, 1)) # ajout d'une explosion à la liste self.score = self.score + 1 for ennemi in self.liste_ennemis: xv = self.vaisseau.x yv = self.vaisseau.y xe = ennemi.x ye = ennemi.y if xv <= xe + 8 and xv > xe - 8 and yv <= ye + 8 and yv > ye - 8: self.liste_ennemis.remove(ennemi) self.liste_explosions.append(Explosion(xe+4, ye+4, 1)) # ajout d'une explosion à la liste self.vies = self.vies - 1 for explosion in self.liste_explosions: explosion.move() if not explosion.is_alive(): self.liste_explosions.remove(explosion) def draw(self): pyxel.cls(0) if self.vies > 0: self.vaisseau.draw() for tir in self.liste_tirs: tir.draw() for ennemi in self.liste_ennemis: ennemi.draw() for explosion in self.liste_explosions: explosion.draw() pyxel.text(1, 1, str(self.score), 15) pyxel.text(pyxel.width-5, 1, str(self.vies), 15) else: pyxel.text(pyxel.width//2-len('GAME OVER')*4//2, pyxel.height//2, 'GAME OVER', 15) #pyxel.stop() ######################## # PROGRAMME PRINCIPAL # ######################## Jeu(128, 128, "Super Jeu")