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

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    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 sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    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 Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    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 sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    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 Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    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 sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    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

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Super !
    Maintenant ça m'affiche ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (4, 61)
    (7, 61)
    (61,)
    (13, 61)
    (16, 61)
    (19, 61)
    (61,)
    (70, 61)

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Y0rd4n Voir le message
    Super !
    Maintenant ça m'affiche ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (4, 61)
    (7, 61)
    (61,)
    (13, 61)
    (16, 61)
    (19, 61)
    (61,)
    (70, 61)
    61 est probablement l'identifiant du "carre" (à vérifier) pour les autres, je sais pas (vous savez tester) : tout bouge...

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

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    C'est bon !

    Ensuite j'aimerais que si le carre rencontre un obstacle pendant un saut il ne le transperce pas, il arrête de descendre.
    Comment faire pour mettre plusieurs arrêts à ma fonction saut:

    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(100):
                if n <= 49:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def _saut(delay=12):
            global inprogress
            global Y1,Y2
            try:
                direction = next(g_move)
                canvas.move('carre', 0, direction)
                root.after(delay, _saut)
     
            except StopIteration:
     
                inprogress = False
     
        _saut()
    J'ai essayé une deuxième clause except, une condition if avec un break mais ça ne tourne pas.

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Y0rd4n Voir le message
    Ensuite j'aimerais que si le carre rencontre un obstacle pendant un saut il ne le transperce pas, il arrête de descendre.
    Comment faire pour mettre plusieurs arrêts à ma fonction saut:
    Il faut que vous preniez un papier et un crayon pour dessiner la suite des déplacements "obstacles", "carre",...
    Déjà (comme je le racontais dans un post précédent) çà serait plus simple si "obstacles", "carres", ... se déplaçaient sous le contrôle d'un seul .after (plutôt que de 3).
    Ensuite comme "obstacle" et "carre" bougent sous le contrôle du programme (les "spaces" sont ignorés tant que...) vous pouvez éventuellement anticiper une collision.
    Le boulot étant de traduire "si le carre rencontre un obstacle pendant un saut il ne le transperce pas, il arrête de descendre" et ce qui se passe après.

    Pour suspendre le déplacement du "carre", vous pouvez essayez avec une variable globale "suspendre" testée à chaque itération.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        def _saut(delay=60):
            global inprogress
            global Y1,Y2
            try:
                if not suspendre:
                    direction = next(g_move)
                    canvas.move('carre', 0, direction * 5)
                    canvas.update_idletasks()
                root.after(delay, _saut)
            except StopIteration:
                inprogress = False
    Le problème étant de savoir quand la positionner (et donc de faire des petits dessins).

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

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    J'ai essayé de visualiser la chose en dessinant et j'ai réussi à stabiliser mon personnage lorsqu'il rencontre un obstacle.

    Par contre j'ai essayé de rassembler tout mon programme sous un seul after, mais lorsque je rassemble la fonction saut et terrain_move j'ai essayé de mettre un compteur et ça fait apparaitre mon terrain un rectangle par un à chaque fois que je saute:
    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
    inprogress = False
    blocage=0
    engrenage=0
     
    def sauter(e=None):
     
        global inprogress
        if inprogress:
            return
        inprogress = True
     
        def gen_move():
            for n in range(100):
                if n <= 49:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def mouvement(delay=10):
     
            global engrenage
            global inprogress
            global Y1,Y2
     
            try:
                direction = next(g_move)
                canvas.move('carre', 0, direction)
                root.after(delay, mouvement)
     
            except StopIteration:
     
                inprogress = False
     
            engrenage +=1
     
            if engrenage ==20:
     
                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)
                a=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)
                        obstacle_down_items.append(a)  
     
                    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)
                        obstacle_up_items.append(a)
     
                    else: # recopie d'un terrain "normal" 
                        obstacle_up_items.append(a)
                        obstacle_down_items.append(a)
                        print('hello1')
                else : # recopie d'un terrain "normal" 
                    obstacle_up_items.append(a)
                    obstacle_down_items.append(a)
                    print('hello2')
                canvas.tag_lower('obstacle_up')
                canvas.tag_lower('obstacle')
                print('hello3')
     
                engrenage=0
                blocage +=1
     
     
     
        mouvement()
    Donc en attendant j'ai essayé de développer la "gravité" sur une autre fonction en gardant les fonctions 'sauter' et 'terrain_move' séparée.
    Mais pour l'instant ça me lance une boucle infini contradictoire et mon programme crash...

    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
    def sauter(e=None):
     
        global inprogress
        if inprogress:
            return
        inprogress = True
     
        def gen_move():
            for n in range(200):
                if n <= 49:
                    yield -1
                else:
                    yield 1
     
        g_move = gen_move()
     
        def _saut(delay=10):
     
     
            global inprogress
            global X1,Y1,X2,Y2
     
            if len(canvas.find_overlapping(X1+1,Y1+1,X2-1,Y2-1)) < 2:
                suspendre = False
            else :
                suspendre = True
            try:
                print(canvas.find_overlapping(X1+2,Y1+2,X2-2,Y2-2))
                if not suspendre:
                    direction = next(g_move)
                    canvas.move('carre', 0, direction)
                    root.after(delay, _saut)
                else :
                    canvas.move('carre', 0, -2)                
            except StopIteration:
     
                inprogress = False
        inprogress = False
        _saut()    
     
    def gravity(delay=10):
        global inprogress
     
        if not inprogress:
            x1, y1, x2, y2 = canvas.bbox('carre')        
            while len(canvas.find_overlapping(x1,y1,x2,y2))<1:
                canvas.move('carre', 0, 1)
     
        root.after(delay, gravity)

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Un des avantages du langage Python est que le code est assez facile à écrire. Çà veut dire aussi qu'il est facile de tout jeter pour ré-écrire une mouture plus "propre".
    note: Ici, le problème est que découvrant au fil de l'eau les fonctionnalités que vous voulez ajouter, pas facile d'anticiper comment construire le code.
    Donc voici une mouture ou le mur bloque la chute et ou le personnage tombe dans les trous (après ce qu'on en fait...)
    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
    import tkinter as tk
    from random import randint
     
    free_holes = []
    free_walls = []
     
    def recycle(ldz, free_list):
        _, y0, _, y1 = ldz
        items = canvas.find_overlapping(-SIZE+1, y0, -1, y1)
        if items:
            assert len(items) == 1
            free_list.append(items[0])
     
    def reuse(ldz, free_list):
        iid = free_list.pop(0)
        canvas.coords(iid, *ldz)    
        return iid
     
    def create_box(ldz, flist, draw):
        recycle(ldz, flist)
        n = randint(0, 10)
        if n in (2, 6, 8):
            return reuse(ldz, flist) if flist else draw(ldz)
     
     
    in_progress = False
    delta_move = [ -1, -1, -1, -1, 1, 1, 1, 1]
    ix = -1
     
    def move_personnage():
        global in_progress, ix
     
        d = delta_move[ix]
        canvas.move('personnage', 0, d * SIZE)
        ix += 1
        if ix == len(delta_move):
            ix = -1
            in_progress = False
     
    def sauter(e=None):        
        global in_progress, ix
        if in_progress:
            return
        in_progress = True
        ix = 0
     
    draw_hole = lambda ldz: canvas.create_rectangle(ldz, fill='red', width=0, tag=('hole', 'move'))
    draw_wall = lambda ldz: canvas.create_rectangle(ldz, fill='green', width=0, tag=('wall', 'move'))
     
    def motion(delay=250):
        # on bouge tout ce qu'il y a à bouger vers la gauche.
        canvas.move('move', -SIZE, 0)
     
        # creation trous et murs
        iid = create_box(HOLE_LDZ, free_holes, draw_hole)
        if iid is None:
            create_box(WALL_LDZ, free_walls, draw_wall)
     
     
        x0, y0, x1, y1 = canvas.bbox('personnage')
        # item below
        item_below = None
        items = canvas.find_overlapping(x0+5, SIZE+y0+5, x1-5, SIZE+y1-5)
        for iid in items:
            tags = canvas.gettags(iid)
            if 'hole' in tags:
                item_below = 'hole'
            elif 'wall' in tags:
                item_below = 'wall'
            if item_below:
                break
     
        if ix != -1: # est ce que le personnage se déplace?
            if delta_move[ix] < 0 or (delta_move[ix] > 0 and not item_below): 
                # s'il monte ou s'il descend sans être bloqué
                move_personnage()
     
        elif item_below == 'hole': # au repos au dessus d'un trou
            canvas.move('personnage', 0, SIZE)
            canvas.tag_raise('personnage')
     
     
        root.after(delay, motion)
     
     
    if __name__ == '__main__':
        HEIGHT = WIDTH = 400
        SIZE = 20
        # landing zones
        HOLE_LDZ = (WIDTH - SIZE, HEIGHT - SIZE, WIDTH, HEIGHT)
        WALL_LDZ = (WIDTH - SIZE, HEIGHT - 2*SIZE, WIDTH, HEIGHT - SIZE)
     
        root = tk.Tk()
        root.geometry('+350+100')
        canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg='grey90')
        canvas.pack()
     
        # creation du sol: une bande.
        x0, x1 = 0, WIDTH+1
        y0, y1 = HEIGHT - SIZE, HEIGHT
        canvas.create_rectangle(x0, y0,  x1, y1, width=0, fill='grey', tag='sol')
     
        # creation du personnage
        x0 = 40
        x1 = x0 + SIZE
        y0 = HEIGHT - 2 * SIZE
        y1 = y0 + SIZE
        canvas.create_oval(x0, y0, x1, y1, fill='blue', tag='personnage')
     
        motion()
        root.bind("<space>", lambda e: sauter())
     
        tk.mainloop()
    - 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