Sol sur pygame

Utilisateur anonyme - 6 mai 2023 à 11:18
 loupiot - 7 mai 2023 à 16:32

Bonjour, j'aimerais savoir comment est ce qu'on peut changer la hauteur du sol. Je l'ai changé a partir du moment ou le score est >= 10 mais le truc c'est que quand le joueur retombe, d'une plateforme par exemple, il retombe au niveau du sol initial et remonte juste apres en mode incognito :/ Comment est ce qu'on peut changer ca pour qu'il reste sur le sol ?

import pygame
import random
import time

pygame.font.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_COLOR = 0,0,0

SOL_Y = 550

PLAYER_COLOR = 255, 255, 255
PLAYER_HEIGHT = 30
PLAYER_WIDTH = 30
EVENT_OBSTACLE_SPAWN = pygame.USEREVENT + 1
police = pygame.font.Font(None, 50)
FPS = 95
BAR_WIDTH = 800
BAR_HEIGHT = 30
EVENT_PROGRESS_BAR = pygame.USEREVENT + 2


class Sol(pygame.sprite.Sprite):
    def __init__(self, y):
        super().__init__()
        self.image = pygame.Surface((SCREEN_RECT.w, 350))
        self.image.fill((0,0,0))
        self.rect = self.image.get_rect()
        self.rect.topleft = 0, y

    class Sol(pygame.sprite.Sprite):
        def __init__(self, y):
            super().__init__()
            self.image = pygame.Surface((SCREEN_RECT.w, 350))
            self.image.fill((0, 0, 0))
            self.rect = self.image.get_rect()
            self.rect.topleft = 0, y




class Player(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((30, 30))
        self.image.fill(PLAYER_COLOR)
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y
        self.x = x
        self.y = y
        self.jumping = False
        self.jump_count = 20


    def move(self, amount):
        self.rect.x += amount

    def jump(self):
        self.jumping = True

    def collision(self, sprites):  # gère les collisions
        for sprite in sprites:

            if isinstance(sprite, Triangle):
                if self.rect.colliderect(sprite.rect):
                    if self.rect.bottom <= sprite.rect.centery:
                        self.rect.bottom = sprite.rect.top

                    elif self.rect.top >= sprite.rect.centery:
                        # pygame.mixer.music.stop()
                        pygame.time.wait(1000)
                        quit()

                    else:
                        if self.rect.centerx < sprite.rect.centerx:
                            self.rect.right = sprite.rect.left

                        else:
                            self.rect.left = sprite.rect.right

            elif isinstance(sprite, Rectangle):
                if self.rect.colliderect(sprite.rect):
                    if self.rect.bottom <= sprite.rect.centery:
                        self.rect.bottom = sprite.rect.top

                    elif self.rect.top >= sprite.rect.centery:
                        # pygame.mixer.music.stop()
                        pygame.time.wait(1000)
                        quit()

                    else:
                        if self.rect.centerx < sprite.rect.centerx:
                            self.rect.right = sprite.rect.left

                        else:
                            self.rect.left = sprite.rect.right

            elif isinstance(sprite, DoubleTriangle):
                if self.rect.colliderect(sprite.rect):
                    if self.rect.bottom <= sprite.rect.centery:
                        self.rect.bottom = sprite.rect.top
                    elif self.rect.top >= sprite.rect.centery:
                        # pygame.mixer.music.stop()
                        pygame.time.wait(1000)
                        quit()

                    else:
                        if self.rect.centerx < sprite.rect.centerx:
                            self.rect.right = sprite.rect.left

            elif isinstance(sprite, Plateforme):

                if self.rect.colliderect(sprite.rect):
                    if self.rect.bottom <= sprite.rect.centery:
                        self.rect.bottom = sprite.rect.top

                    elif self.rect.top >= sprite.rect.centery:
                        # pygame.mixer.music.stop()
                        pygame.time.wait(1000)
                        quit()

                    else:
                        if self.rect.centerx < sprite.rect.centerx:
                            self.rect.right = sprite.rect.left

                        else:
                            self.rect.left = sprite.rect.right

        # Retourne les sprites en collision avec le joueur
        return tuple(s for s in sprites if s.rect.colliderect(self.rect))

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE] or keys[pygame.K_UP]:
            self.jump()

        if self.jumping:
            step = -(0.05 * self.jump_count ** 2) * (70 / FPS)
            if self.jump_count > 0:
                step *= -1
            self.rect.y -= step
            self.jump_count -= 1
            if self.rect.bottom >= self.y:
                self.rect.bottom = self.y
                self.jumping = False
                self.jump_count = 20
        else:
            if self.rect.bottom < SOL_Y:
                self.rect.bottom += 6 #simule le fait qu'il retombe d'une plateforme sinon il y reste
            if score.score >= 10 and self.rect.bottom > 350:
                self.rect.bottom = 350
                """c'est peut etre ca qu'il faut changer parce que y a marqué que si il est en dessous de 350, il retourne à 350 mais faut juste pas qu'il tombe en dessous de 350"""

         

class ProgressBar(pygame.sprite.Sprite):
    def __init__(self, width, height, color):
        super().__init__()
        self.image = pygame.Surface((width, height), pygame.SRCALPHA).convert_alpha()
        self.rect = self.image.get_rect()
        self.color = color
        self._percent = 0

    def is_full(self):
        return self._percent == 100

    def increase(self, percent):
        if self._percent == 100:
            return
        self._percent += percent
        self._percent = min(100, self._percent)
        width = self.rect.w / 100 * self._percent
        pygame.draw.rect(self.image, self.color, (0, 0, width, self.rect.h))


# score
class ScoreBoard(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.x = x
        self.y = y
        self.score = 0
        self.font = pygame.font.SysFont('Arial', 30)  # police
        self.color = (255, 255, 255)
        self.image = self.font.render('0', True, self.color)
        self.rect = self.image.get_rect()
        self.rect.topright = x, y
        self.last_update_time = time.time()  # enregistre l'heure de la dernière mise à jour du score

    def update1(self):
        # Vérifie si 5 secondes se sont écoulées depuis la dernière mise à jour du score
        current_time = time.time()
        if current_time - self.last_update_time >= 5:
            self.add(5)  # Ajoute 5 points au score, qui augmente toutes les 5 secondes
            self.last_update_time = current_time

    def add(self, amount):  # ajoute
        self.score += amount
        self.image = self.font.render(str(self.score), True, self.color)
        self.rect = self.image.get_rect()
        self.rect.topright = self.x, self.y


class Obstacle(pygame.sprite.Sprite):  # classe pour les obstacles
    def __init__(self, x, y, width, height):
        super().__init__()
        self.image = pygame.Surface((width, height), pygame.SRCALPHA)
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y

    def update(self):
        self.rect.x -= 6


class Triangle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 60, 60)
        pygame.draw.polygon(self.image, (0, 255, 0), ((30, 0), (0, 60), (60, 60)))  # formation du triangle



class Rectangle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 70, 135)
        pygame.draw.rect(self.image, (12, 48, 255), (5, 5, 130, 130))


class BasPlateforme(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 252, 60)
        pygame.draw.rect(self.image, (88, 35, 255), (10, 10, 670, 50))


class DoubleTriangle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 60, 60)
        self.image = pygame.Surface((240, 60), pygame.SRCALPHA)
        pygame.draw.polygon(self.image, (255, 255, 0), ((30, 0), (0, 60), (60, 60)))
        pygame.draw.polygon(self.image, (255, 255, 0), ((90, 0), (60, 60), (120, 60)))
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y


class Plateforme(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 187, 187)
        pygame.draw.rect(self.image, (185, 235, 255), (10, 10, 670, 50))




