PyGame Collision?

2019-01-15 17:05发布

问题:

How do I find collisions between characters and images within PyGame? I have drawn a player from an image, and have drawn the walls from tiles, so how would I detect these collisions?

回答1:

If you use the pygame Rect class to represent the boundaries of your object, you can detect whether two are colliding by using the Rect.colliderect function. For example:

import pygame

a = pygame.Rect((1, 1), (2, 2))
b = pygame.Rect((0, 0), (2, 2))
c = pygame.Rect((0, 0), (1, 1))
a.colliderect(b)
# 1
a.colliderect(c)
# 0
b.colliderect(c)
# 1

a is colliding with b, and b is colliding with c, but a is not colliding with c. Note that rects that share a boundary are not colliding.

Pygame also supports letting you use a Rect as the position for an image when you want to 'blit' it onto the screen.



回答2:

Yes, but make sure to use sprite classes for the rectangles, sprite info available here. So, for each sprite make a rect:

class object(pygame.sprite.Sprite):
def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.x = 0
    self.y = 0
    self.image = pygame.image.load('object.png')
    self.rect = pygame.Rect(self.x,self.y,32,32) #The rect for collision detection.

I know it looks like a lot, and thats what I thought when I started with sprites, but trust me, it is totally worth it.



回答3:

import pygame
pygame.init()
class Sprite(pygame.sprite.Sprite):
    def __init__(self, image, location):
        self.image = pygame.image.load(urimage)
...

then make collision groups and use pygame.sprite.spritecollide()



回答4:

There are many ways you can do collision detection in Pygame. The Rect(@Darthfett) and spritecollide methods are the more popular ones, but there are 2 others that you can use:

Method 1:

This method is really easy to program, but does increase the sloppiness of coding, has many restrictions, and usually is not the best thing to use.

What you do is choose a certain color, check the pixel colors around the object, and make it collide if you detect a certain color. This allows simple games, like "Don't Let Your Mouse Touch The Color Black", and other simple programs.

Method 2:

This method is by far my favorite, and I use this in 90% of all my programs. You detect the collision by calculation. This is where you take the coordinates of objects 1 and 2, see how close they are to each other, and do collisions based off of that. That method allows lots of flexibility with collisions, isn't too sloppy if done right, and is quite simple. It may take a bit of tweaking, and you will need to test the program many times, but the results are well worth it. This method also allows detection between invisible objects, and it allows the easy adjustment of collision boxes, e.g. if there is a wizard, or just anything, and you die when you come a certain distance from it. This method really is not as popular as it should be, but I assure you it works. The 2 easiest forms of collision with this method are with circular and with rectangular collision.



回答5:

Lets say you have a player class that looks something like this, I like using pygame.sprite.collide_rect() in this case we'll also have a wall class.

class Player(pygame.sprite.Sprite):
    def __init__(self,x,y):

        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((32,32))
        self.rect = Rect(x, y, 32, 32)

    def move(self, px, py):

        if px != 0:
            self.move_on_axis(px, 0)
        if py != 0:
            self.move_on_axis(0, py)

    def move_on_axis(self, px, py):
        self.rect.x += px
        self.rect.y += py

Here is where we cheek for Collisions with anything in walls group, which we add when ever we make a new wall.

        for wall in walls:
            if pygame.sprite.collide_rect(self, wall):   
                if px > 0:
                     self.rect.right = wall.rect.left
                if px < 0:
                    self.rect.left = wall.rect.right
                if py > 0:
                    self.rect.bottom = wall.rect.top                        
                if py < 0:
                    self.rect.top = wall.rect.bottom

class Wall(pygame.sprite.Sprite):
    def __init__(self, wx):
        super().__init__()
        all_Sprite_List.add(self)
        walls.add(self)
        self.image = pygame.Surface((32,32))
        self.rect = Rect(wx[0], wx[1], 32, 32)


回答6:

Create a function that checks for the x, y, w, h perimeters of both objects and create an if statement as such that will check if the two objects are colliding:

def col_check(x,y,w,h,x2,y2,w2,h2):
if (x < (x2 + w2) and (x + w) > x2 and y < (y2 + h2) and (h + y) > y2):                     
    # Do something here                                                

Now you can just call the function with the objects perimeters as the arguments.