Partage
  • Partager sur Facebook
  • Partager sur Twitter

[résolu]Programme avec un compte à rebours en prallèle

besoin d'aide

    6 mai 2011 à 19:15:11

    Salut à tous, je suis entrain de faire un jeu de labyrinthe et pour "pimenter" un peu le tout, j'aimerai qu'il y ai un temps impartis. Pour cela, je voudrais faire un compte à rebours, le problème, c'est que pour l'instant je ne suis arrivé qu'à lancer le jeu une fois que le temps était à 0 (code utilisé):

    def timer(length, dt=1):  
        end = time.time() + length  
        while(time.time() < end):  
            print(int((end - time.time())))  
            time.sleep(dt)  
        print("Time's up!")
    


    Mais ce que je veux c'est qu'on puisse jouer pendant que le temps diminue...

    Un autre idée serait de faire incrémenter une variable dans ma boucle principale et une fois arrivée à un certain nombre, faire baisser le temps d'une unité et remettre la variable à 0, mais c'est pas très précis... Est-ce la seule solution ?

    A+

    [EDIT] Je m’aperçois que ma seconde solution fonctionne a merveille et qu'elle remplit parfaitement sa fonction. Si vous pensez avoir quelque chose de mieux à me proposer, je suis toujours preneur, mais sachez que je ne suis plus bloqué par ce problème. A+
    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      6 mai 2011 à 19:33:09

      avec les threads peut-être
      • Partager sur Facebook
      • Partager sur Twitter
        6 mai 2011 à 19:38:57

        Je sais pas ce que sont les threads (enfin, très vaguement), mais je viens d'éditer mon message précédent. Merci quand même pour ta piste ;)
        • Partager sur Facebook
        • Partager sur Twitter
          6 mai 2011 à 20:11:17

          Bonjour,

          Les threads ça me semble overkill. Au mieux il y a les timers.

          Au cas ou : ta seconde solution ne fonctionne qu'à partir du moment ou tu régules le nombre de FPS. Sans ça, le temps passera plus vite sur un ordinateur plus rapide et plus lentement sur un ordinateur plus modeste.
          Elle permet aussi de mettre simplement d'arréter le décompte du temps si le jeu est en pause. Avec les timers je pense qu'il faudrait les inclure dans une classe pour gérer ça.

          Tu utilises une bibliothèques sans doute, elle ne propose pas déjà des outils pour ça ?

          Sinon, si tu connais les classes en Python, reste à en créer une petite qui fait le boulot.

          Genre :
          class Decompte(object):
              def __init__(self, duree):
                  pass
          
              def start(self):
                  pass    
          
              def temps_restant(self):
                  pass
          
              def pause():
                  pass
          


          À l'utilisation ça pourrait donner quelque chose comme :

          decompte = Decompte(30)
          
          done = False
          decompte.start()
          while not done:
              for e in events:
                  if e.type == QUIT:
                      done = True
          
                  elif e.type == SPACE:
                      decompte.pause()
          
              temps = decompte.temps_restant()
              if temps:
                  print 'temps restant : %d' : temps
              else:
                  print 'temps écoulé ! Try again hahaha'
                  done = True
          
          • Partager sur Facebook
          • Partager sur Twitter
            6 mai 2011 à 22:38:14

            Merci pour la réponse mais j'ai quelques difficultés à voir comment ça marche, surtout avec des "pass" partout ^^.

            En ce qui concerne le support, le jeu est destiné à une petite console portable, et bien qu'elle soit overlockable, je pense que le temps sera le même un peut partout.
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              6 mai 2011 à 23:21:13

              Citation

              Les threads ça me semble overkill



              C'est fort possible en effet.

              Dans son cas l'utilisation du module time me semble être la meilleure solution.

              • Partager sur Facebook
              • Partager sur Twitter
                6 mai 2011 à 23:27:20

                Citation : Monstercrunch

                Merci pour la réponse mais j'ai quelques difficultés à voir comment ça marche, surtout avec des "pass" partout ^^.

                En ce qui concerne le support, le jeu est destiné à une petite console portable, et bien qu'elle soit overlockable, je pense que le temps sera le même un peut partout.



                Les pass sont là pour dire que les méthodes de la classe restent à implémenter.

                Du reste, ne trouves-tu pas dommage de coder un jeu en python qui est par nature un langage extrêmement portable et de le cibler uniquement pour un seul type d'architecture en sortie ?
                Plus exactement, ce que je veux dire par là, c'est que python incorpore en standard des modules pour mesurer le temps (time, notamment), indépendamment de la plate-forme cliente. Ce serait quand même dommage de s'en passer alors que tu as la possibilité d'une solution propre, non ?
                • Partager sur Facebook
                • Partager sur Twitter
                Zeste de Savoir, le site qui en a dans le citron !
                  7 mai 2011 à 2:46:51

                  Va pour la solution time :) , mais je vois pas comment procéder: le code que j'ai utilisé plus haut faisait le décompte PUIS lançais le jeu. Chose que j'ai oublié de préciser, je suis débutant en python, de plus, je n'ai presque jamais touché au module time.

                  Je vais donc jeter un coup d’œil à la doc.

                  A+
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    7 mai 2011 à 10:19:43

                    from time import time, sleep
                    
                    start = time()
                    while time() - start < 10:
                        print "bonjour"
                        sleep(1)
                    
                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 mai 2011 à 20:23:50

                      avec sleep, tout le programme n'est-il pas mis en pause ?
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        7 mai 2011 à 22:41:11

                        d'où le problème des threads qui rentrent en ligne de compte.

                        Quand on veut travailler 2 choses à la fois, il faut passer aux threads

                        Mais bon tu peux mettre 0.1 au lieu de 1 pour ton sleep :)
                        • Partager sur Facebook
                        • Partager sur Twitter
                          7 mai 2011 à 23:32:45

                          Le truc c'est qu'ici il n'est pas question de faire deux choses à la fois, tout est faisable séquentiellement... et tant mieux, quand on peut se passer des thread, on s'en passe.
                          Le sleep() ne sera pas présent dans la boucle principale de ton jeu, dans le code de Fred c'est juste un artifice nécessaire pour ne pas avoir 10000 "bonjour" qui s'affiche en 10s.

                          Dans ton jeu, le sleep() correspond en fait au traitement des évènements + temps de rendu + temps à ajouter pour réguler les FPS.
                          Un code testable avec pygame :

                          import pygame as pg
                          from time import time
                          
                          pg.display.init()
                          
                          screen = pg.display.set_mode((400,225))
                          fin_jeu = False
                          start = time()
                          duree_max = 10
                          
                          while not fin_jeu:
                              # traitement evenements
                              for ev in pg.event.get():
                                  if ev.type == pg.QUIT:
                                      fin_jeu = True
                          
                              # mise a jour du compteur
                              temps_ecoule = time() - start
                              if temps_ecoule > duree_max:
                                  fin_jeu = True
                          
                              # rendu
                              if temps_ecoule < duree_max:
                                  print 'reste : %ds' % int(time() - start)
                              else:
                                  print 'fin du temps !'
                          


                          Rien n'est bloquant, pas besoin de thread.
                          C'est presque le même code que j'ai posté plus haut mais sans classe... c'est moins classe.
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            7 mai 2011 à 23:47:12

                            Le problème, c'est l'utilisation du CPU. Pas top.

                            Du coup, créer un thread pour gérer le temps pendant que le principale s'occupe des évènements et de l'affichage ne serait peut-être pas tant overkill que ça, non ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                              8 mai 2011 à 0:01:08

                              hm Je ne vois pas en quoi la création d'un thread soulagerait le CPU : la boucle évènement + affichage tournerait toujours à fond elle.
                              C'est donc de toute manière dans celle-ci qu'il faut réguler le nombre de FPS (vérifier combien de temps à pris l'exécution de la boucle, si inférieur à 1/fps, sleep(1/fps - temps_ecoule)

                              Par contre un timer pourquoi pas oui (mais ça serait juste une autre façon de faire et n'éviterait pas de limiter ces foutues FPS ^^ )
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                8 mai 2011 à 0:06:36

                                Oui d'où ma solution avec un sleep << à 1, cependant le PO parle d'un travail parallèle, si si :) et dans ce cas, c'est du thread qui nous intéresse, en tout cas c'est pas très complexe, j'ai jamais touché au module threading et je fais un petit code tout simple mais qui fonctionne.

                                import threading as th
                                from time import time, sleep
                                
                                def countdown():
                                    count = 0
                                    start = time()
                                    while time() - start < 10:
                                        count += 1
                                        print count
                                        sleep(1)
                                
                                def affichage():
                                    count = 1
                                    while count < 10:
                                        print "bonjour"
                                        count += 1
                                        sleep(1)
                                
                                th_1 = th.Thread(None, countdown, None)
                                th_2 = th.Thread(None, affichage, None)
                                
                                th_1.start()
                                th_2.start()
                                
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  8 mai 2011 à 0:19:11

                                  Citation : fred1599

                                  [...] cependant le PO parle d'un travail parallèle, si si :) [...]



                                  Il faudrait vraiment que tu m'expliques où Fred ^^
                                  Sa seconde solution est purement séquentielle et il dit que ça lui va très bien :

                                  Citation : Monstercrunch

                                  Un autre idée serait de faire incrémenter une variable dans ma boucle principale et une fois arrivée à un certain nombre, faire baisser le temps d'une unité et remettre la variable à 0, mais c'est pas très précis... Est-ce la seule solution ?

                                  A+

                                  [EDIT] Je m’aperçois que ma seconde solution fonctionne a merveille et qu'elle remplit parfaitement sa fonction. Si vous pensez avoir quelque chose de mieux à me proposer, je suis toujours preneur, mais sachez que je ne suis plus bloqué par ce problème. A+



                                  Si c'est cette phrase qui te convainc de ça : « Mais ce que je veux c'est qu'on puisse jouer pendant que le temps diminue... », le but c'est que ce soit de cette façon que le joueur le ressente, mais à l'implémentation ça se fait très bien de calculer séquentiellement tout à chaque frame.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Anonyme
                                    8 mai 2011 à 0:21:19

                                    J'ai juste vu ça dans le titre :)

                                    Ne connaissant pas les threads, il ne pouvait se douter de la solution.

                                    Enfin bref plusieurs solutions lui sont données, tant mieux ;)
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      8 mai 2011 à 1:11:32

                                      Citation : Grinwik

                                      hm Je ne vois pas en quoi la création d'un thread soulagerait le CPU : la boucle évènement + affichage tournerait toujours à fond elle.
                                      C'est donc de toute manière dans celle-ci qu'il faut réguler le nombre de FPS (vérifier combien de temps à pris l'exécution de la boucle, si inférieur à 1/fps, sleep(1/fps - temps_ecoule)

                                      Par contre un timer pourquoi pas oui (mais ça serait juste une autre façon de faire et n'éviterait pas de limiter ces foutues FPS ^^ )



                                      Si on cherche à avoir un grand nombre de FPS alors effectivement ce n'est pas très utile. Mais dans le cas d'un petit jeu style tetris, bomberman ou autres, le rafraichissement de l'écran n'a lieu que lors d'un évènement (input, bot, time, etc.), ainsi en plaçant la gestion de ces évènements dans des threads à part, le rôle du thread principal sera simplement de blitter à chaque évènement.

                                      Au passage, les Timers sont des threads qui se lancent après un temps donné.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        8 mai 2011 à 1:50:53

                                        Citation : PsycoPy

                                        Si on cherche à avoir un grand nombre de FPS alors effectivement ce n'est pas très utile. Mais dans le cas d'un petit jeu style tetris, bomberman ou autres, le rafraichissement de l'écran n'a lieu que lors d'un évènement (input, bot, time, etc.), ainsi en plaçant la gestion de ces évènements dans des threads à part, le rôle du thread principal sera simplement de blitter à chaque évènement.



                                        Quelque soit le nombre de FPS souhaité, je suis septique quand au fait qu'une solution à base de thread soit globalement plus économe qu'une solution séquentielle.
                                        Dans la solution que tu proposes, chaque évènement engendrerait un rendu c'est bien ça ? Dans la solution séquentielle, on traite d'abord tous les évènements et ensuite on fait un seul rendu pour la frame. Du coup, je pense que tu es gagnant (et encore de peu je pense) quand il y a vraiment peu d'évènement, c'est à dire plus jeux de plateau basique ou jeux de cartes que Tetris et bonberman.

                                        Un autre problème mais peut-être est-ce particulier à Pygame : avec cette lib on ne peut gérer l'affichage et les évènements que dans le thread principal.

                                        Si jamais tu as un exemple sous le coude (« in code we trust »), n'hésites pas en tout cas :)
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Anonyme
                                          8 mai 2011 à 2:39:15

                                          En faite, je ne sais pas pour ce qui est de pygame et je me rends compte que j'ai dit une grosse connerie aussi. :-°

                                          Ici, la réponse serai plutôt de définir un interval pour éviter que la boucle principale ne tourne trop dans le vide et de compter les tours de boucle.

                                          interval = 0.1
                                          maxtime = 120 // interval # 2 minutes
                                          for i in range(maxtime):
                                              last = time()
                                              events()
                                              blits()
                                              split()
                                              pause = interval - (time() - last)
                                              if pause > 0:
                                                  sleep(pause)
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            9 mai 2011 à 17:58:23

                                            dans pygame on s'arrange pour faire des fonctions/methodes non bloquantes ...

                                            typiquement on fourni un timer général ou bien chaque objet/partie possède son propre timer:

                                            while 1:
                                                truc.update()
                                                compteur.update()
                                                affichage.update()
                                            


                                            mais ça peut s'appliquer à tout en fait. Où est le problème ?
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Python c'est bon, mangez-en. 

                                              12 mai 2011 à 22:36:07

                                              Merci à tous pour vos suggestion, mais j'ai un peu de mal à comprendre ( et la flemme de me creuser la tête :-° ).

                                              Du coup, je demande juste votre avis sur le code suivant:

                                              continuer = 1
                                              x = 0
                                              
                                              while continuer:
                                                  pygame.time.Clock().tick(30) # 30 frames par seconde
                                                  for event in pygame.event.get():    #Attente des événements
                                                      if event.type == QUIT:
                                                          continuer = 0
                                                      if event.type == KEYDOWN:
                                                      # mes trucs à faire
                                                  x+=1
                                                  if x == 30 #au bout de 30 frames (1s donc):
                                                      x = 0
                                                      refresh_time()
                                              


                                              Voilà ! Sachez que je ne fais pas un jeu avec plein d'animations dans tous les sens ! 30 "images par seconde" suffisent largement !
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                12 mai 2011 à 23:17:44

                                                en fait tu veux exceuter refresh_time() 30 fois par seconde ?

                                                continuer = 1
                                                
                                                clk = pygame.Clock()
                                                tks = 0
                                                laps = 1000/30
                                                
                                                while continuer:
                                                    #temporisation du refresh()
                                                    tks += clk.tick()
                                                    if tks >= laps:
                                                        refresh_time()
                                                        tks -= laps
                                                
                                                    for event in pygame.event.get():    #Attente des événements
                                                        if event.type == QUIT: continuer = 0
                                                        if event.type == KEYDOWN: pass # mes trucs à faire
                                                
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Python c'est bon, mangez-en. 

                                                  13 mai 2011 à 18:47:59

                                                  Nop, je veux juste le rafraichir une fois par seconde, comme dans mon code ^^. J'ai testé et ça marche, je voulais juste savoir si vous "approuviez" la méthode.

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    13 mai 2011 à 22:39:59

                                                    Citation : Monstercrunch

                                                    Nop, je veux juste le rafraichir une fois par seconde, comme dans mon code ^^. J'ai testé et ça marche, je voulais juste savoir si vous "approuviez" la méthode.


                                                    ben non,
                                                    suffit de remplacer la ligne 5 de mon code par
                                                    laps = 1000
                                                    

                                                    pourquoi ? parce que
                                                    pygame.time.Clock().tick(30)
                                                    

                                                    est bloquant ...
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    Python c'est bon, mangez-en. 

                                                      14 mai 2011 à 16:21:37

                                                      pygame.time.Clock().tick(30)
                                                      


                                                      -> limite la boucle à 30 tours par secondes, donc au bout de 30 tours, ça fait une seconde et je rafraichit le temps.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        14 mai 2011 à 17:04:21

                                                        Citation : Monstercrunch

                                                        pygame.time.Clock().tick(30)
                                                        



                                                        -> limite la boucle à 30 tours par secondes, donc au bout de 30 tours, ça fait une seconde et je rafraichit le temps.



                                                        pygame.time.Clock().tick(30) pause l'exécution pour que la laps de temps entre 2 appels fasse au minimum dans ce cas 1/30s.
                                                        donc oui, ça limite bien la boucle à 30 tours par secondes, mais ça limite aussi la boucle for ...
                                                        si ça correspond à tes besoins, alors c'est bien; sinon c'est pas le top comme méthode. amha.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter

                                                        Python c'est bon, mangez-en. 

                                                          14 mai 2011 à 23:55:41

                                                          Merci quand même pour tes propositions ^^
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          [résolu]Programme avec un compte à rebours en prallèle

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown