Probleme de transition

Fermé
Justin - 9 avril 2023 à 14:10
 Justin - 12 avril 2023 à 15:26

Bonjour. Je fais pour moi-même un jeu (simple) et j'ai un problème. En fait, je souhaiterais creer une une ligne sur laquelle le joueur sera pendant 2 secondes, avant de jouer lui même (c'est une sorte de base). J'ai ma ligne, là ça va, et un de mes amis m'a dit qu'on ne pouvait pas supprimer de l'écran un dessin "rect" (je sais plus exactement ce qu'il a dit). Donc c'est pas grave, mon nouveau but est que des que les 2 secondes sont passées, j'aiemerai que la ligne soit soit très basse, soit très haute, juste qu'elle ne gene pas le joueur, qui peut jouer tranquillement. 
Le probleme c'est que la ligne (special floor) reste quand même, mais je ne sait pas pourquoi.

voici mon code : 

 import pygame
                        import time
                        import random

                        # Initialisation de Pygame
                        pygame.init()

                        # Constantes
                        SCREEN_WIDTH = 800
                        SCREEN_HEIGHT = 600
                        BACKGROUND_COLOR = (255, 105, 180)
                        PLAYER_COLOR = (255, 255, 255)
                        OBSTACLE_COLOR = (255, 255, 255)
                        SPECIAL_FLOOR_COLOR = (50, 205, 50)
                        PLAYER_SIZE = 25
                        PLAYER_START_X = 100
                        PLAYER_START_Y = 200
                        GRAVITY = 0.4
                        JUMP_VELOCITY = -10
                        OBSTACLE_WIDTH = 50
                        OBSTACLE_HEIGHT = 250
                        OBSTACLE_GAP = 175
                        OBSTACLE_VELOCITY = -3
                        OBSTACLE_GENERATION_DELAY = 1.5
                        FPS = 100
                        screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
                        game_over = False
                        player_y = PLAYER_START_Y
                        player_velocity = 0
                        obstacles = []
                        obstacle_last_generation_time = 0
                        score = 0
                        font = pygame.font.Font(None, 36)
                        start_time = time.time()


                        # Fonctions
                        def reset_game():
                            global game_over, player_y, player_velocity, obstacles, obstacle_last_generation_time, score
                            game_over = False
                            player_y = PLAYER_START_Y
                            player_velocity = 0
                            obstacles = []
                            obstacle_last_generation_time = 0
                            score = 0


                        def creer_obstacles():
                            gap_center_y = random.randint(150, SCREEN_HEIGHT - 150 - OBSTACLE_GAP)
                            obstacle_top_y = gap_center_y - OBSTACLE_GAP / 2 - OBSTACLE_HEIGHT
                            obstacle_bottom_y = gap_center_y + OBSTACLE_GAP / 2
                            obstacle_top_rect = pygame.Rect(SCREEN_WIDTH, obstacle_top_y, OBSTACLE_WIDTH, OBSTACLE_HEIGHT)
                            obstacle_bottom_rect = pygame.Rect(SCREEN_WIDTH, obstacle_bottom_y, OBSTACLE_WIDTH, OBSTACLE_HEIGHT)
                            obstacles.append((obstacle_top_rect, obstacle_bottom_rect))


                        def update_obstacles():
                            for i, obstacle_pair in enumerate(obstacles):
                                obstacle_top_rect, obstacle_bottom_rect = obstacle_pair
                                obstacle_top_rect.move_ip(OBSTACLE_VELOCITY, 0)
                                obstacle_bottom_rect.move_ip(OBSTACLE_VELOCITY, 0)
                                if obstacle_top_rect.right < 0:
                                    obstacles.pop(i)


                        def draw_player():
                            player_rect = pygame.Rect(PLAYER_START_X, player_y, PLAYER_SIZE, PLAYER_SIZE)
                            pygame.draw.rect(screen, PLAYER_COLOR, player_rect)

                            # dessiner le sol spécial
                            if time.time() - start_time < 2:
                                special_floor_rect = pygame.Rect(0, SCREEN_HEIGHT - 270, SCREEN_WIDTH, 2)
                                pygame.draw.rect(screen, SPECIAL_FLOOR_COLOR, special_floor_rect)

                            else:
                                special_floor_rect = pygame.Rect(0, SCREEN_HEIGHT - 500, SCREEN_WIDTH, 0)
                                pygame.draw.rect(screen, SPECIAL_FLOOR_COLOR, special_floor_rect)


                        def draw_obstacles():
                            for obstacle_pair in obstacles:
                                obstacle_top_rect, obstacle_bottom_rect = obstacle_pair
                                pygame.draw.rect(screen, OBSTACLE_COLOR, obstacle_top_rect)
                                pygame.draw.rect(screen, OBSTACLE_COLOR, obstacle_bottom_rect)


                        def check_collision():
                            global game_over
                            player_rect = pygame.Rect(PLAYER_START_X, player_y, PLAYER_SIZE, PLAYER_SIZE)
                            for obstacle_pair in obstacles:
                                obstacle_top_rect, obstacle_bottom_rect = obstacle_pair
                                if player_rect.colliderect(obstacle_top_rect) or player_rect.colliderect(
                                        obstacle_bottom_rect):
                                    game_over = True


                        def handle_events():
                            global player_velocity
                            for event in pygame.event.get():
                                if event.type == pygame.QUIT:
                                    pygame.quit()
                                    quit()
                                if event.type == pygame.KEYDOWN:
                                    if event.key == pygame.K_SPACE or pygame.K_UP:
                                        if game_over:
                                            reset_game()
                                        else:
                                            player_velocity = JUMP_VELOCITY


                        def update_player():
                            global player_y, player_velocity, game_over
                            player_y += player_velocity
                            player_velocity += GRAVITY
                            if player_y < 0 or player_y + PLAYER_SIZE > SCREEN_HEIGHT - 100:
                                game_over = True #jeu s'arrete si le joueur est en dehors de l'écran
                            if player_y + PLAYER_SIZE >= SCREEN_HEIGHT - 270 and player_y < SCREEN_HEIGHT - 270 + PLAYER_SIZE:
                                player_y = SCREEN_HEIGHT - 270 - PLAYER_SIZE
                                player_velocity = 0
                            for obstacle_pair in obstacles:
                                obstacle_top_rect, obstacle_bottom_rect = obstacle_pair
                                if obstacle_top_rect.right < PLAYER_START_X and obstacle_top_rect.right + OBSTACLE_VELOCITY >= PLAYER_START_X:
                                    score += 1

                        clock=pygame.time.Clock()

                        # Boucle principale du jeu
                        while True:
                            screen.fill(BACKGROUND_COLOR)
                            FPS = 100
                            clock.tick(FPS)

                            # Gérer les événements
                            handle_events()

                            # maj joueur & obstacles
                            if not game_over:
                                update_player()
                                current_time = time.time()
                                if current_time - obstacle_last_generation_time > OBSTACLE_GENERATION_DELAY:
                                    creer_obstacles()
                                    obstacle_last_generation_time = current_time
                                update_obstacles()
                                check_collision()

                            # Dessiner les éléments du jeu
                            draw_player()
                            draw_obstacles()

                            # Calculer le temps écoulé depuis le début du jeu
                            temps_ecoule = time.time() - start_time

                            # Augmenter le score toutes les 5 secondes de 5
                            if temps_ecoule >= 5:
                                score += 5
                                start_time = time.time()

                            # Afficher le score en haut à droite
                            score_text = font.render(format(score), True, (255, 255, 255))
                            score_rect = score_text.get_rect()
                            score_rect.topright = (SCREEN_WIDTH - 10, 10)
                            screen.blit(score_text, score_rect)

                            pygame.time.Clock().tick(100)
                            pygame.display.update()

                            # Vérifier les collisions
                            if not game_over:
                                check_collision()

                            if game_over:
                                menu_en_cours = True


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

Merci :)