# le spawn ; c'est une sorte de création en direct d'objets ou de personnages (ici ça va être les obstacles)
def obstacle_spawn():
    # Choix de l'obstacle (tu choisis si tu veux plus de triangles ou de cercles)
    obstacle_class = \
    random.choices((Triangle, Rectangle, DoubleTriangle, Plateforme, BasPlateforme), (11, 14, 15, 14, 12))[0]
    obstacle = obstacle_class(SCREEN_RECT.w, SOL_Y)
    draw_group.add(obstacle)
    obstacles_group.add(obstacle)


def spawn_timer():
    ms = random.randrange(490, 750)  # temps en millisecondes, determine le temps d'espace entre les obstacles
    pygame.time.set_timer(EVENT_OBSTACLE_SPAWN, ms)


def sprites_clear(surface, rect):
    surface.fill(SCREEN_COLOR, rect)


# application
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
SCREEN_RECT = screen.get_rect()
pygame.mouse.set_visible(False)
pygame.display.set_caption("Geo")

draw_group = pygame.sprite.RenderUpdates()
obstacles_group = pygame.sprite.Group()

player = Player(100, SOL_Y)
draw_group.add(player)

sol = Sol(SOL_Y)
draw_group.add(sol)

score = ScoreBoard(SCREEN_RECT.right - 10, 10)  # position ou y aura le score sur l'écran
score.update()
draw_group.add(score)

progress_bar = ProgressBar(BAR_WIDTH, BAR_HEIGHT, (0, 255, 0))
progress_bar.rect.topleft = 0, 0
draw_group.add(progress_bar)

screen.fill(SCREEN_COLOR)
pygame.display.update()

clock = pygame.time.Clock()
running = True
points = 0
spawn_timer()

pygame.time.set_timer(EVENT_PROGRESS_BAR, 100)
all_sprites = pygame.sprite.Group()

# boucle principale
while running:
    clock.tick(FPS)
    score.update1()
    screen.blit(score.image, score.rect)

    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP or pygame.K_SPACE and not player.jumping:  # touches pour sauter
                player.jump()
        elif event.type == EVENT_OBSTACLE_SPAWN:  # generations obstacles
            obstacle_spawn()
            spawn_timer()
            draw_group.remove(player)
            draw_group.add(player)
        elif event.type == EVENT_PROGRESS_BAR:
            progress_bar.increase(0.5)

        elif event.type == pygame.QUIT:
            running = False

    # Vérification de la collision entre le joueur et la plateforme
    on_platform = False
    for obstacle in obstacles_group:
        if isinstance(obstacle, Plateforme) and player.rect.colliderect(obstacle.rect):
            if player.rect.bottom <= obstacle.rect.bottom:
                player.rect.bottom = obstacle.rect.top
                player.jumping = False
                player.jump_count = 21
                on_platform = True

    on_platform = False
    for obstacle in obstacles_group:
        if isinstance(obstacle, BasPlateforme) and player.rect.colliderect(obstacle.rect):
            if player.rect.bottom <= obstacle.rect.bottom:
                player.rect.bottom = obstacle.rect.top
                player.jumping = False
                player.jump_count = 21
                on_platform = True

    on_platform = False
    for obstacle in obstacles_group:
        if isinstance(obstacle, Rectangle) and player.rect.colliderect(obstacle.rect):
            if player.rect.bottom <= obstacle.rect.bottom:
                player.rect.bottom = obstacle.rect.top
                player.jumping = False
                player.jump_count = 21
                on_platform = True

    # Collision obstacles avec le joueur
    for sprite in player.collision(obstacles_group.sprites()):
        obstacles_group.remove(sprite)
        draw_group.remove(sprite)

    # Suppression des sprites hors écran
    for sprite in obstacles_group.copy().sprites():
        if sprite.rect.right < SCREEN_RECT.x:
            obstacles_group.remove(sprite)
            draw_group.remove(sprite)

    if score.score >= 10:
        SOL_Y = 350


    draw_group.clear(screen, sprites_clear)
    draw_group.update()
    rects = draw_group.draw(screen)
    pygame.display.update(rects)

    pygame.display.flip()

