Décompte de victoire
On va mettre en place un compte à rebours jusqu'à la victoire du joueur.
Simulation
Dans la simulation, on va rajouter un attribut decompte_victoire
. La valeur initiale de la durée avant une victoire (en secondes) sera pour le moment sous forme d'une constante.
class Simulation:
def __init__(self, personnage):
self.personnage = personnage
self.projectiles = [
Projectile(Vector2(200, 300), Vector2(1.0, 1.0)),
Projectile(Vector2(400, 120), Vector2(1.0, 0)),
Projectile(Vector2(800, 600), Vector2(-1.1, -0.3)),
Projectile(Vector2(200, 600), Vector2(0.2, -0.1)),
]
self.collision = False
self.decompte_victoire = DECOMPTE_VICTOIRE
On écrit maintenant une fonction de simulation responsable du décompte. Si le temps restant devient négatif, on le bloque à zéro.
def decompter_victoire(etat, t):
etat.simulation.decompte_victoire -= t
if etat.simulation.decompte_victoire < 0:
etat.simulation.decompte_victoire = 0.0
On l'ajoute à la simulation.
def avancer_simulation(etat, t):
deplacer_personnage(etat, t)
limiter_deplacement_personnage(etat)
deplacer_projectiles(etat, t)
faire_rebondir_projectiles(etat)
detecter_collisions(etat)
decompter_victoire(etat, t)
Boucle principale
Dans la boucle principale, on rajoute une condition pour arrêter la simulation, et on affiche le message de victoire ou de défaite.
while not etat.controles.quitter:
if etat.controles.recommencer:
reinitialiser_controles(etat)
reinitialiser_simulation(etat)
reinitialiser_rendu(etat)
t = clock.tick(FPS)/1000
traiter_controles(etat, t)
if etat.simulation.collision:
print("Défaite !")
elif etat.simulation.decompte_victoire == 0.0:
print("Victoire !")
else:
avancer_simulation(etat, t)
afficher_rendu(etat, t)
Si on execute le jeu, et qu'on arrive à survivre assez longtemps, on pourra voir la victoire s'afficher en console. Au contraire, si on a une collision avant, on verra la défaite.
Le code complet de l'étape se trouve dans le dépliant ci-dessous :
Code Complet
import pygame
from pygame.math import Vector2
####################
#### CONFIG ####
####################
## Général
FPS = 60
LARGEUR_FENETRE = 1280
HAUTEUR_FENETRE = 720
## Controles
TOUCHE_QUITTER = pygame.K_ESCAPE
TOUCHE_HAUT = pygame.K_UP
TOUCHE_BAS = pygame.K_DOWN
TOUCHE_DROITE = pygame.K_RIGHT
TOUCHE_GAUCHE = pygame.K_LEFT
TOUCHE_RECOMMENCER = pygame.K_r
## Simulation
VITESSE_PERSONNAGE = 300
TAILLE_PERSONNAGE = 10
TAILLE_PROJECTILES = 10
VITESSE_PROJECTILES = 200
DECOMPTE_VICTOIRE = 5.0
## Rendu
COULEUR_ARRIERE_PLAN = (0, 0, 0)
COULEUR_PERSONNAGE = (255, 146, 205)
COULEUR_PROJECTILES = (146, 255, 205)
####################
#### GENERAL ####
####################
class GameState :
def __init__(self):
self.controles = None # on met a None parce que ces attributs seront initialisés plus tard
self.simulation = None
self.rendu = None
####################
#### CONTROLEUR ####
####################
class Controles :
def __init__(self):
self.quitter = False
self.direction = Vector2(0,0)
self.recommencer = False
def initialiser_controles(etat):
etat.controles = Controles()
def reinitialiser_controles(etat):
etat.controles = Controles()
def traiter_controles(etat, t):
for e in pygame.event.get():
if e.type == pygame.KEYDOWN:
if e.key == TOUCHE_QUITTER:
etat.controles.quitter = True
if e.key == TOUCHE_RECOMMENCER:
etat.controles.recommencer = True
direction = Vector2(0, 0)
clavier = pygame.key.get_pressed()
if clavier[TOUCHE_HAUT]:
direction.y += 1.0
if clavier[TOUCHE_BAS]:
direction.y -= 1.0
if clavier[TOUCHE_DROITE]:
direction.x += 1.0
if clavier[TOUCHE_GAUCHE]:
direction.x -= 1.0
if direction.length() != 0:
direction.normalize_ip()
etat.controles.direction = direction
####################
#### SIMULATION ####
####################
class Personnage:
def __init__(self, position):
self.position = position
class Projectile:
def __init__(self, position, direction):
self.position = position
self.direction = direction
if self.direction.length != 0:
self.direction.normalize_ip()
class Simulation:
def __init__(self, personnage):
self.personnage = personnage
self.projectiles = [
Projectile(Vector2(200, 300), Vector2(1.0, 1.0)),
Projectile(Vector2(400, 120), Vector2(1.0, 0)),
Projectile(Vector2(800, 600), Vector2(-1.1, -0.3)),
Projectile(Vector2(200, 600), Vector2(0.2, -0.1)),
]
self.collision = False
self.decompte_victoire = DECOMPTE_VICTOIRE
def initialiser_simulation(etat):
pos = Vector2(LARGEUR_FENETRE/2, HAUTEUR_FENETRE/2)
p = Personnage(pos)
etat.simulation = Simulation(p)
def reinitialiser_simulation(etat):
initialiser_simulation(etat)
def intersection(c1, r1, c2, r2):
return c1.distance_to(c2) <= r1 + r2
def detecter_collisions(etat):
perso = etat.simulation.personnage
for p in etat.simulation.projectiles:
if intersection(perso.position, TAILLE_PERSONNAGE, p.position, TAILLE_PROJECTILES):
etat.simulation.collision = True
def deplacer_personnage(etat, t):
direction = etat.controles.direction
etat.simulation.personnage.position += direction * VITESSE_PERSONNAGE * t
def limiter_deplacement_personnage(etat):
p = etat.simulation.personnage
if p.position.x < TAILLE_PERSONNAGE:
p.position.x = TAILLE_PERSONNAGE
if p.position.x > LARGEUR_FENETRE - TAILLE_PERSONNAGE:
p.position.x = LARGEUR_FENETRE - TAILLE_PERSONNAGE
if p.position.y < TAILLE_PERSONNAGE:
p.position.y = TAILLE_PERSONNAGE
if p.position.y > HAUTEUR_FENETRE - TAILLE_PERSONNAGE:
p.position.y = HAUTEUR_FENETRE - TAILLE_PERSONNAGE
def deplacer_projectiles(etat, t):
for p in etat.simulation.projectiles:
p.position += p.direction * VITESSE_PROJECTILES * t
def faire_rebondir_projectiles(etat):
for p in etat.simulation.projectiles:
if p.position.x < TAILLE_PROJECTILES:
p.position.x = TAILLE_PROJECTILES
p.direction.x *= -1
if p.position.x > LARGEUR_FENETRE - TAILLE_PROJECTILES:
p.position.x = LARGEUR_FENETRE - TAILLE_PROJECTILES
p.direction.x *= -1
if p.position.y < TAILLE_PROJECTILES:
p.position.y = TAILLE_PROJECTILES
p.direction.y *= -1
if p.position.y > HAUTEUR_FENETRE - TAILLE_PROJECTILES:
p.position.y = HAUTEUR_FENETRE - TAILLE_PROJECTILES
p.direction.y *= -1
def decompter_victoire(etat, t):
etat.simulation.decompte_victoire -= t
if etat.simulation.decompte_victoire < 0:
etat.simulation.decompte_victoire = 0.0
def avancer_simulation(etat, t):
deplacer_personnage(etat, t)
limiter_deplacement_personnage(etat)
deplacer_projectiles(etat, t)
faire_rebondir_projectiles(etat)
detecter_collisions(etat)
decompter_victoire(etat, t)
####################
#### RENDU ####
####################
class Rendu:
def __init__(self, ecran):
self.ecran = ecran
def ref_sve(v):
return Vector2(v.x, HAUTEUR_FENETRE - v.y)
def initialiser_rendu(etat, ecran):
etat.rendu = Rendu(ecran)
def reinitialiser_rendu(etat):
ecran = etat.rendu.ecran
etat.rendu = Rendu(ecran)
def rendre_personnage(etat):
ecran = etat.rendu.ecran
position = etat.simulation.personnage.position
pygame.draw.circle(ecran, COULEUR_PERSONNAGE, ref_sve(position), TAILLE_PERSONNAGE)
def rendre_projectiles(etat):
ecran = etat.rendu.ecran
for p in etat.simulation.projectiles:
position = p.position
pygame.draw.circle(ecran, COULEUR_PROJECTILES, ref_sve(position), TAILLE_PROJECTILES)
def afficher_rendu(etat, t):
ecran = etat.rendu.ecran
ecran.fill(COULEUR_ARRIERE_PLAN)
rendre_projectiles(etat)
rendre_personnage(etat)
pygame.display.flip()
####################
#### MAIN ####
####################
def main():
pygame.init()
etat = GameState()
fenetre = pygame.display.set_mode([LARGEUR_FENETRE, HAUTEUR_FENETRE])
initialiser_controles(etat)
initialiser_simulation(etat)
initialiser_rendu(etat, fenetre)
clock = pygame.time.Clock()
while not etat.controles.quitter:
if etat.controles.recommencer:
reinitialiser_controles(etat)
reinitialiser_simulation(etat)
reinitialiser_rendu(etat)
t = clock.tick(FPS)/1000
traiter_controles(etat, t)
if etat.simulation.collision:
print("Défaite !")
elif etat.simulation.decompte_victoire == 0.0:
print("Victoire !")
else:
avancer_simulation(etat, t)
afficher_rendu(etat, t)
pygame.quit()
if __name__ == "__main__":
main()