Pygame: Colisión a los lados de Sprite

¿Hay una manera en pygame de buscar una colisión entre un lado particular de un sprite y un lado particular de otro sprite en pygame? Por ejemplo, si la parte superior del sprite A choca con la parte inferior del Sprite B, devuelva Verdadero.

Estoy seguro de que hay una forma de hacerlo, pero no puedo encontrar ningún método en particular en la documentación.

¡Gracias!

No hay ninguna función para obtener colisión de lados en PyGame.

Pero puede intentar usar pygame.Rect.collidepoint para probar si A.rect.midleft , A.rect.midright , A.rect.midtop , A.rect.midbottom , A.rect.topleft , A.rect.bottomleft , A.rect.topright , A.rect.bottomright están dentro de B.rect ( pygame.Rect ).


EDITAR:

Código de ejemplo. Usa las flechas para mover al jugador y toca al enemigo.

( probablemente no sea la solución óptima )

 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() 

introduzca la descripción de la imagen aquí


EDITAR (08.2016): versión con colilisions rect , rect_ratio , circle

GitHub: furas / python-examples / pygame / collisions

introduzca la descripción de la imagen aquí

Como ha dicho Furas, no, no hay manera de evitar colisiones laterales en Pygame más allá del sistema de puntos que estableció. E incluso ese no te dará lo que quieres, porque nunca puedes estar seguro de en qué dirección se produjo la colisión al tratar con filas, columnas o esquinas de rectangularjs.

Es por esto que la mayoría de los tutoriales recomiendan guardar tus sprites en la dirección inicial. Luego se mueve en la dirección opuesta en caso de una colisión.

La lógica detrás de la colisión es así:

 #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 

Si desea detectar una colisión lateral (como si el objeto A golpeara el objeto B en el lado), puede hacer lo siguiente:

 #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