Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pygame lent ?

    23 juillet 2021 à 18:28:37

    Bonjour,

    j'ai effectué ce code :

    import pygame
    import os
    import random
    
    def center(surface, ecran):
        centerScreenX = ecran.get_width()/2
        centerScreenY = ecran.get_height()/2
        centerSurfaceX = surface.get_width()/2
        centerSurfaceY = surface.get_height()/2
    
        ecran.blit(surface, (centerScreenX - centerSurfaceX, centerScreenY - centerSurfaceY))
        pygame.display.flip()
    
    def printMainMenu(ecran, surfaces_menu, rects_menu):
        for surface in range(len(surfaces_menu)):
            if rects_menu[surface] == "center":
                center(surfaces_menu[surface], ecran)
            else:
                ecran.blit(surfaces_menu[surface], rects_menu[surface])
                pygame.display.flip()
    
    
    pygame.font.init()
    
    class Texte:
        def __init__(self, pathToFont, size, texte, color):
            self.font = pygame.font.Font(pathToFont, size)
            self.text = self.font.render(texte, True, color)
            self.__h = self.text.get_height()
            self.__w = self.text.get_width()
            self.__x = self.text.get_rect()[0]
            self.__y = self.text.get_rect()[1]
    
        def display(self, ecran, rect):
            ecran.blit(self.text, rect)
            pygame.display.flip()
    
        def get_height(self):
            return self.__h
        def get_width(self):
            return self.__w
        def get_abscisse(self):
            return self.__x
        def get_ordonnee(self):
            return self.__y
    
    
    class Cartes:
        def __init__(self):
            self.listcategorie = []               #liste des cartes appartenant à une catégorie
            self.selection = []             #liste des cartes sélectionnées aléatoirement parmi la première la liste
        
        def extract_cards(self, filepath):
            fichier = open(filepath)
            line = 'c'
            while line != '':     #= tant qu'on a pas ateint la fin du fichier
                line = fichier.readline()
                line = line.replace('\n','')
                self.listcategorie.append(line)   
    
        def select_cards(self, nbcartes):                   #nbcartes = le nombre de cartes qui seront sélectionnées pour la catégorie concernée (calculé au préalable)        
            for i in range(nbcartes):
                index = random.randint(len(self.listcategorie))
                self.selection.append(self.listcategorie[index])
                self.listcategorie.pop(index)
    
    
    
    #definition of colors
    white = (255,255,255)
    black = (0,0,0)
    red = (255,0,0)
    green = (0,255,0)
    blue = (0,0,255)
    yellow = (255,255,0)
    light_blue = (40,130,255)
    
    
    ecran = pygame.display.set_mode((0,0))
    ecran.fill(light_blue)
    width_ecran = ecran.get_width()
    height_ecran = ecran.get_height()
    
    #initialisation images boutons et affichage
    bouton_play = pygame.image.load("button_play.png")
    bouton_play_selected = pygame.image.load("selected_play.png")
    bouton_quit = pygame.image.load("button_quit.png")
    bouton_quit_selected = pygame.image.load("selected_quit.png")
    center(bouton_play,ecran)
    
    title_game = Texte("Royalacid.ttf", 75, "Time's Up", yellow)
    title_game.display(ecran, (width_ecran/2 - title_game.get_width()/2 , height_ecran/12 - title_game.get_height()/2))
    play_text = Texte("Classic_title.ttf", 65, "PLAY", yellow)
    play_text.display(ecran, (width_ecran/2 - play_text.get_width()/2 , height_ecran/3.5 - play_text.get_height()/2))
    
    surfaces_menu = [bouton_play,bouton_quit,title_game.text,play_text.text]
    rects_menu = ["center",(width_ecran/2 - bouton_quit.get_width()/2, height_ecran/1.20 - bouton_quit.get_height()), (width_ecran/2 - title_game.get_width()/2 , height_ecran/12 - title_game.get_height()/2), (width_ecran/2 - play_text.get_width()/2 , height_ecran/3.5 - play_text.get_height()/2)]
    #initial display
    printMainMenu(ecran, surfaces_menu, rects_menu)
    
    continuer = True    #booléen qui maintien le programme
    start = False       #booléen qui lance le jeu
    play = False        #booléen qui détecte si la souris est sur le bouton play
    quit = False        #booléen qui détecte si la souris est sur le bouton quit
    while continuer:
        surfaces_menu = [title_game.text,play_text.text]
        rects_menu = [(width_ecran/2 - title_game.get_width()/2 , height_ecran/12 - title_game.get_height()/2), (width_ecran/2 - play_text.get_width()/2 , height_ecran/3.5 - play_text.get_height()/2)]
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                continuer = False
    
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_q:
                    continuer = False 
    
            if event.type == pygame.MOUSEMOTION:   
                play_rect = bouton_play.get_rect()
                play_rect[0] = width_ecran/2 - bouton_play.get_width()/2
                play_rect[1] = height_ecran/2 - bouton_play.get_height()/2         
                if play_rect.collidepoint(event.pos[0], event.pos[1]):
                    play = True
                    surfaces_menu.append(bouton_play_selected)
                    centered_button = (width_ecran/2 - bouton_play_selected.get_width()/2 , height_ecran/2 - bouton_play_selected.get_height()/2)
                    rects_menu.append(centered_button)
                #elif 
                else:
                    play=False
                    surfaces_menu.append(bouton_play)
                    rects_menu.append("center")
                    surfaces_menu.append(bouton_quit)
                    rects_menu.append((width_ecran/2 - bouton_quit.get_width()/2, height_ecran/1.20 - bouton_quit.get_height()))
    
        printMainMenu(ecran, surfaces_menu, rects_menu)

    (bonne lecture...)

    il n'est pas encore fini, mais j'ai un blocage : au moment ou la souris passe sur le bouton play, ce qui est censé le "sélectionner", et le faire passer en gris (l.134-142), ça marche, mais il met longtemps à afficher la version grise du bouton play.

    j'ai pensé à l'optimisation donc j'ai utilisé la technique du "profiling" comme elle été appelée sur le site où je me suis renseigné, tout ça pour savoir qu'aucune fonction ne ralentissait vraiment le process...

    donc, je suis dépassé, et j'ai besoin d'aide.

    quelqu'un aurait-il une solution ???

    • Partager sur Facebook
    • Partager sur Twitter
      23 juillet 2021 à 18:50:57

      Je me demande si tu n'accumules pas trop de surfaces (lignes 122, 128), puisque sauf erreur de ma part, à chaque mouvement de souris, tu va ajouter soit bouton_play soit bouton_play_selected.
      peut-être traiter la variable play en dehors de la boucle des évènements

      Et tu oublie de fermer le fichier dans extract_cards (il y a un open mais pas de close)

      -
      Edité par umfred 23 juillet 2021 à 18:51:50

      • Partager sur Facebook
      • Partager sur Twitter
        23 juillet 2021 à 21:51:30

        Mais pourquoi les gens s'obstinent à tout mettre dans une seule boucle événementielle ? Je renonce à aider sur pygame, je laisse umfred s'en charger il est bien plus patient ...

        Bon un dernier pour la route. Si t'as qu'un seul bouton à gérer et qu'il n'y a rien d'autre à faire qu'attendre le clic dessus, tu crées une fonction dédiée, même bloquante osef, qui retourne une action. Genre 0 le bouton est cliqué, 1 l'utilisateur a appuyez sur 'q', 2 l'utilisateur a fermé la fenêtre, etc ... La fonction aura sa propre boucle événementielle. C'est plus claire et plus facile à intégrer.

        • Partager sur Facebook
        • Partager sur Twitter

        "il vaut mieux vivre en France qu'en Italie, la France a de plus jolies prisons"

          23 juillet 2021 à 23:58:31

          josmiley a écrit:

          Mais pourquoi les gens s'obstinent à tout mettre dans une seule boucle événementielle ? Je renonce à aider sur pygame, je laisse umfred s'en charger il est bien plus patient ...

          Bon un dernier pour la route. Si t'as qu'un seul bouton à gérer et qu'il n'y a rien d'autre à faire qu'attendre le clic dessus, tu crées une fonction dédiée, même bloquante osef, qui retourne une action. Genre 0 le bouton est cliqué, 1 l'utilisateur a appuyez sur 'q', 2 l'utilisateur a fermé la fenêtre, etc ... La fonction aura sa propre boucle événementielle. C'est plus claire et plus facile à intégrer.

          j'y ai pensé mais le bouton play sera pas le seul à gérer, y'aura aussi le bouton quit....

          umfred a écrit:

          Je me demande si tu n'accumules pas trop de surfaces (lignes 122, 128), puisque sauf erreur de ma part, à chaque mouvement de souris, tu va ajouter soit bouton_play soit bouton_play_selected.
          peut-être traiter la variable play en dehors de la boucle des évènements

          Et tu oublie de fermer le fichier dans extract_cards (il y a un open mais pas de close)

          -
          Edité par umfred il y a environ 4 heures

          j'ai supprimé les lignes 125 et 126, j'ai remplacé les ligne 139-141 par
          surfaces_menu[0] = bouton_play_selected  

          et les lignes 143-146 par

          surfaces_menu[0] = bouton_play

          ça passe ?

          PS : après test, la fluidité du passage non selectionné --> selectionné  a l'air assez aléatoire...

          -
          Edité par alexpatt 24 juillet 2021 à 0:00:13

          • Partager sur Facebook
          • Partager sur Twitter
            24 juillet 2021 à 2:16:01

            Un tuto provenant du site de Pygame : https://www.patternsgameprog.com/series/discover-python-and-patterns/ (EN)

            Je comprends Jos qui fait allusion à Hugo dans son coup de gueule.

            Je suis en train de suivre le lien que je propose. Il est tard, je suis un peu fatigué, mais je vais essayer d'avancer. J'aime beaucoup ces tutos qui parlent des design patterns.

            -
            Edité par CristianoRolando 24 juillet 2021 à 2:25:26

            • Partager sur Facebook
            • Partager sur Twitter
              24 juillet 2021 à 13:38:57

              josmiley a écrit:

              Mais pourquoi les gens s'obstinent à tout mettre dans une seule boucle événementielle ? Je renonce à aider sur pygame, je laisse umfred s'en charger il est bien plus patient ...


              Mais du coup il faut faire du multithreading ? Nan ? Je vois pas trop l'intérêt à première vue. Je dois mal comprendre.
              • Partager sur Facebook
              • Partager sur Twitter

              https://www.youtube.com/watch?v=Dv6Th7kJ64Q

                24 juillet 2021 à 20:40:29

                CristianoRolando a écrit:

                Un tuto provenant du site de Pygame : https://www.patternsgameprog.com/series/discover-python-and-patterns/ (EN)

                Je comprends Jos qui fait allusion à Hugo dans son coup de gueule.

                Je suis en train de suivre le lien que je propose. Il est tard, je suis un peu fatigué, mais je vais essayer d'avancer. J'aime beaucoup ces tutos qui parlent des design patterns.

                -
                Edité par CristianoRolando il y a environ 18 heures

                hehe je sais pas trop où chercher sur ce tuto ÉNORME y a pas une section où je pourrait directement aller et voir la partie susceptible de résoudre mon problème ?

                animation peut-etre...?

                • Partager sur Facebook
                • Partager sur Twitter
                  24 juillet 2021 à 20:54:17

                  Dans le tuto, je ne sais plus à quelle page. Il dit clairement que pygame n'est pas optimisé du tout. Il faut parfois revoir à la baisse ses objectifs.

                  Pour info, la méthode update peut contenir une liste de rectangles. Ça ne met à jour que les rectangles que tu souhaites.

                  Si j'y pense, je te ponds un exemple simple. Je dois travailler l'algo, j'ai juste l'idée en tête. Mais, plus tard, j'ai faim !

                  Voilà, c'est peut-être pas parfait, il n'y a pas d'image non plus. Mais, comme les CPU sont ultra rapides avec les booléens, j'en ai utilisés :

                  import pygame as pg
                  
                  """
                  Modifier couleur d'un rectangle lorsqu'on passe la souris dessus
                  """
                  
                  
                  pg.init()
                  clock = pg.time.Clock()
                  fps = 60
                  width = 640
                  height = 480
                  red = pg.Color(255,0,0)
                  fill_color = pg.Color(128,128,128)
                  blue = pg.Color(0,0,255)
                  white = pg.Color(255,255,255)
                  black = pg.Color(0,0,0)
                  out = True
                  window = pg.display.set_mode((width,height))
                  
                  running = True
                  
                  blue_rectangle = pg.draw.rect(window, (blue), (50, 400, 150, 50))
                  white_rectangle = pg.draw.rect(window, (white), (250, 400, 150, 50))
                  red_rectangle = pg.draw.rect(window, (red), (450, 400, 150, 50))
                  blue_to_black = white_to_black = red_to_black = False
                  
                  rectangles = [blue_rectangle, white_rectangle, red_rectangle]
                  window.fill(fill_color)
                  
                  pg.display.update()
                  
                  while running:
                    for event in pg.event.get():
                      if event.type == pg.QUIT:
                        running = False
                      elif event.type == pg.MOUSEMOTION:
                        x, y = event.pos
                        if blue_rectangle.collidepoint(x,y):
                          blue_to_black = True
                        elif white_rectangle.collidepoint(x,y):
                          white_to_black = True
                        elif red_rectangle.collidepoint(x,y):
                         red_to_black = True
                        else:
                          blue_to_black = False
                          white_to_black = False
                          red_to_black = False
                  
                    window.fill(fill_color)
                    if blue_to_black:
                      window.fill(black, blue_rectangle)
                      pg.display.update(blue_rectangle)
                    elif white_to_black:
                      window.fill(black, white_rectangle)
                      pg.display.update(white_rectangle)
                    elif red_to_black:
                      window.fill(black, red_rectangle)
                      pg.display.update(red_rectangle)
                    else:
                      window.fill(blue, blue_rectangle)
                      window.fill(white, white_rectangle)
                      window.fill(red, red_rectangle)
                      pg.display.update(rectangles)
                  
                    clock.tick(fps)
                  
                  pg.quit()



                  -
                  Edité par CristianoRolando 24 juillet 2021 à 22:09:49

                  • Partager sur Facebook
                  • Partager sur Twitter
                    25 juillet 2021 à 12:01:18

                    j'ai lu ton code, et j'ai remarqué qu'à la ligne 66 ça parlait de fps...

                    je ne sais pas comment ça marche mais j'ai du coup rajouté les lignes 9 et 66à mon programme et ça marche....

                    j'en profite donc pour poser une autre question : le bouton play sur lequel la souris passe pour le "sélectionner" est plutot ovale. sauf qu'une surface est forcément carrée, donc quand la souris passe dans un coin de la surface, qui n'est pas vraiment le bouton, ça le sélectionne quand meme. quelqu'un connait un moyen de résoudre ça ??

                    -
                    Edité par alexpatt 25 juillet 2021 à 12:11:33

                    • Partager sur Facebook
                    • Partager sur Twitter
                      25 juillet 2021 à 19:17:51

                      Dans un vieux tuto pygame qui était référencé sur le site officiel. L'auteur dit qu'il vaut mieux éviter les collisions parfaites. Donc pour ton bouton ovale, j'ai entendu parler des dirty rects mais je ne sais pas à quoi ils servent. C'est compliqué à expliqué textuellement, mais, renseigne-toi dessus.

                      Sinon, tu gères la collision dans le rectangle inscrit dans l'ovale.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        26 juillet 2021 à 15:20:49

                        @alexpatt, quand tu parles de lignes 139-141, j'ai du mal à voir de quelles lignes il s'agit. Dans le code que l'on voit on ne va que jusqu'à 133 :p
                        • Partager sur Facebook
                        • Partager sur Twitter

                        Pygame lent ?

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        • Editeur
                        • Markdown