pygame.quit()

1 réponse

Salut,

Lorsque tu présentes du code, assure-toi au moins que ce soit visualisable, si on lance ton script, on a à peine le temps de voir quelque chose que la fenêtre se ferme directement.

J''imagine que seules les formes planes seront lesquelles où le joueur pourra se déplacer, donc il faut en 1er lieu ajouter un attribut (walkable dans le code) à la classe obstacle, ainsi lorsque le joueur tombera, il pourra se réceptionner sur ces surfaces.

Idem pour les obstacles que peuvent percuter le joueur, peuvent-ils tous le faire ? Un autre attribut (solid dans le code) pourrait s'avérer nécessaire afin de le savoir.

Sachant que le joueur doit avoir connaissance des éléments qui l'entourent, donc des surfaces “ walkable ”, on peut lui fournir dans l'instance du joueur en fourrant cela dans un groupe pygame (bien plus simple à gérer).

Pour faciliter la détection que le joueur est sur un sol, on peut se créer un autre Rect sous le joueur, et s'en servir pour détecter les collisions avec les sols.

Pourquoi ne pas avoir gardé la modification avec la mise à jour du score ?

Voici un code gérant les sauts et chutes du joueur, il y aurait encore des choses à peaufiner et revoir, mais le principe est là, je suis parti du précédent code que je t'avais exposé dans ton sujet précédent.

Il y a aussi désormais une classe gérant l'application.

import random
import pygame

FPS = 60
# Ajustement de la gravité en fonction de l'IPS
GRAVITY = 0.38 * (60 / FPS) ** 2
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_COLOR = 120, 170, 255

GROUND_Y = 550

PLAYER_COLOR = 255, 255, 255

BAR_WIDTH = 800
BAR_HEIGHT = 30

EVENT_OBSTACLE_SPAWN = pygame.USEREVENT
EVENT_SCORE_UPDATE = pygame.USEREVENT + 1
EVENT_PROGRESS_BAR = pygame.USEREVENT + 2


class Ground(pygame.sprite.Sprite):
    def __init__(self, y):
        super().__init__()
        self.image = pygame.Surface((SCREEN_WIDTH, 100))
        self.image.fill((100, 200, 80))
        self.rect = self.image.get_rect()
        self.rect.topleft = 0, y


class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, walkable_group):
        super().__init__()
        self.image = pygame.Surface((30, 30))
        self.image.fill(PLAYER_COLOR)
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y
        self._walkable_group = walkable_group
        self.x = x
        self.y = y
        # Création d'un rectangle d'1 px de haut situé sous le joueur
        # dont on se servira pour déterminer si le joueur est sur une surface
        # sur laquelle il peut se mouvoir
        self._sub_rect = pygame.Rect(self.rect.x, self.rect.bottom, self.rect.w, 1)
        self._jumping = False
        self._falling = False
        # Nombre d'étape max. du saut (ne pas toucher)
        self._vertical_step = 30 / 60 * FPS
        self._falling_step = 0
        self._gravity = GRAVITY

    def on_solid_surface(self):
        # Détermine si le joueur est sur un sol

        # mise à jour de la position y du « sous » rectangle
        self._sub_rect.top = self.rect.bottom
        rects = tuple(sprite.rect for sprite in self._walkable_group)
        # collidelist retourne -1 si aucune collision parmi les rect. fournis
        # ou l'indice du 1er rect. en collision de la liste fournie
        return not self._sub_rect.collidelist(rects) == -1

    def jump(self):
        if not self._jumping and not self._falling:
            self._jumping_step = self._vertical_step
            self._jumping = True

    def collide(self, sprites):
        return tuple(s for s in sprites if s.rect.colliderect(self.rect))

    def update(self):
        if self._jumping:
            self.rect.y -= self._jumping_step * self._gravity
            self._jumping_step -= 1
            if not self._jumping_step:
                self._jumping = False
                self._falling = True
                self._falling_step = 0
        elif self._falling:
            self.rect.y += self._falling_step * self._gravity
            if self.on_solid_surface():
                self._falling = False
                # Ajustement de la position du joueur sur la surface en contact
                rects = tuple(s.rect for s in self._walkable_group)
                i = self._sub_rect.collidelist(rects)
                rect = rects[i]
                self.rect.bottom = rect.top
            self._falling_step = min(self._vertical_step, self._falling_step + 1)
        else:
            if not self.on_solid_surface():
                # Donc, le joueur tombe sans avoir sauté, on le fait rechuter
                self._falling = True
                self._falling_step = 0

    jumping = property(lambda self: self._jumping)