4 réponses

Bonsoir.

Ton ami se trompe ;) Ce qui est affiché à l'écran, c'est toi qui le décide.

Quant à ton problème, ce n'est pas clair.  Tout ce que l'on peut constater est que tu initialises au début de ton code une variable start_time (qui devrait être une constante), puis que tu en changes la valeur dans la boucle de ton jeu.

# Augmenter le score toutes les 5 secondes de 5
    if temps_ecoule >= 5:
        score += 5
        start_time = time.time()

Donc, normal que cette ligne passe de bas en haut et inversement. dans la fonction draw_player.

Mais à quoi sert cette ligne ? Pourquoi ne pas simplement remplir d'une couleur ce qui est en dessous du joueur afin de simuler le sol ?

2

merci de me répondre :))
(xd je lui dirai)

Oui c'est vrai que mon problème n'est pas ce qu'il y a de plus clair. Jvais essayer de le reformuler :

- ma ligne est là au milieu parce que en fait ce 'mini jeu' est la suite d'un autre 'mini jeu'

- en fait l'idée c'est qu'elle serve de transition et que le joueur ne soit pas perdu quand il arrive sur ce jeu (qu'il ait quelques secondes - parce que s'il ne le connait pas, il ne s'y attend pas forcément et dès que ca bascule sur ce jeu, il perd instantanément parce qu'il n'a pas sauté)

- l'idéal serait que ma ligne disparaisse complètement après les 2 secondes (pas simplement qu'elle se camoufle au background)

- la je l'avait faite changer de position parce que je pensait que si tu la baissais ou la montait, elle ne serait plus la, mais en fait si elle est toujours la dasn la version actuelle. Ce que je veux dire c'est que y en a une autre, mais y a toujours l'originale qui est camouflée au bg, donc ca ne va pas

J'avais effectivement penser a faire un sol, mais nan en fait l'idéal serait vraiment d'avoir une sorte de ligne

Tu saurais comment on pourrait modifier ça ?

0

Salut.

Comme je t'ai signalé, tu utilises une même variable pour faire 2 choses sans rapport (affichage d'un élément,  mise à jour d'un score), c'est ça qui ne va pas.

D'abord supprimer cette variable start_game et la remplacer par 2 disctinctes, comme :

score_time = time.time()
game_start_time = time.time()

Puis :

def draw_player():
    player_rect = pygame.Rect(PLAYER_START_X, player_y, PLAYER_SIZE, PLAYER_SIZE)
    pygame.draw.rect(screen, PLAYER_COLOR, player_rect)

    # dessiner le sol spécial
    # print(time.time() - start_time)
    if time.time() - game_start_time < 2:
        special_floor_rect = pygame.Rect(0, SCREEN_HEIGHT - 270, SCREEN_WIDTH, 2)
        pygame.draw.rect(screen, SPECIAL_FLOOR_COLOR, special_floor_rect)

Plus besoin du else.


Ensuite, si nécessaire la réinitialiser lors du redémarrage :

def reset_game():
    global ..., game_start_time
    # ...
    game_start_time = time.time()

Ne reste plus que ce qu'il y a dans la boucle :

# Calculer le temps écoulé depuis le début du jeu
temps_ecoule = time.time() - score_time

# Augmenter le score toutes les 5 secondes de 5
if temps_ecoule >= 5:
    score += 5
    score_time = time.time()

Et voilà, en utilisant 2 variables, plus de problème d'interférence.

0

merci :)

j'ai modifié le code, c'est plus clair

merci :)))

0

Je m'ennuie, alors j'ai refais à peu de choses près ce que fait ton code en reprenant quelques petites parties de ton code.

En utilisant des sprites, groupes de sprites et surtout des timers qui servent à créer des événements utilisateurs, ça permet de simplifier certaines choses, notamment comme pour ne plus afficher le sol.

import pygame as pg
import math
import random

FPS = 60
GRAVITY = 0.3
GAME_RESTART_EVENT = pg.USEREVENT
GAME_RESTART_DELAY = 1500

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
SCREEN_COLOR = pg.Color(255, 90, 180, 255)

PLAYER_SIZE = 32
PLAYER_BG_COLOR = pg.Color('yellow')
PLAYER_FG_COLOR = pg.Color('red')
PLAYER_EDGE_COLOR = pg.Color('yellowgreen')
PLAYER_VELOCITY = 8

