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

Tkinter Python Discussion :

gérer les collisions entres widgets Tkinter


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Par défaut gérer les collisions entres widgets Tkinter
    Bonjour !

    Je suis élève en terminale S et je cherche à développer un petit jeu dans le cadre de mon projet bac.
    Seulement voilà: je n'ai pas la moindre idée pour gérer les collisions entre mon perso et les obstacles/trous !

    Le soucis majeur que je vois c'est que je n'arrive pas à identifier facilement mes obstacles (à la base je voulais faire ça par le tag mais lorsque le widget passe par la liste je crois qu'il disparaît) pour mettre des conditions qui géreraient les interactions sol/perso.

    Je veux bien une petite astuce ou des pistes

    Merci d'avance !

    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
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
    import tkinter as tk
    from random import randrange
     
     
    def sol_move(delay=250):
        canvas.move('sol', -20, 0)
        iid = sol_items.pop(0)
        canvas.coords(iid, 380, 380, 400, 400)
        sol_items.append(iid)
        root.after(delay, sol_move)
     
    blocage=0
     
    def obstacle_move (delay=250):
     
        global blocage
     
        canvas.move('obstacle_up',-20,0)
        canvas.move('obstacle_down',-20,0)
        obs=obstacle_up_items.pop(0)
        obs=obstacle_down_items.pop(0)
     
        if blocage%3==0: 
            proba=randrange(0,11)
     
            if proba<4: # création d'un obstacle 
     
                obs=canvas.create_rectangle( 380, 360, 400, 380, fill='grey', tag='obstacle_up')
                obstacle_up_items.append(obs)
                obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle_down')
                obstacle_down_items.append(obs_d)  
     
            elif proba>7: # création d'un trou 
     
                obs=canvas.create_rectangle( 380, 380, 400, 400, fill='grey90', outline='grey90', tag='obstacle_down')
                obstacle_down_items.append(obs)
                obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
                obstacle_up_items.append(obs_u)
     
            else: # recopie d'un terrain "normal" 
                obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
                obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle_down')
                obstacle_up_items.append(obs_u)
                obstacle_down_items.append(obs_d)
     
        else : # recopie d'un terrain "normal" 
            obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
            obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle_down')
            obstacle_up_items.append(obs_u)
            obstacle_down_items.append(obs_d)
     
        blocage +=1
        root.after(delay, obstacle_move)
     
     
    inprogress = False
     
    def sauter(e=None):
     
        global inprogress
        if inprogress:
            return
        inprogress = True
     
        def gen_move():
            for n in range(20):
                if n <= 9:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def _saut(delay=60):
            global inprogress
     
            try:
                direction = next(g_move)
                canvas.move('carre', 0, direction * 5)
                root.after(delay, _saut)
            except StopIteration:
                inprogress = False
     
        _saut()    
     
     
     
    root = tk.Tk()
    root.geometry('800x600+350+100')
    canvas = tk.Canvas(root, width=400, height=400, bg='grey90')
    canvas.pack()
     
     
    obstacle_up_items=[]
    obstacle_down_items=[]
    sol_items = []
     
     
    y0 = 380
    y1 = y0 +20
    y2 = 360
    y3 = y2+20
     
     
    for j in range(20): #liste des obstacles
        x0 = j*20
        x1 = x0 + 20
        iie = canvas.create_rectangle(x0, y2, x1, y3, fill='grey90', outline='grey90', tag='obstacle_up')
        obstacle_up_items.append(iie)
     
    for k in range(20): #liste des trous
        x0 = k*20
        x1 = x0 + 20
        iif = canvas.create_rectangle(x0, y0, x1, y1, fill='grey90', outline='grey90', tag='obstacle_down')
        obstacle_down_items.append(iif)
     
    for i in range(20): #liste du sol
        x0 = i*20
        x1 = x0 + 20
        iid = canvas.create_rectangle(x0, y0, x1, y1, fill='grey', tag='sol')
        sol_items.append(iid)   
     
     
    X1=40
    X2=X1+20
    Y1=360
    Y2=Y1+20
     
    f2=canvas.create_rectangle((X1,Y1,X2,Y2),fill='blue',tag="carre") #Perso bleu
     
    sol_move()
    obstacle_move()
     
    root.bind("<space>",sauter)
     
    tk.mainloop()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    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 736
    Par défaut
    Salut,

    Vous avez changé de pseudo ou vous avez récupéré le code de cette discussion?

    Seulement voilà: je n'ai pas la moindre idée pour gérer les collisions entre mon perso et les obstacles/trous !
    Pas d'idée = pas de code...

    La première question est de savoir "quand détecter ces collisions?".
    Une autre façon de regarder votre truc est de penser "intervalles de temps".
    Ce qui apparaît à l'écran à l'instant T sera déplacé/mis à jour à T+delay via les fonctions/callbacks déclenchés par .after(delay,...).
    Soit il faut avoir une seule horloge (un seul .after(delay...) plutôt que 3, soit il faut détecter les collisions dans ce qui "bouge" le plus souvent.
    Pour détecter les collisions, comme toutes vos figures sont des "rectangles", il suffit de regarder l'intersection de 'carre' avec le reste.
    Pour çà, vous devez apprendre à jouer avec canvas.find_overlapping(canvas.bbox('carre')) - voir ce que çà fait dans une documentation et testez...-.
    Ca va retourner la liste d'identifiants des items qui sont en intersection (les entiers créés par canvas.create_XXX et non les tags).
    Vous y trouverez l'identifiant de 'carre', (normal) et éventuellement d'autres.
    Si 'carre' ne doit jamais rien toucher alors, il suffira de tester si cette liste est plus grande que 1 sinon, il faudra récupérer les tags associés et regarder si...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Par défaut
    On peut dire que j'ai récupéré le code, on fait un travail en binôme pour notre spécialité ISN
    Vu que le sujet était différent j'ai voulu créer une nouvelle discussion.

    Merci pour votre aide !

    J'ai essayé la méthode .bbox mais ça ne marche pas (ou bien je l'utilise mal )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    f3=canvas.find_overlapping(canvas.bbox('carre'))
    >>>
    Traceback (most recent call last):
      File "C:\Python34\Fichier Python\try to progress.py", line 134, in <module>
        f3=canvas.find_overlapping(canvas.bbox('carre'))
    TypeError: find_overlapping() missing 3 required positional arguments: 'y1', 'x2', and 'y2'
    Pourtant quand je met ça dans une variable, ça correspond bien à 4 coordonnées:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    g=canvas.bbox('carre')
    print(g)
    f3=canvas.find_overlapping(g)
    >>> 
    (39, 359, 61, 381)
    Traceback (most recent call last):
      File "C:\Python34\Fichier Python\try to progress.py", line 136, in <module>
        f3=canvas.find_overlapping(g)
    TypeError: find_overlapping() missing 3 required positional arguments: 'y1', 'x2', and 'y2'

    Bref, ensuite j'ai intégré cette ligne de code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    f3=canvas.find_overlapping(X1,Y1,X2,Y2)
     
    >>> f3
    (3, 4, 5, 23, 24, 25, 43, 44, 45, 61)
    La liste est composée de 10 nombres, il y a autant d'items en intersection ? Après je les utilise comme des variables ?

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    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 736
    Par défaut
    Salut,

    Citation Envoyé par Y0rd4n Voir le message
    J'ai essayé la méthode .bbox mais ça ne marche pas (ou bien je l'utilise mal )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f3=canvas.find_overlapping(canvas.bbox('carre'))
    C'est ma faute: j'aurais du écrire canvas.find_overlapping(*canvas.bbox('carre'))

    Citation Envoyé par Y0rd4n Voir le message
    Bref, ensuite j'ai intégré cette ligne de code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    f3=canvas.find_overlapping(X1,Y1,X2,Y2)
     
    >>> f3
    (3, 4, 5, 23, 24, 25, 43, 44, 45, 61)
    La liste est composée de 10 nombres, il y a autant d'items en intersection ? Après je les utilise comme des variables ?
    A priori, il y a 10 items en intersection (en incluant 'carre'). Je n'en attendais pas autant. Pour voir à quoi ils correspondent, vous pouvez faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for iid in f3:
         print (canvas.gettags(iid))
         print (canvas.type(iid))
    Pour autant qu'il soit "normal" d'avoir autant d'items, vous pouvez dire "il y a collision" si au moins un des items à pour un tag "obstacle"dans la liste de tags retournés par .gettags.
    note: s'il y a beaucoup de bruit parce que 'carre' frotte, essayez de réduire la surface d'intersection avec canvas.find_overlapping(X1+2,Y1+2,X2-2,Y2-2) si çà le fait çà fera toujours moins de cas de figure à gérer.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Par défaut
    Bonjour !

    J'ai donc utilisé ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    f3=canvas.find_overlapping(X1+2,Y1+2,X2-2,Y2-2)
     
    for iid in f3:
         print (canvas.gettags(iid))
         print (canvas.type(iid))
    Et maintenant je n'ai plus que deux items concernés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> 
    ('obstacle_up',)
    rectangle
    ('carre',)
    rectangle
    (3, 61)
    Par contre je me suis rendu compte d'un petit soucis: lorsque je saute le personnage ne change pas d'ordonnées (360 380). Ça risque de poser problème pour la suite... Il faudrait changer ma fonction "sauter" pour que les coordonnées du personnage soient actualisées à chaque move. J'ai voulu utiliser .update puis .update_idletasks mais ça n'a rien donné.

    Voici ma fonction sauter:
    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
    def sauter(e=None):
     
        global inprogress
        if inprogress:
            return
        inprogress = True
     
        def gen_move():
            for n in range(20):
                if n <= 9:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def _saut(delay=60):
            global inprogress
            global Y1,Y2
            try:
                direction = next(g_move)
                canvas.move('carre', 0, direction * 5)
                canvas.update_idletasks()
                print(Y1,Y2)
                root.after(delay, _saut)
            except StopIteration:
                inprogress = False
     
        _saut()
    Dernier doute:
    lorsque je fais print(f3) le long de mon programme, le couple ne change pas : (3, 61)
    Ça me semble bizarre, est ce qu'il y aurait un autre défaut? Normalement lorsque le personnage est superposé avec des obstacles le couple devrait changer ou bien il devrait y avoir un nombre en plus.

    Je vous remet tout mon programme si ça peut vous aider :
    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
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    import tkinter as tk
    from random import randrange
     
     
    def sol_move(delay=250):
        canvas.move('sol', -20, 0)
        iid = sol_items.pop(0)
        canvas.coords(iid, 380, 380, 400, 400)
        sol_items.append(iid)
        root.after(delay, sol_move)
     
    blocage=0
     
    def obstacle_move (delay=250):
     
        global blocage
     
        canvas.move('obstacle',-20,0)
        canvas.move('obstacle_up',-20,0)
        canvas.move('obstacle_down',-20,0)
        obs=obstacle_up_items.pop(0)
        obs=obstacle_down_items.pop(0)
     
        if blocage%3==0: 
            proba=randrange(0,11)
            print(f3) 
            if proba<4: # création d'un obstacle 
     
                obs=canvas.create_rectangle( 380, 360, 400, 380, fill='grey', tag='obstacle_up')
                obstacle_up_items.append(obs)
                obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle')
                obstacle_down_items.append(obs_d)  
     
            elif proba>7: # création d'un trou 
     
                obs=canvas.create_rectangle( 380, 380, 400, 400, fill='grey90', outline='grey90', tag='obstacle_down')
                obstacle_down_items.append(obs)
                obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
                obstacle_up_items.append(obs_u)
     
            else: # recopie d'un terrain "normal" 
                obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
                obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle')
                obstacle_up_items.append(obs_u)
                obstacle_down_items.append(obs_d)
     
        else : # recopie d'un terrain "normal" 
            obs_u=canvas.create_rectangle( 380, 360, 400, 380, fill='grey90', outline='grey90', tag='obstacle')
            obs_d=canvas.create_rectangle( 380, 380, 400, 400, fill='grey', tag='obstacle')
            obstacle_up_items.append(obs_u)
            obstacle_down_items.append(obs_d)
     
        canvas.tag_lower('obstacle_up')
        canvas.tag_lower('obstacle')
     
        blocage +=1
        root.after(delay, obstacle_move)
     
     
    inprogress = False
     
    def sauter(e=None):
     
        global inprogress
        if inprogress:
            return
        inprogress = True
     
        def gen_move():
            for n in range(20):
                if n <= 9:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def _saut(delay=60):
            global inprogress
            global Y1,Y2
            try:
                direction = next(g_move)
                canvas.move('carre', 0, direction * 5)
                canvas.update_idletasks()
                print(Y1,Y2)
                root.after(delay, _saut)
            except StopIteration:
                inprogress = False
     
        _saut()    
     
     
     
    root = tk.Tk()
    root.geometry('800x600+350+100')
    canvas = tk.Canvas(root, width=400, height=400, bg='grey90')
    canvas.pack()
     
     
    obstacle_up_items=[]
    obstacle_down_items=[]
    sol_items = []
     
     
    y0 = 380
    y1 = y0 +20
    y2 = 360
    y3 = y2+20
     
     
    for j in range(20): #liste des obstacles
        x0 = j*20
        x1 = x0 + 20
        iie = canvas.create_rectangle(x0, y2, x1, y3, fill='grey90', outline='grey90', tag='obstacle_up')
        obstacle_up_items.append(iie)
     
    for k in range(20): #liste des trous
        x0 = k*20
        x1 = x0 + 20
        iif = canvas.create_rectangle(x0, y0, x1, y1, fill='grey90', outline='grey90', tag='obstacle_down')
        obstacle_down_items.append(iif)
     
    for i in range(20): #liste du sol
        x0 = i*20
        x1 = x0 + 20
        iid = canvas.create_rectangle(x0, y0, x1, y1, fill='grey', tag='sol')
        sol_items.append(iid)   
     
     
    X1=40
    X2=X1+20
    Y1=360
    Y2=Y1+20
     
    f2=canvas.create_rectangle((X1,Y1,X2,Y2),fill='blue',tag="carre") #Perso bleu
    canvas.tag_raise('carre')
    f3=canvas.find_overlapping(X1+2,Y1+2,X2-2,Y2-2)
     
    for iid in f3:
         print (canvas.gettags(iid))
         print (canvas.type(iid))
     
    sol_move()
    obstacle_move()
     
    root.bind("<space>",sauter)
     
    tk.mainloop()
    Merci !

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    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 736
    Par défaut
    Salut,

    Remplacez print(f3) par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
             x1, y1, x2, y2 = canvas.bbox('carre')
             print(canvas.find_overlapping(x1+2, y1+2, x2-2, y2-2)
    Si 'carre' bouge, les variables X1, Y1, X2, Y2 utilisées pour le créer ne seront mises à jour que si vous leur assignez de nouvelles valeurs et non automagiquement.
    note: au cas où, vous pouvez récupérer la "position" actuelle du carré via canvas.coords('carre')

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Gérer les Collisions
    Par Charlie111 dans le forum Ogre
    Réponses: 9
    Dernier message: 01/05/2008, 23h38
  2. [1.0.2][Zend_db_table] Gérer les liaisons entre les tables
    Par Baptiste Wicht dans le forum Zend_Db
    Réponses: 8
    Dernier message: 05/10/2007, 09h00
  3. Gérer les collisions
    Par gazier20 dans le forum Physique
    Réponses: 5
    Dernier message: 13/05/2006, 09h34
  4. GLScene et les collisions entre les objets
    Par HopeLeaves dans le forum API, COM et SDKs
    Réponses: 5
    Dernier message: 13/06/2005, 19h45
  5. Méthode simple pour gérer les collisions
    Par Hyoga dans le forum OpenGL
    Réponses: 2
    Dernier message: 19/02/2005, 13h43

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