class ScoreBoard(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.x = x
        self.y = y
        self.score = 0
        self.font = pygame.font.SysFont('Arial', 30)
        self.color = (255, 255, 255)
        self.image = self.font.render('0', True, self.color)
        self.rect = self.image.get_rect()
        self.rect.topright = x, y

    def add(self, amount):
        self.score += amount
        self.image = self.font.render(str(self.score), True, self.color)
        self.rect = self.image.get_rect()
        self.rect.topright = self.x, self.y


class Obstacle(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.image = pygame.Surface((width, height), pygame.SRCALPHA)
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y
        self.walkable = False  # spécifie que le joueur peut se mouvoir dessus
        self.solid = False  # spécifie que le joueur entrera en contact avec lui

    def update(self):
        self.rect.x -= 6


class Cercle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 60, 60)  # position du cercle sur l'écran
        pygame.draw.circle(self.image, (0, 155, 155), (30, 30), 30)


class Triangle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 60, 60)
        pygame.draw.polygon(self.image, (0, 255, 0), ((30, 0), (0, 60), (60, 60)))
        self.solid = True


class Rectangle(Obstacle):
    def __init__(self, x, y):
        # XXX Aucun intérêt de créer un rect, l'image EST un rectangle
        # d'autant que ça va poser un problème avec les collisions d'avoir une image
        # bien plus grande que ce qui est visualisable.
        # super().__init__(x, y, 70, 135)
        # pygame.draw.rect(self.image, (12, 48, 255), (5, 5, 130, 130))
        super().__init__(x, y, 70, 130)
        self.image.fill((12, 48, 255))
        self.walkable = True


class BasPlateforme(Obstacle):
    def __init__(self, x, y):
        # XXX Idem qu'au-dessus
        # super().__init__(x, y, 252, 60)
        # pygame.draw.rect(self.image, (88, 35, 255), (10, 10, 670, 50))
        super().__init__(x, y, 250, 60)
        self.image.fill((88, 35, 255))
        self.walkable = True


class DoubleTriangle(Obstacle):
    def __init__(self, x, y):
        super().__init__(x, y, 120, 60)
        pygame.draw.polygon(self.image, (255, 255, 0), ((30, 0), (0, 60), (60, 60)))
        pygame.draw.polygon(self.image, (255, 255, 0), ((90, 0), (60, 60), (120, 60)))
        self.rect = self.image.get_rect()
        self.rect.bottomleft = x, y
        self.solid = True


class Plateforme(Obstacle):
    def __init__(self, x, y):
        # XXX Idem que pour Rectangle
        # super().__init__(x, y, 187, 187)
        # pygame.draw.rect(self.image, (185, 235, 255), (10, 10, 670, 50))
        # TODO voir pour mettre la position y exacte à l'instance plutôt qu'ici
        super().__init__(x, y - 80, 187, 45)
        self.image.fill((185, 235, 255))
        self.walkable = True