GROUND_HEIGHT = 250
GROUND_COLOR = pg.Color(34, 139, 34, 0)
GROUND_HIDE_DELAY = 3000
GROUND_HIDE_EVENT = pg.USEREVENT + 1

OBSTACLE_COLORS = pg.Color(70, 130, 180, 0), pg.Color(72, 61, 139, 0)
OBSTACLE_WIDTH = 50
OBSTACLE_DELTAS = 150, 200
OBSTACLE_SPAWN_DELAYS = 1000, 1800
OBSTACLE_VELOCITY = 5
OBSTACLE_EVENT = pg.USEREVENT + 2

SCORE_COLOR = pg.Color(178, 34, 34, 0)


class Obstacle(pg.sprite.Sprite):
    def __init__(self, y, y2):
        super().__init__()
        self.image = pg.Surface((OBSTACLE_WIDTH, y2 - y)).convert()
        self.rect = self.image.get_rect()
        self.rect.topleft = SCREEN_WIDTH, y
        self.image.fill(OBSTACLE_COLORS[0])
        pg.draw.line(
            self.image, OBSTACLE_COLORS[1], (0, 0), (0, self.rect.h), 3
        )
        pg.draw.line(
            self.image,
            OBSTACLE_COLORS[1],
            (self.rect.w - 2, 0),
            (self.rect.w - 2, self.rect.h),
            3,
        )

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


class ObstacleTop(Obstacle):
    def __init__(self, y, y2):
        super().__init__(y, y2)
        pg.draw.rect(
            self.image,
            OBSTACLE_COLORS[1],
            (0, self.rect.bottom - 20, self.rect.w, 20),
        )


class ObstacleBottom(Obstacle):
    def __init__(self, y, y2):
        super().__init__(y, y2)
        pg.draw.rect(self.image, OBSTACLE_COLORS[1], (0, 0, self.rect.w, 20))


