IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Gestion d'événements simultanés avec tkinter.


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    OOpps
    Inscrit en
    Mai 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : OOpps

    Informations forums :
    Inscription : Mai 2015
    Messages : 11
    Points : 5
    Points
    5
    Par défaut Gestion d'événements simultanés avec tkinter.
    Bonsoir à tous,

    pour un jeu que je tente de développer, j'aurai besoin de récupérer simultanément plusieurs entrées clavier et les traiter séparément.

    J'ai cherché du côté du multithreading sans succès pour le moment.

    Pour faire simple, plutôt que de vous embrouiller avec le code lourd et touffu de mon jeu, j'ai transposé le problème avec une fenêtre tkinter contenant deux balles :

    - une rouge pour le joueur 1 pilotée par up, down, right, left.
    - une bleue pour le joueur 2 pilotée par e, s, d, x.

    Comment faire en sorte que chaque joueur puisse piloter sa balle de façon fluide sans être bloqué par les actions de l'autre ?

    Un grand merci à tous pour votre aide et ce forum !

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    import tkinter
    import threading
    import time
     
    class Appl(object) :
        def __init__(self) :
            # Création de la fenetre :
            self.root = tkinter.Tk()
            self.can = tkinter.Canvas(self.root, width=600, height=600, bg='ivory')
            self.can.grid(row=0, column=0)
            self.balleR = self.can.create_oval(85,85,115,115, fill='red')
            self.balleB = self.can.create_oval(485,485,515,515, fill='blue')
     
            # Création de deux threads pour un traitement multitache :
            # La méthode start de la classe threading.Thread dont dérive 
            # nos classes ThreadBallR et ThreadBallB va lancera elle-même
            # la méthode run que nous allons surchargée
            tbr = ThreadBallR(self.can, self.balleR)
            tbr.start()
            tbb = ThreadBallB(self.can, self.balleB)
            tbb.start()
     
     
     
    class ThreadBallR(threading.Thread) :
        def __init__(self, can, balle) :
            threading.Thread.__init__(self)
            self.can , self.balle = can , balle
     
        def run(self) :
            self.can.focus_set()
            self.can.bind("<Up>", self.moove)
            self.can.bind("<Down>", self.moove)
            self.can.bind("<Right>", self.moove)
            self.can.bind("<Left>", self.moove)
     
     
        def moove(self, event) :
            if event.keysym == 'Up' :
                self.can.move(self.balle, 0, -5)
            if event.keysym == 'Down' :
                self.can.move(self.balle, 0, 5)
            if event.keysym == 'Right' :
                self.can.move(self.balle, 5, 0)
            if event.keysym == 'Left' :
                self.can.move(self.balle, -5, 0)
            time.sleep(0.01)
     
     
     
    class ThreadBallB(threading.Thread) :
        def __init__(self, can, balle) :
            threading.Thread.__init__(self)
            self.can , self.balle = can , balle
     
        def run(self) :
            self.can.focus_set()
            self.can.bind("<KeyPress-e>", self.moove)
            self.can.bind("<KeyPress-x>", self.moove)
            self.can.bind("<KeyPress-d>", self.moove)
            self.can.bind("<KeyPress-s>", self.moove)
     
     
        def moove(self, event) :
            if event.keysym == 'e' :
                self.can.move(self.balle, 0, -5)
            if event.keysym == 'x' :
                self.can.move(self.balle, 0, 5)
            if event.keysym == 'd' :
                self.can.move(self.balle, 5, 0)
            if event.keysym == 's' :
                self.can.move(self.balle, -5, 0)
            time.sleep(0.01)
     
     
     
     
     
    Appl().root.mainloop()

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 379
    Points : 36 923
    Points
    36 923
    Par défaut
    Salut,

    Citation Envoyé par Piittt Voir le message
    Comment faire en sorte que chaque joueur puisse piloter sa balle de façon fluide sans être bloqué par les actions de l'autre ?

    Un grand merci à tous pour votre aide et ce forum !
    On ne peut pas (et c'est une des raisons du multi-touch) sauf à imaginer deux applications tk (a chacun son PC) qui communiquent via un serveur.

    - W

  3. #3
    Futur Membre du Club
    Homme Profil pro
    OOpps
    Inscrit en
    Mai 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : OOpps

    Informations forums :
    Inscription : Mai 2015
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Et dans mon jeu : un space Invader légérement modifié : à chaque fois que la fusée de défense tire une balle, son mouvement est stoppé.

    Il n'y a rien à faire pour qu'elle puisse tirer tout en continuant à se déplacer ?
    Dans les nombreux jeux en ligne qu'on trouve sur le web, c'est possible.

    Il n'y aurait que Python qui n'en serait pas capable ?

    Un grand merci pour votre aide.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 379
    Points : 36 923
    Points
    36 923
    Par défaut
    Citation Envoyé par Piittt Voir le message
    Et dans mon jeu : un space Invader légérement modifié : à chaque fois que la fusée de défense tire une balle, son mouvement est stoppé.

    Il n'y a rien à faire pour qu'elle puisse tirer tout en continuant à se déplacer ?
    Dans les nombreux jeux en ligne qu'on trouve sur le web, c'est possible.
    C'est une toute autre question. Cà on peut car ce n'est pas une histoire de gestion d'un clavier/souris pensé unique sur un poste de travail, mais la capacité à faire plusieurs choses, toujours l'une après l'autre, mais assez vite pour que l’œil humain n'y voie que du feu.
    note: si le problème est 2 touches en même temps, on peut appuyer sur ctrl-, alt- " en même temps que... Dans tous les cas, Python ne fait rien: c'est la bibliothèque graphique et essentiellement le window manager de l'environnement d'exploitation (sur laquelle la biblio. graphique s'appuie) qui gère tout çà.

    - W

  5. #5
    Futur Membre du Club
    Homme Profil pro
    OOpps
    Inscrit en
    Mai 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : OOpps

    Informations forums :
    Inscription : Mai 2015
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Merci pour ta réponse !

    Je ne comprends pas exactement : lorsque je maintiens la touche 'Left' enfoncée, ma fusée se déplace en continu.
    Il suffit que je tire un missile avec la touche 'space' et elle s'arrête sur place en ne tenant plus compte de la touche 'Left' qui est toujours enfoncée (il faut alors relâcher la touche 'Left' et la ré-enfoncer pour que ma fusée reparte).

    Que faire pour qu'elle ne soit plus stoppée dans son déplacement par le tir d'un missile avec la touche 'space' ?

    Un grand merci pour ton aide !

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 481
    Points : 9 280
    Points
    9 280
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Si les jeux font couramment plein de choses en même temps, ce n'est pas de la programmation facile. Et les machines de jeux sont en général très puissantes.

    Programmer un jeux en Python ne me semble pourtant pas impossible, et je pense au principe suivant:

    - chaque joueur a sa logique de jeux dans un thread. Mais les thread ne peuvent pas toucher au graphique (=> plantages).

    - par contre, les thread peuvent donner des instructions au programme principal, et c'est lui qui fait bouger les pièces. Si ce sont des boules à faire rouler, le programme principal peut les faire bouger alternativement un petit peu à chaque fois pour qu'on ait l'impression de mouvements autonomes. J'avais fait quelque chose comme ça il y a pas mal de temps: http://python.jpvweb.com/mesrecettes...billard_boules.

    Après, il y a des réglages à faire pour exploiter au mieux la puissance machine dont on dispose, pour autant qu'elle soit suffisante... Si nécessaire, les parties les plus critiques du code Python peuvent être compilées en C avec Cython.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 379
    Points : 36 923
    Points
    36 923
    Par défaut
    Citation Envoyé par Piittt Voir le message
    Que faire pour qu'elle ne soit plus stoppée dans son déplacement par le tir d'un missile avec la touche 'space' ?
    Je viens de faire l'essai sous LibreOffice Writer. Cà marche pareil: tant quej 'appuie sur "s" çà va puis si j'appuie en même temps sur <space>, il y a de <space>, je relâche: les "s" ne revienne plus. Donc çà ne vient ni de Python ni de la bibliothèque graphique donc il va falloir faire avec.
    Une chose que vous pouvez faire, c'est détecter les différents KeyPress et KeyRelease i.e. fabriquer une machine à états.

    - W

  8. #8
    Futur Membre du Club
    Homme Profil pro
    OOpps
    Inscrit en
    Mai 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : OOpps

    Informations forums :
    Inscription : Mai 2015
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Effectivement, je viens de faire le test sous libre office.

    Mais pourtant, le jeu à l'adresse ci-dessous, bien que très basique y parvient sans problème : le déplacement n'est pas stoppé par l'appui sur la touche 'space' de tir :

    http://www.dwmkerr.com/experiments/spaceinvaders/


    Un avis sur la technique qu'ils utilisent ?

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 379
    Points : 36 923
    Points
    36 923
    Par défaut
    Citation Envoyé par Piittt Voir le message
    Un avis sur la technique qu'ils utilisent ?
    La technique qu'ils utilisent on s'en fout puisque vous ne pouvez que "détecter les différents KeyPress et KeyRelease i.e. fabriquer une machine à états."
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import tkinter as tk
    import sys
     
    xmap = {}
     
    def shoot_key(keysym, delay=10):
        print (keysym if keysym == 's' else '*', end='')
        sys.stdout.flush()
        xmap[keysym] = root.after(delay, lambda: shoot_key(keysym))
     
    def key_press(keysym):
        if keysym in ('s', 'space') and xmap.get(keysym) is None:
            shoot_key(keysym)
     
    def key_release(keysym):
        if keysym in ('s', 'space') and xmap.get(keysym) is not None:
            root.after_cancel(xmap[keysym])
            xmap[keysym] = None
     
     
    root = tk.Tk()
    root.bind('<KeyRelease>', lambda e: key_release(e.keysym))
    root.bind('<KeyPress>', lambda e: key_press(e.keysym))
    tk.mainloop()
    C'est pas compliqué

    - W

  10. #10
    Futur Membre du Club
    Homme Profil pro
    OOpps
    Inscrit en
    Mai 2015
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : OOpps

    Informations forums :
    Inscription : Mai 2015
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Effectivement, je ne partais pas dans la bonne direction.

    Je vais étudier de plus près ta machine à états qui semble faire exactement ce que je veux : thanks !

Discussions similaires

  1. Gestion des évènements avec une superposition d'éléments
    Par Meardon dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 26/10/2008, 14h47
  2. Problème gestion des évènements avec un JTree
    Par lyaminat dans le forum Composants
    Réponses: 2
    Dernier message: 14/10/2008, 15h44
  3. Problème avec la gestion des événements
    Par Franck.H dans le forum SDL
    Réponses: 32
    Dernier message: 26/02/2007, 16h01
  4. Problème avec la gestion des événements
    Par CynO dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 17/10/2005, 10h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo