Partage
  • Partager sur Facebook
  • Partager sur Twitter

Faire interagir des objets dans le canvas Tkinter

Faire interagir des objets dans le canvas Tkinter

    8 avril 2016 à 20:31:54

    Donc voila dans un précédent sujet j'ai demandé comment faire des ennemies (carré) qui bouge horizontalement dans le canvas. J en ai tiré la fonction ci-dessous. J ai maintenant besoin d' aide car je cherche a faire interagir ces ennemies avec mon joueur qui lui, a des coordonnées x1,y1,x2,y2 dans une fonction qui lui permet de bouger.

    Merci d'avance pour votre aide, Wakkko

    FRAME_RATE = 1000//30 # +/- 30 FPS
    
        def move_enemis(canvas, enemis):
            for i, enemi_data in enumerate(enemis):
                # We use enumerate to retrieve the index with the item as we
                # might change the item in the list.
                enemi, speed = enemi_data
                old_x0, old_y0, old_x1, old_y1 = canvas.coords(enemi)
    
    
                canvas.move(enemi, speed, 0)
    
    
                x0, y0, x1, y1 = canvas.coords(enemi)
                canvas.tag_raise(enemi)
                if x0 < 0 or x1 > 650:
                    speed = speed * -1
                    canvas.move(enemi, speed, 0)
                    enemis[i] = (enemi, speed)
    
    
            canvas.after(FRAME_RATE, move_enemis, canvas, enemis)
    
    
        canvas.grid()
    
        enemis = []
        enemi_speed = 10
        enemi = canvas.create_rectangle(25, 0, 50, 25, fill='brown')
        enemi_data = (enemi, enemi_speed)
        enemis.append(enemi_data)
    
        enemi = canvas.create_rectangle(0,75 , 25, 100, fill='brown')
        enemi_data = (enemi, enemi_speed)
        enemis.append(enemi_data)
    
        enemi = canvas.create_rectangle(0,150 , 25, 175, fill='brown')
        enemi_data = (enemi, enemi_speed)
        enemis.append(enemi_data)
    
    
        canvas.after(FRAME_RATE, move_enemis, canvas, enemis)



    -
    Edité par wakkko 11 avril 2016 à 1:09:40

    • Partager sur Facebook
    • Partager sur Twitter
      9 avril 2016 à 15:56:20

      Tu peux mettre les coordonnées de ton perso en global, comme ça, elles seront accessibles partout. par contre, fait gaffe car dans ce cas, tu devras changer le nom des variables x1,y1 qui sont dans la fonction move_enemis sinon, les changements des uns affecteront les autres, car ce sera la même variable.
      • Partager sur Facebook
      • Partager sur Twitter
        11 avril 2016 à 1:09:01

        J ai fait global et changé le nom des variables de mon joueur en x3,y3,x4,y4

        Mais je n'arrive toujours pas a faire que, quand les ennemies de coordonnées x0,y0,x1,y1(?) ont les mêmes coordonnées que le joueur, sa face quelque chose (active une autre fonction)

        Le problème peut venir du fait qu'il y est plusieurs ennemies avec des coordonées differentes mais tous avec x0, y0, x1, y1?

        -
        Edité par wakkko 11 avril 2016 à 1:10:30

        • Partager sur Facebook
        • Partager sur Twitter
          11 avril 2016 à 11:34:23

          plusieurs variables ne peuvent pas avoir le même nom, tu as raison. il faut sauvegarder les coordonnées de tous les ennemis, tu peux faire ça dans des listes, mais pour plus d'élégance, je te conseillerais de créer une classe ennemi, qui aura ses coordonnées en paramètre.

          de plus, pourquoi tu utilises 4 variables en coordonnée, tu pourrais utiliser seulement une en x, l'autre en y, ensuite, tu calcule la distance entre ton perso et l'ennemi à l'aide de ces coordonnées, et si la distance obtenue est inférieure à un certain seuil, alors tu pourras considérer qu'il y a collision. 

          • Partager sur Facebook
          • Partager sur Twitter
            11 avril 2016 à 12:01:05

            Dans un canvas tu peux utiliser la méthode find_overlapping qui te renvoie tous les items qui touchent une zone. Cette zone peut-être ce que tu veux, et donc ça peut également être ton objet:

            can.find_overlapping(x1, y1, x2, y2)


            Avec can ton Canvas et x1, y1, x2, y2 les coordonnées de ta zone.

            PS: Pour avoir les coordonnées de ton objet à un instant t, il suffit d'utiliser la méthode coords et de lui passer en argument l'identifiant de ton objet:

            id_rect = can.create_rectangle(10, 10, 20, 25, fill="blue")
            coord_rect = can.coords(id_rect)


            EDIT: Et donc si on combine les 2, ça donne:

            coord_rect = can.coords(id_rect)
            items = can.find_overlapping(*coord_rect)

            -
            Edité par Olygrim 11 avril 2016 à 12:04:04

            • Partager sur Facebook
            • Partager sur Twitter
            Précepte: Le mieux est l'ennemi du bien
              21 avril 2016 à 16:16:52

              Bonjour,

              Je suis intéresse par t a fonction find_overlapping mais je ne vois pas comment faire une condition qui énoncerai cela:

              Si (ennemi) find_overlapping (joueur:x1,y1,x2,y2) alors fonction.

              • Partager sur Facebook
              • Partager sur Twitter
                21 avril 2016 à 16:34:31

                La méthode find_overlapping renvoie les items qui touchent ton objet (sûrement dans une liste). Donc si la liste est vide, ça signifie que rien ne touche ton objet. Si la liste contient quelque chose, il suffit de comparer ses éléments avec les ids de tes ennemis (que tu auras au préalable enregistrés). Si l'un d'eux est positif, c'est qu'un ennemi touche ton objet.

                Un truc du style:

                ids_ennemis = []
                
                #Création d'un ennemi
                ids_ennemis.append(can.create_rectangle(x1, y1, x2, y2, fill="blue"))
                
                
                #Création de ton perso
                id_perso = can.create_rectangle(x1, y1, x2, y2, fill="green")
                
                
                #Recherche
                coord_perso = can.coords(id_perso)
                id_touch = can.find_overlapping(*coord_perso)
                if id_touch:
                   if any(elt in ids_ennemis for elt in id_touch):
                      #SI L'UN DES ENNEMIS TOUCHE LE PERSO, FAIRE LE TRAITEMENT
                


                Je pense qu'un truc comme ça (en le mettant dans le contexte de ton projet) devrait fonctionner.

                -
                Edité par Olygrim 21 avril 2016 à 16:35:06

                • Partager sur Facebook
                • Partager sur Twitter
                Précepte: Le mieux est l'ennemi du bien
                  21 avril 2016 à 17:15:24

                  je n ai pas encore essayé le programme que tu m'a soumis mais j' ai un problème pour le "id_perso" car le joueur est dans une autre fonction qui lui permet de se déplacer  ducoup je sais pas comment faire pour :

                  coord_perso = can.coords(id_perso)

                  • Partager sur Facebook
                  • Partager sur Twitter
                    21 avril 2016 à 18:01:15

                    Il faut juste que tu récupère l'id de ton perso à sa création. Donc soit utiliser une variable global ou un objet muable (si la création de ton perso se passe aussi dans une fonction). Un truc du style:

                    id_perso = []
                    
                    def ma_fonction_ou_mon_perso_est_crée():
                        #Les traitements avant
                    
                        #Récup de l'id
                        id_perso.append(can.create_rectangle(.....))
                    
                        #Les traitements après


                    En faisant ça, l'identifiant de ton perso se trouve en première position de la liste id_perso et donc pour y avoir accès il faudra faire: id_perso[0]

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Précepte: Le mieux est l'ennemi du bien

                    Faire interagir des objets dans le canvas Tkinter

                    × 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