====== Le joueur ====== ===== Principe général ===== ==== Première approche ==== Le mouvement gauche - droite ne pose pas de problème. C'est le mouvement vertical qu'il faut travailler. Un mouvement vertical réaliste sera obtenu grâce à trois paramètres : * la position $y$ * la vitesse $v_y$ * l'accélération de la pesanteur $g$. Quand le joueur a les pieds sur terre, $y$ ne change pas, $v_y = 0$ et $g$ n'agit pas. Quand le joueur saute, au début de sont saut, $v_y = V$, où $V < 0$ est une vitesse de saut à choisir pour un saut réaliste. Puis à chaque période de temps, on a : $y \leftarrow y + v_y$ et $v_y \leftarrow v_y + g$. Ainsi quand $v_y < 0$, le sprite monte à l'écran et quand $v_y > 0$ il descend. L'action de $g$ est qu'au début du saut, le sprite monte. Puis il perd de la vitesse, atteint son sommet et se met à descendre. def jump(self): """ amorce un saut """ self.vy = self.JUMP_VELOCITY ... def update_position(self, plateformes): """ Calcule la nouvelle position tenant compte de la vitesse courante et sans dépasser les limites """ self.rect.centerx += self.vx self.vy += self.G #pesanteur self.rect.centery += self.vy if self.rect.centerx > self.xmax: self.rect.centerx = self.xmax elif self.rect.centerx < self.xmin: self.rect.centerx = self.xmin self.vx *= 0.2 if abs(self.vx) < 1: self.vx = 0 ==== Détection de plate-forme ==== Si on fait ce qui précède, les plates-formes sont ignorées et le sprite tombe aussitôt à travers le sol. Pour résoudre ce problème, on va détecter si les pieds du joueurs ont traversé la ligne supérieure d'une plate-forme en **descendant**. Le personnage sera toujours considéré en chute libre. Si sa chute lui fait traverser une plate-forme, on arrête la chute. * si ''self.vy > 0''... //seulement si le sprite descend// * pour chaque plate-forme ''pf'', * si le sprite était au-dessus de ''pf'' au début de son mouvement\\ //c'est à dire //''self.rect.bottom - self.vy <= pf.rect.top'' * si le sprite est au-dessous du top de ''pf'' à la fin de son mouvement\\ //c'est à dire //''self.rect.bottom > pf.rect.top'' * dans ce cas, on ramène le sprite sur le dessus de la plate-forme Notez que l'on fait toujours tomber le sprite. Comme on le ramène aussitôt s'il traverse la plate-forme, on ne le voit pas traverser, il semble immobile. def update_position(self, plateformes): """ plateformes: liste des plates-formes Calcule la nouvelle position tenant compte de la vitesse courante et sans dépasser les limites """ self.rect.centerx += self.vx self.vy += self.G #pesanteur self.rect.centery += self.vy if self.rect.centerx > self.xmax: self.rect.centerx = self.xmax elif self.rect.centerx < self.xmin: self.rect.centerx = self.xmin self.vx *= 0.2 if self.vy > 0: for pf in pygame.sprite.spritecollide(self, plateformes, False): if self.rect.bottom - self.vy <= pf.rect.top < self.rect.bottom: self.vy = 0 self.rect.bottom = pf.rect.top break if abs(self.vx) < 1: self.vx = 0 ==== Pas de saut dans le saut ==== On ne souhaite pas que le sprite puisse sauter s'il est déjà en train de sauter ou qu'il est en train de chuter. On rajoute alors une marqueur ''jumping'' qui passe à ''True'' chaque fois que le sprite saute ou tombe. ===== script complet ===== # fichier player.py import pygame class Player(pygame.sprite.Sprite): COLOR = (255, 255, 0) VELOCITY = 10 JUMP_VELOCITY = -20 HEIGHT = 50 WIDTH = 20 G = 2 def __init__(self, x0, y0, xmin, xmax): """ x0, y0: position initiale du coin inférieur gauche xmin, xmax: valeurs à ne pas dépasser """ super().__init__() self.image = pygame.Surface((self.WIDTH, self.HEIGHT)) self.image.fill(self.COLOR) self.rect = self.image.get_rect() self.rect.left = x0 self.rect.bottom = y0 self.xmin = xmin self.xmax = xmax self.jumping = False self.vx = 0 self.vy = 0 def move_left(self): """ amorce un mouvement vers la gauche """ self.vx = -self.VELOCITY def move_right(self): """ amorce un mouvement vers la droite """ self.vx = self.VELOCITY def jump(self): """ amorce un saut """ if not self.jumping: self.vy = self.JUMP_VELOCITY self.jumping = True def update_position(self, plateformes): """ plateformes: liste des plates-formes Calcule la nouvelle position tenant compte de la vitesse courante et sans dépasser les limites """ self.rect.centerx += self.vx self.vy += self.G #pesanteur self.rect.centery += self.vy if self.rect.centerx > self.xmax: self.rect.centerx = self.xmax elif self.rect.centerx < self.xmin: self.rect.centerx = self.xmin self.vx *= 0.2 if self.vy > 0: self.jumping = True for pf in pygame.sprite.spritecollide(self, plateformes, False): if self.rect.bottom - self.vy <= pf.rect.top < self.rect.bottom: self.vy = 0 self.rect.bottom = pf.rect.top self.jumping = False break if abs(self.vx) < 1: self.vx = 0