Pygame: Collision by Sides of Sprite

前端 未结 4 1406
春和景丽
春和景丽 2020-11-30 12:07

Is there a way in pygame to look for a collision between the a particular side of a sprite and a particular side of another sprite in pygame? For example, if the top of spri

相关标签:
4条回答
  • 2020-11-30 12:29

    There is no function to get sides collision in PyGame.

    But you could try to use pygame.Rect.collidepoint to test if A.rect.midleft, A.rect.midright, A.rect.midtop, A.rect.midbottom, A.rect.topleft, A.rect.bottomleft , A.rect.topright, A.rect.bottomright are inside B.rect (pygame.Rect).


    EDIT:

    Example code. Use arrows to move player and touch enemy.

    (probably it is not optimal solution)

    import pygame
    
    WHITE = (255,255,255)
    BLACK = (0  ,0  ,0  )
    RED   = (255,0  ,0  )
    GREEN = (0  ,255,0  )
    BLUE  = (0  ,0  ,255)
    
    class Player():
    
        def __init__(self, x=0, y=0, width=150, height=150):
    
            self.rect = pygame.Rect(x, y, width, height)
    
            self.speed_x = 5
            self.speed_y = 5
    
            self.move_x = 0
            self.move_y = 0
    
            self.collision = [False] * 9
    
            self.font = pygame.font.SysFont("", 32)
            self.text = "";
    
        def set_center(self, screen):
            self.rect.center = screen.get_rect().center
    
        def event_handler(self, event):
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    self.move_x -= self.speed_x
                elif event.key == pygame.K_RIGHT:
                    self.move_x += self.speed_x
                elif event.key == pygame.K_UP:
                    self.move_y -= self.speed_y
                elif event.key == pygame.K_DOWN:
                    self.move_y += self.speed_y
    
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT:
                    self.move_x += self.speed_x
                elif event.key == pygame.K_RIGHT:
                    self.move_x -= self.speed_x
                elif event.key == pygame.K_UP:
                    self.move_y += self.speed_y
                elif event.key == pygame.K_DOWN:
                    self.move_y -= self.speed_y
    
        def update(self):
            self.rect.x += self.move_x
            self.rect.y += self.move_y
    
        def draw(self, screen):
    
            pygame.draw.rect(screen, WHITE, self.rect, 2)
            self.draw_point(screen, self.rect.topleft, self.collision[0])
            self.draw_point(screen, self.rect.topright, self.collision[1])
            self.draw_point(screen, self.rect.bottomleft, self.collision[2])
            self.draw_point(screen, self.rect.bottomright, self.collision[3])
    
            self.draw_point(screen, self.rect.midleft, self.collision[4])
            self.draw_point(screen, self.rect.midright, self.collision[5])
            self.draw_point(screen, self.rect.midtop, self.collision[6])
            self.draw_point(screen, self.rect.midbottom, self.collision[7])
    
            self.draw_point(screen, self.rect.center, self.collision[8])
    
        def draw_point(self, screen, pos, collision):
            if not collision:
                pygame.draw.circle(screen, GREEN, pos, 5)
            else:
                pygame.draw.circle(screen, RED, pos, 5)
    
        def check_collision(self, rect):
            self.collision[0] = rect.collidepoint(self.rect.topleft)
            self.collision[1] = rect.collidepoint(self.rect.topright)
            self.collision[2] = rect.collidepoint(self.rect.bottomleft)
            self.collision[3] = rect.collidepoint(self.rect.bottomright)
    
            self.collision[4] = rect.collidepoint(self.rect.midleft)
            self.collision[5] = rect.collidepoint(self.rect.midright)
            self.collision[6] = rect.collidepoint(self.rect.midtop)
            self.collision[7] = rect.collidepoint(self.rect.midbottom)
    
            self.collision[8] = rect.collidepoint(self.rect.center)
    
        def render_collision_info(self):
    
            text = "collision: "
            print "collision:",
    
            if self.collision[0] or self.collision[2] or self.collision[4]:
                text += "left "
                print "left",
    
            if self.collision[1] or self.collision[3] or self.collision[5]:
                text += "right "
                print "right",
    
            if self.collision[0] or self.collision[1] or self.collision[6]:
                text += "top "
                print "top",
    
            if self.collision[2] or self.collision[3] or self.collision[7]:
                text += "bottom "
                print "bottom",
    
            if self.collision[8]:
                text += "center "
                print "center",
    
            print
    
            self.text = self.font.render(text, 1, WHITE)
    
        def draw_collision_info(self, screen, pos):
            screen.blit(self.text, pos)
    
    #----------------------------------------------------------------------
    
    class Game():
    
        def __init__(self):
    
            pygame.init()
    
            self.screen = pygame.display.set_mode( (800,600) )
            pygame.display.set_caption("Side Collision")
    
            self.player = Player()
            self.enemy  = Player()
            self.enemy.set_center(self.screen)
    
    
        def run(self):
            clock = pygame.time.Clock()
    
            RUNNING = True
    
            while RUNNING:
    
                # --- events ----
    
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        RUNNING = False
    
                    elif event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            RUNNING = False
    
                    self.player.event_handler(event)
    
                # --- updates ---
    
                self.player.update()
                self.enemy.update()
    
                self.player.check_collision(self.enemy.rect)
                self.enemy.check_collision(self.player.rect)
                self.player.render_collision_info()
                self.enemy.render_collision_info()
    
                # --- draws ----
    
                self.screen.fill(BLACK)
    
                self.player.draw(self.screen)
                self.enemy.draw(self.screen)
    
                self.player.draw_collision_info(self.screen, (0,0))
                self.enemy.draw_collision_info(self.screen, (0,32))
    
                pygame.display.update()
    
                # --- FPS ---
    
                clock.tick(30)
    
            pygame.quit()
    
    #----------------------------------------------------------------------
    
    Game().run()
    

    enter image description here


    EDIT (08.2016): version with colllisions rect, rect_ratio, circle

    GitHub: furas/python-examples/pygame/collisions

    0 讨论(0)
  • 2020-11-30 12:33

    For objectA give the object this method:

    def is_collided_with(self, sprite): return self.rect.colliderect(sprite.rect)

    This return statement returns either True or False

    then in the main loop for collisions just do: if objectA.is_collided_with(ObjectB): Collision happened!

    0 讨论(0)
  • 2020-11-30 12:48

    The logic behind collision is like that:

    #Assume two surfaces
    objectA
    objectB
    
    if objectA.right > objectB.left and objectA.left < objectB.right and objectA.top < objectB.bottom and objectA.bottom > objectB.top
        #Collision happens
    

    if you want to detect side collision (as if objectA hitted objectB on the side) you can do the following:

    #Here is the code where objectA moves
    objectA.X += 10
    #Here check Collision, if collision happens objectA hitted objectB from the side
    objectA.Y += 10
    #Here check Collision again, if collision is true then objectA hitted object B from top/bottom
    
    0 讨论(0)
  • 2020-11-30 12:49

    Like Furas has said, no, there is not way to get side collisions in Pygame past the point system he set up. And even that one wont give you what you want, because you can never be sure which direction the collision happened when dealing with rows, columns or corners of Rectangles.

    This is why most tutorials recommend saving your sprites initial direction. then moving in the opposite direction in case of a collision.

    0 讨论(0)
提交回复
热议问题