class ProgressBar(pygame.sprite.Sprite):
    def __init__(self, width, height, color):
        super().__init__()
        self.image = pygame.Surface((width, height), pygame.SRCALPHA).convert_alpha()
        self.rect = self.image.get_rect()
        self.color = color
        self._percent = 0

    def is_full(self):
        return self._percent == 100

    def increase(self, percent):
        if self._percent == 100:
            return
        self._percent += percent
        self._percent = min(100, self._percent)
        width = self.rect.w / 100 * self._percent
        pygame.draw.rect(self.image, self.color, (0, 0, width, self.rect.h))


class Button(pygame.sprite.Sprite):
    def __init__(self, width, height, text, font, command):
        super().__init__()
        self.image = pygame.Surface((width, height)).convert()
        self.rect = self.image.get_rect()
        self.image.fill((125, 20, 200))
        self._text = font.render(text.upper(), True, (255, 255, 255))
        self.image.blit(self._text, self._text.get_rect(center=self.rect.center))
        self._command = command
        self._focus = False

    def call(self):
        self._command()

    @property
    def focus(self):
        return self._focus

    focus.setter
    def focus(self, bool_):
        assert bool_ in (0, 1)
        [self.focus_out, self.focus_in][bool_]()

    def focus_in(self):
        if self._focus:
            return
        self._focus = True
        pygame.draw.rect(self.image, (255, 255, 0), (0, 0, *self.rect.size), 5)

    def focus_out(self):
        if not self._focus:
            return
        self._focus = False
        pygame.draw.rect(self.image, (125, 20, 200), (0, 0, *self.rect.size), 5)


class Menu:
    def __init__(self, group):
        self._group = group
        self._font = pygame.font.SysFont('mono', 24, True)
        self._buttons = []
        self._focus_button = 0

    def add_button(self, text, command):
        button = Button(300, 60, text, self._font, command)
        self._buttons.append(button)

    def display(self):
        rect = self._buttons[0].rect
        bt_len = len(self._buttons)
        x = (SCREEN_WIDTH - rect.w) / 2
        y = SCREEN_HEIGHT - rect.h * bt_len - 50 * (bt_len - 1)
        y /= 2
        for button in self._buttons:
            button.rect.topleft = x, y
            y += rect.h + 70
        self._group.add(self._buttons)
        self._buttons[0].focus(True)

    def update(self, events):
        for evt in events:
            if evt.type == pygame.KEYDOWN:
                if evt.key == pygame.K_TAB:
                    self._buttons[self._focus_button].focus_out()
                    # Si une touche maj. n'est pas pressée
                    if not evt.mod & pygame.KMOD_SHIFT:
                        self._focus_button += 1
                        try:
                            self._buttons[self._focus_button].focus_in()
                        except IndexError:
                            self._focus_button = 0
                            self._buttons[self._focus_button].focus_in()
                    else:
                        self._focus_button -= 1
                        try:
                            self._buttons[self._focus_button].focus_in()
                        except IndexError:
                            self._focus_button = -1
                            self._buttons[self._focus_button].focus_in()
                elif evt.key == pygame.K_RETURN:
                    self._buttons[self._focus_button].call()


