Aller au contenu

Recommencer

On veut pouvoir recommencer la partie sans avoir à quitter puis relancer le jeu.

Commande de RAZ

La touche pour recommencer à zéro sera R. On l'ajoute aux constantes du contrôleur.

## 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

Controles

Dans la classe Controles, on ajoute une commande recommencer.

class Controles :
    def __init__(self):
        self.quitter = False
        self.direction = Vector2(0,0)
        self.recommencer = False

Dans la fonction traiter_controles, on ajoute une détection d'un appui sur la touche R.

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

Réinitialisation

Il nous faut maintenant créer des fonctions qui réinitialisent l'état des contrôles, de la simulation et du rendu. Celà consiste simplement à remettre à zéro l'état de chaque système, en recréant l'objet associé.

def reinitialiser_controles(etat):
    etat.controles = Controles()
def reinitialiser_simulation(etat):
    initialiser_simulation(etat)

Pour le rendu, on garde le même écran.

def reinitialiser_rendu(etat):
    ecran = etat.rendu.ecran
    etat.rendu = Rendu(ecran)

Boucle principale

Dans la boucle principale, si la commande pour recommencer est activée, on réinitialise l'état du jeu.

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 not etat.simulation.collision:
        avancer_simulation(etat, t)

    afficher_rendu(etat, t)

On peut exécuter le programme pour vérifier que l'on peut recommencer à tout instant en appuyant sur R, même après une collision.

Le code complet 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

## 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):
        self.position = position

class Simulation:

    def __init__(self, personnage):
        self.personnage = personnage
        self.projectiles = [
            Projectile(Vector2(200, 300)),
            Projectile(Vector2(400, 120)),
            Projectile(Vector2(800, 600)),
            Projectile(Vector2(200, 600)),
        ]
        self.collision = False


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 avancer_simulation(etat, t):
    deplacer_personnage(etat, t)
    detecter_collisions(etat)

####################
####   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 not etat.simulation.collision:
            avancer_simulation(etat, t)

        afficher_rendu(etat, t)

    pygame.quit()


if __name__ == "__main__":
    main()