Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pygame : Gestion mask de collision

Masks non-rectangulaires

Anonyme
    28 janvier 2015 à 18:34:12

    Bonjour à tous ! Je suis actuellement en train de programmer un Worms-like en Python et j'utilise pour cela la bibliothèque Pygame (je débute). J'expérimente tout d'abord le déplacement de personnage sur une plateforme ainsi que le saut et la gravité.
    Comme il s'agit d'un jeu type Worms, le sol n'est pas de type rectangulaire ou linéaire car il peut se détruire par endroit (et donc comporter des trous dans lesquels le personnage peut tomber).

    Or voilà mon problème :
    Je voudrai vérifier si il y a une collision entre le personnage et le sol, je me suis orienté vers les masks et j'ai défini des masks qui suivent parfaitement les silhouettes du sol et du personnage (afin de pouvoir vérifier exactement quand le personnage touche le sol).
    J'ai naturellement utilisé la fonction de Pygame qui permet normalement ça :

    #On charge l'image
    monimage = pygame.image.load("lien/image.png").convert_alpha()
    #On crée le mask de l'image
    monimage_mask = pygame.mask.from_surface(monimage)

    Jusqu'à là ça va... mais quand j'utilise la fonction :

    #On test la collision entre les masks
    pygame.sprite.collide_mask(image1_mask, image2_mask)

    qui retourne une valeur booléenne, ça ne fonctionne pas et ça me retourne le message :

    AttributeError: 'pygame.Rect' object has no attribute 'rect'

     Alors question : faut-il mettre autre chose que des masks dans

    pygame.sprite.collide_mask()

    ?

    Faut-il transformer les images (appliquer une autre fonction ?), car je vois " sprite " mais je ne sais pas à quoi cela correspond vraiment.

    Aidez-moi s'il vous plait, je cherche sur internet mais je ne trouve que des tests de collision entre masks rectangulaires et je pense que ça ne peut pas faire l'affaire.

    Des solutions ? des suggestions ? des imprécisions ? Répondez-moi ;) toute aide est la bienvenue !

    Le Github du projet : https://github.com/SL-prog/MountainDomination

    • Partager sur Facebook
    • Partager sur Twitter
      29 janvier 2015 à 15:38:42

      Le message d'erreur est explicite. Tu passes des Rect alors que la doc dit qu'il veut des Sprite. J'attire aussi ton attention sur ces deux choses

      If the sprites have a “mask” attribute, that is used as the mask, otherwise a mask is created from the sprite image. [...] You should consider creating a mask for your sprite at load time if you are going to check collisions many times. This will increase the performance, otherwise this can be an expensive function because it will create the masks each time you check for collisions.

      Donc en pratique ça donne:

      mon_sprite1 = pygame.Sprite()
      mon_sprite1.image = pygame.image.load("lien/image1.png").convert_alpha()
      mon_sprite1.rect = mon_sprite1.image.get_rect()
      mon_sprite1.mask = pygame.mask.from_surface(mon_sprite1.image)
      

      mon_sprite2 = pygame.Sprite() mon_sprite2.image = pygame.image.load("lien/image2.png").convert_alpha() mon_sprite2.rect = mon_sprite2.image.get_rect() mon_sprite2.mask = pygame.mask.from_surface(mon_sprite2.image)

      pygame.sprite.collide_mask(mon_sprite1, mon_sprite2)

      </pre>
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        30 janvier 2015 à 18:21:54

        Merci beaucoup Dan737 ! Je vais tester ça illico-presto !
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          30 janvier 2015 à 19:02:57

          Ça fonctionne :) par contre, tu t'es trompé c'est :

          pygame.sprite.Sprite()


          et non :

          pygame.Sprite()



          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            30 janvier 2015 à 19:23:48

            En fait finalement non ça ne fonctionne pas... :/ je n'ai plus de messages d'erreur, mais quand je fais un test avec une variable :
            test = pygame.sprite.collide_mask(image1, image)

            ben ' test ' reste à None même lorsque je met mes deux images l'une sur l'autre..
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              30 janvier 2015 à 21:35:29

              Je donne mon code pour tester la collision et qui me renvoie toujours la même chose quelle que soit la position de l'image 1 par rapport à la 2.

              import pygame
              from pygame.locals import *
              pygame.init()
              
              x = 300
              y = 10
              
              
              fenetre = pygame.display.set_mode((640, 480), RESIZABLE)
              pygame.display.set_caption("Test")
              
              
              fond = pygame.image.load("background.png").convert()
              
              image1 = pygame.sprite.Sprite()
              image1.image = pygame.image.load("image1.png").convert_alpha()
              image1.rect = image1.image.get_rect()
              image1.mask = pygame.mask.from_surface(image1.image)
              
              image2 = pygame.sprite.Sprite()
              image2.image = pygame.image.load("image2.png").convert_alpha()
              image2.rect = image2.image.get_rect()
              image2.mask = pygame.mask.from_surface(image2.image)
              
              pygame.display.flip()
              
              done = False
              
              #BOUCLE Principale
              while not done:
              
                  for event in pygame.event.get():
                      if event.type == pygame.QUIT:
                          done = True
              
              
                  fenetre.blit(fond, (0,0))
              
              
                  fenetre.blit(image1.image, (x,y))
                  fenetre.blit(image2.image, (x,250))
              
                  y += 5
                  if y == 300:
                      y=0
              
              #afficher l'état de la collision entre les deux sprites - TEST
                  font = pygame.font.Font(None, 50)
                  test_collision = pygame.sprite.collide_rect(image1, image2)
                  collision_char = str(test_collision)
                  collision = font.render(collision_char, 1, (0,0,0))
                  fenetre.blit(collision, (10,30))
              
              
                  pygame.display.flip()
              
              
                  pygame.time.Clock().tick(30)
              
              pygame.quit()

              Aidez-moi svp !

              • Partager sur Facebook
              • Partager sur Twitter
                30 janvier 2015 à 22:05:12

                Modifier la position du blit ne change pas la position des sprites ... ce qui change la position d'un sprite c'est son attribut rect.
                • Partager sur Facebook
                • Partager sur Twitter

                Python c'est bon, mangez-en. 

                Anonyme
                  31 janvier 2015 à 13:34:19

                  D'accord, mais concrètement je fais comme s'il te plait ?
                  • Partager sur Facebook
                  • Partager sur Twitter
                    31 janvier 2015 à 22:45:07

                    Tu positionnes: image1.rect.topleft = x, y

                    Tu blites: fenetre.blit(image1.image, image1.rect)

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Python c'est bon, mangez-en. 

                      31 janvier 2015 à 23:11:51

                      J'ai revu ton code:

                      !/usr/bin/python3

                      - coding: utf-8 -

                      import pygame from pygame.locals import *

                      pygame.init()

                      fenetre = pygame.display.set_mode((640, 480), RESIZABLE) pygame.display.set_caption("Test")

                      fond = pygame.image.load("background.png").convert()

                      image1 = pygame.sprite.Sprite() image1.image = pygame.image.load("image1.png").convert_alpha() image1.rect = image1.image.get_rect() image1.rect.topleft = 300, 20 image1.mask = pygame.mask.from_surface(image1.image)

                      image2 = pygame.sprite.Sprite() image2.image = pygame.image.load("image2.png").convert_alpha() image2.rect = image2.image.get_rect() image2.rect.topleft = 250, 150 image2.mask = pygame.mask.from_surface(image2.image)

                      clock = pygame.time.Clock()

                      done = False font = pygame.font.Font(None, 50)

                      BOUCLE Principale

                      while not done:

                      for event in pygame.event.get():
                          if event.type == pygame.QUIT:
                              done = True
                      
                      fenetre.blit(fond, (0,0))
                      
                      fenetre.blit(image1.image, image1.rect)
                      fenetre.blit(image2.image, image2.rect)
                      
                      image1.rect.y += 5
                      if image1.rect.y > 300:
                          image1.rect.y=0
                      
                      #afficher l'état de la collision entre les deux sprites - TEST
                      test_collision = pygame.sprite.collide_rect(image1, image2)
                      collision_char = "Collision" if test_collision else "Pas collision"
                      collision = font.render(collision_char, 1, (200,200,200))
                      fenetre.blit(collision, (10,30))
                      
                      pygame.display.flip()
                      
                      clock.tick(30)
                      

                      pygame.quit()

                      </pre>
                      • Partager sur Facebook
                      • Partager sur Twitter
                        1 février 2015 à 1:06:25

                        Je vais tester ça mais j'espère que ça prend réellement la forme de l'image et non que ça prend juste un rectangle autour.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 février 2015 à 8:22:36

                          J'ai juste corriger l'exemple que tu avais donné. Dans celui-ci, tu as utilisé pygame.sprite.collide_rect- Si tu le remplaces par pygame.sprite.collide_mask ça fonctionnera.

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Pygame : Gestion mask de collision

                          × 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