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.
On va créer une classe Projectile, puis en ajouter quelques objets (aussi appelés instances) à la Simulation.
La classe est relativement simple :
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.
-
C'est bien entendu une référence à Dany Boon, un humoriste orginaire du Nord. ↩