Aller au contenu

Projectiles

On va commencer par ajouter des projectiles immobiles. Ce qui en fait de plutôt mauvais projectiles à vrai dire.

Simulation

La taille des projectiles sera une constante.

## Simulation

VITESSE_PERSONNAGE = 300
TAILLE_PERSONNAGE = 10
TAILLE_PROJECTILES = 10

On va créer une classe Projectile, puis en ajouter quelques objets (aussi appelés instances) à la Simulation.

La classe est relativement simple :

class Projectile:

    def __init__(self, position):
        self.position = position

L'ajout à la Simulation se fait sous forme d'une liste fixée dans la méthode __init__. La position est exprimée en pixels et doit être un Vector2.

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)),
        ]

Comme les projectiles ne se déplacent pas[^projectile_immobile], on n'a pas besoin de changer la fonction de simulation.

[^projectile_immobile] : C'est extrêmement perturbant d'écrire celà, je me demande si c'est aussi perturbant de le lire.

Rendu

La couleur des projectile va également être une constante. On va choisir une sorte de bleu-vert, le blair1.

## Rendu

COULEUR_ARRIERE_PLAN = (0, 0, 0)
COULEUR_PERSONNAGE = (255, 146, 205)
COULEUR_PROJECTILES = (146, 255, 205)

On crée une fonction rendre_projectiles, assez similaire de rendre_personnage, en n'oubliant pas qu'il y a un changement de référentiel à effectuer.

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)

Il nous faut l'appeler dans la fonction afficher_rendu. On l'appelle avant rendre_personnage, de manière à ce que le personnage soit "devant" les projectiles en cas de superposition.

def afficher_rendu(etat, t):
    ecran = etat.rendu.ecran
    ecran.fill(COULEUR_ARRIERE_PLAN)

    rendre_projectiles(etat)

    rendre_personnage(etat)

    pygame.display.flip() 

Le code complet de cette é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 

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

def initialiser_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

    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)),
        ]


def initialiser_simulation(etat):
    pos = Vector2(LARGEUR_FENETRE/2, HAUTEUR_FENETRE/2)
    p = Personnage(pos)
    etat.simulation = Simulation(p)

def avancer_simulation(etat, t):
    direction = etat.controles.direction
    etat.simulation.personnage.position += direction * VITESSE_PERSONNAGE * 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 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:

        t = clock.tick(FPS)/1000

        traiter_controles(etat, t)

        avancer_simulation(etat, t)

        afficher_rendu(etat, t)

    pygame.quit()


if __name__ == "__main__":
    main()

En lançant le programme, on peut voir les 4 ennemis apparaître à l'écran.

resultat


  1. C'est bien entendu une référence à Dany Boon, un humoriste orginaire du Nord.