class Game:
    def __init__(self, group):
        self.group = group
        self.obstacle_group = pygame.sprite.Group()
        # Groupe des surfaces parcourables que l'on passe au joueur
        self.walkable_group = pygame.sprite.Group()
        # Groupe des surfaces qui peuvent enter en contact avec le joueur
        self.solid_group = pygame.sprite.Group()
        self.player = Player(100, 0, self.walkable_group)
        self.ground = Ground(GROUND_Y)
        self.score = ScoreBoard(SCREEN_WIDTH - 10, 10)
        self.progress_bar = ProgressBar(BAR_WIDTH, BAR_HEIGHT, (255, 165, 0, 128))
        self.progress_bar.rect.topleft = 0, 0
        self.group.add(self.ground, self.score, self.progress_bar, self.player)
        # Ajout du sol dans ce group
        self.walkable_group.add(self.ground)

        self._obstacle_spawn_timer()
        pygame.time.set_timer(EVENT_SCORE_UPDATE, 5000)
        pygame.time.set_timer(EVENT_PROGRESS_BAR, 100)

    def _obstacle_spawn_timer(self, ms=-1):
        if ms == -1:
            # ms = random.randrange(490, 750)
            ms = random.randrange(1800, 2500)
        pygame.time.set_timer(EVENT_OBSTACLE_SPAWN, ms)

    def obstacle_spawn(self):
        obstacle_class = random.choices(
            (Cercle, Triangle, Rectangle, DoubleTriangle, Plateforme, BasPlateforme),
            # (Plateforme, BasPlateforme),
            (5, 8, 7, 8, 9, 8),
            # (5, 8),
        )[0]
        obstacle = obstacle_class(SCREEN_WIDTH, GROUND_Y)
        self.group.add(obstacle)
        self.obstacle_group.add(obstacle)
        if obstacle.solid:
            self.solid_group.add(obstacle)
        if obstacle.walkable:
            self.walkable_group.add(obstacle)

    def update(self, events):
        for event in events:
            if event.type == pygame.KEYDOWN:
                # On ne fait pas : truc == machin or bidule
                # mais : truc == machin or truc == bidule
                # ou plus simplement avec un tuple comme ci-dessous
                if event.key in (pygame.K_UP, pygame.K_SPACE):
                    self.player.jump()
            elif event.type == EVENT_OBSTACLE_SPAWN:
                self.obstacle_spawn()
                self._obstacle_spawn_timer()
            elif event.type == EVENT_SCORE_UPDATE:
                self.score.add(5)
            elif event.type == EVENT_PROGRESS_BAR:
                self.progress_bar.increase(0.1)
                if self.progress_bar.is_full():
                    print('progression réussie !')
                    # Annulation du timer (mise à 0 des ms)
                    pygame.time.set_timer(EVENT_PROGRESS_BAR, 0)
                    # Faire ce qu'il y a à faire.
                    # Par exemple, arrêt des autres animations
                    self._obstacle_spawn_timer(0)
                    pygame.time.set_timer(EVENT_SCORE_UPDATE, 0)

        # Collision obstacles dur avec le joueur
        for sprite in self.player.collide(self.solid_group):
            # suppression du sprite de tous les groupes
            sprite.kill()

        # Suppression des sprites hors écran
        for sprite in self.obstacle_group.sprites():
            if sprite.rect.right < 0:
                sprite.kill()


class Application:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        # pygame.mouse.set_visible(False)
        pygame.display.set_caption("Geo")
        self.clock = pygame.time.Clock()
        self.draw_group = pygame.sprite.RenderUpdates()
        self.running = True

    def _sprites_clear(self, surface, rect):
        surface.fill(SCREEN_COLOR, rect)

    def menu(self):
        self.draw_group.empty()
        self.interface = Menu(self.draw_group)
        self.interface.add_button("JOUER", self.play)
        self.interface.add_button("OPTIONS", lambda: print("à réaliser"))
        self.interface.add_button("QUITTER", self.quit)
        self.interface.display()

    def play(self):
        self.draw_group.empty()
        self.interface = Game(self.draw_group)

    def quit(self):
        print("À la prochaine !")
        self.running = False

    def run(self):
        self.screen.fill(SCREEN_COLOR)
        pygame.display.update()
        while self.running:
            self.clock.tick(FPS)
            events = pygame.event.get()
            for evt in events:
                if evt.type == pygame.QUIT:
                    return self.quit()
            self.interface.update(events)

            self.draw_group.clear(self.screen, self._sprites_clear)
            self.draw_group.update()
            rects = self.draw_group.draw(self.screen)
            pygame.display.update(rects)
        pygame.quit()

if __name__ == '__main__':
    app = Application()
    app.menu()
    app.run()


Touche TAB (et MAJ) pour sélectionner, ENTRÉE pour lancer le jeu.

0