class Ground(pg.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pg.Surface((SCREEN_WIDTH, GROUND_HEIGHT)).convert()
        self.image.fill(SCREEN_COLOR)
        self.rect = self.image.get_rect()
        self.rect.top = SCREEN_HEIGHT - GROUND_HEIGHT
        pg.draw.rect(self.image, GROUND_COLOR, (0, 0, self.rect.w, 2))


class Player(pg.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pg.Surface((PLAYER_SIZE,) * 2, pg.SRCALPHA).convert_alpha()
        self.rect = self.image.get_rect()
        wm = int(self.rect.w / 2)
        wt = int(self.rect.w / 3)
        pg.draw.circle(self.image, PLAYER_BG_COLOR, (wm, wm), wm, wm - 1)
        pg.draw.circle(self.image, PLAYER_EDGE_COLOR, (wm, wm), wm, 2)
        pg.draw.circle(self.image, PLAYER_FG_COLOR, (wt, wt), 2)
        pg.draw.circle(
            self.image, PLAYER_FG_COLOR, (int(self.rect.w / 3 * 2), wt), 2
        )
        pg.draw.arc(
            self.image,
            PLAYER_FG_COLOR,
            self.rect.inflate(-wm, -wt),
            math.radians(220),
            math.radians(-40),
            2,
        )
        self.rect.bottomleft = x, y
        self.ground_top = y
        self._move = False
        self.jumping = False

    def update(self):
        if self.jumping:
            self.rect.y -= self.velocity
            self.velocity -= GRAVITY
            if self.rect.bottom > self.ground_top:
                self.jumping = False
                self.rect.bottom = self.ground_top
            elif self.rect.top < 0:
                self.rect.top = 0

    def jump(self):
        if self._move:
            self.jumping = True
            self.velocity = PLAYER_VELOCITY

    move = property(
        lambda self: self._move, lambda self, b: setattr(self, '_move', b)
    )


class Score(pg.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.x = x
        self.y = y
        self.score = 0
        self.font = pg.font.SysFont('serif', 42, True)
        self.set_image()

    def set_image(self):
        self.image = self.font.render(
            str(self.score),
            True,
            SCORE_COLOR
        ).convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.topright = self.x, self.y

    def increase(self):
        self.score += 1
        self.set_image()

    def reset(self):
        self.score = 0
        self.set_image()


class Obstacles:
    def __init__(self, *groups, kill_callback):
        self.groups = groups
        self.kill_callback = kill_callback

    def spawn(self):
        y, y2 = self.get_random_pos()
        obstacles = (ObstacleTop(0, y), ObstacleBottom(y2, SCREEN_HEIGHT))
        for sprite in obstacles:
            sprite.add(self.groups)

    def get_random_pos(self):
        y_center = random.randint(GROUND_HEIGHT - 125, GROUND_HEIGHT - 50)
        y_delta = random.randint(*OBSTACLE_DELTAS) / 2
        return y_center - y_delta, y_center + y_delta

    def set_timer(self, ms=-1):
        if ms == -1:
            ms = random.randrange(*OBSTACLE_SPAWN_DELAYS)
        pg.time.set_timer(OBSTACLE_EVENT, ms)

    def update(self):
        killed = False
        for sprite in self.groups[1].copy().sprites():
            if isinstance(sprite, Obstacle) and sprite.rect.right < 0:
                sprite.kill()
                killed = True
        if killed:
            self.kill_callback()


class Game:
    def __init__(self):
        pg.init()
        self.screen = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        self.screen.convert()
        self.screen.fill(SCREEN_COLOR)
        pg.display.update()
        self.display_group = pg.sprite.LayeredUpdates()
        self.obstacles_group = pg.sprite.Group()

        self.ground = Ground()
        self.player = Player(50, self.ground.rect.top)
        self.player.move = True
        self.score = Score(SCREEN_WIDTH - 10, 10)
        self.display_group.add(self.ground, self.player, self.score)

        self.obstacles = Obstacles(
            self.display_group,
            self.obstacles_group,
            kill_callback=self.score.increase,
        )
        self.obstacles.set_timer()
        pg.time.set_timer(GROUND_HIDE_EVENT, GROUND_HIDE_DELAY)

    def stop(self):
        self.player.move = False
        self.obstacles.set_timer(0)
        pg.sprite.groupcollide(
            self.display_group, self.obstacles_group, False, True
        )
        pg.time.set_timer(GAME_RESTART_EVENT, GAME_RESTART_DELAY)

    def restart(self):
        pg.time.set_timer(GAME_RESTART_EVENT, 0)
        pg.time.set_timer(GROUND_HIDE_EVENT, GROUND_HIDE_DELAY)
        self.display_group.add(self.ground)
        self.score.reset()
        self.obstacles.set_timer()
        self.player.move = True

    def _clear(self, surf, rect):
        surf.fill(SCREEN_COLOR, rect)

    def run(self):
        clock = pg.time.Clock()
        running = True
        while running:
            for evt in pg.event.get():
                if evt.type == pg.QUIT:
                    running = False
                elif evt.type == OBSTACLE_EVENT:
                    self.obstacles.spawn()
                    self.obstacles.set_timer()
                elif evt.type == pg.KEYDOWN:
                    if evt.key == pg.K_SPACE or pg.K_UP:
                        self.player.jump()
                elif evt.type == GAME_RESTART_EVENT:
                    self.restart()
                elif evt.type == GROUND_HIDE_EVENT:
                    self.display_group.remove(self.ground)
                    pg.time.set_timer(GROUND_HIDE_EVENT, 0)
            self.obstacles.update()
            self.display_group.update()
            if pg.sprite.spritecollide(
                self.player, self.obstacles_group, False
            ):
                self.stop()
            self.display_group.clear(self.screen, self._clear)
            rects = self.display_group.draw(self.screen)
            pg.display.update(rects)
            clock.tick(FPS)

        pg.quit()


game = Game()
game.run()

Bon, c'est de l'objet, et je ne suis pas certain que tu sois bien à l'aise avec, mais ça peut te donner des idées afin d'améliorer ton code.

Le système de points est différent, le score est augmenté à chaque obstacles franchis.

0

xd merci. J'aime bien l'idée du smiley

merci bcp !!

0