Collisions
在Pygame中,我们使用矩形来移动物体,并且用矩形检测碰撞。
colliderect
检测两个矩形是否碰撞,但是没法确定碰撞的方向。
Rect1.colliderect(Rect2)
# collision -> return Ture
# else -> return False
collidepoint
可以确定一个矩形是否和另一个矩形的某个点碰撞(并确定碰撞方向),但是会很麻烦,并且很容易遗漏某些碰撞。
Rect1.collidepoint(x, y)
# x,y is the point on a Rect
综合考虑之后,
我们通常使用colliderect
来检测碰撞,然后根据两个矩形的相对位置确定碰撞方向。
案例
一个矩形(和边框的碰撞)
# rect1
rect1 = pygame.Rect(100, 100, 50, 50)
color1 = (255, 255, 255)
speed_1_x = 5
speed_1_y = 5def update_rect():global speed_1_x, speed_1_yrect1.x += speed_1_xrect1.y += speed_1_y# rect 和边界的碰撞:if rect1.left <= 0 and speed_1_x <0:speed_1_x *= -1elif rect1.right >= witdth and speed_1_x > 0:speed_1_x *= -1if rect1.top <= 0 and speed_1_y < 0 :speed_1_y *= -1elif rect1.bottom >= height and speed_1_y > 0:speed_1_y *= -1pygame.draw.rect(screen, color1, rect1)# 在主循环中调用 update_rect()
while True:...screen.fill((30, 30, 30))update_rect()...
添加第二个矩形
注意:除了判断碰撞方向之外,还要判断矩形的速度方向,以防止矩形在碰撞后反复移动。
# rect2
rect2 = pygame.Rect(200, 200, 200, 50)
color2 = (0, 255, 0)
speed_2_x = 0
speed_2_y = 4 # 为了简化,rect2只在竖直方向上移动def update_rect():global speed_1_x, speed_1_y, speed_2_y...rect2.y += speed_2_y# rect 和边界的碰撞:...if rect2.top <= 0 and speed_2_y < 0 :speed_2_y *= -1elif rect2.bottom >= height and speed_2_y > 0:speed_2_y *= -1# rect1 和 rect2的碰撞collide_threshold = 20if rect1.colliderect(rect2): if abs(rect1.top - rect2.bottom) < collide_threshold and speed_1_y < 0:speed_1_y *= -1elif abs(rect1.bottom - rect2.top) < collide_threshold and speed_1_y > 0:speed_1_y *= -1elif abs(rect1.left - rect2.right) < collide_threshold and speed_1_x < 0:speed_1_x *= -1elif abs(rect1.right - rect2.left) < collide_threshold and speed_1_x > 0:speed_1_x *= -1pygame.draw.rect(screen, color1, rect1)pygame.draw.rect(screen, color2, rect2)
完整案例
两个方块的碰撞。为了简化,rect2只在竖直方向上移动。
import sys
import time
import pygame# Initialize Pygame
pygame.init()# Set up the display
witdth = 800
height = 600
screen = pygame.display.set_mode((witdth, height))# Set up the clock
clock = pygame.time.Clock()# rect1
rect1 = pygame.Rect(100, 100, 50, 50)
color1 = (255, 255, 255)
speed_1_x = 5
speed_1_y = 5# rect2
rect2 = pygame.Rect(200, 200, 300, 50)
color2 = (0, 255, 0)
speed_2_x = 0
speed_2_y = 4 # 为了简化,rect2只在竖直方向上移动def update_rect():global speed_1_x, speed_1_y, speed_2_x, speed_2_yrect1.x += speed_1_xrect1.y += speed_1_y#rect2.x += speed_2_xrect2.y += speed_2_y# rect 和边界的碰撞:if rect1.left <= 0 and speed_1_x <0:speed_1_x *= -1elif rect1.right >= witdth and speed_1_x > 0:speed_1_x *= -1if rect1.top <= 0 and speed_1_y < 0 :speed_1_y *= -1elif rect1.bottom >= height and speed_1_y > 0:speed_1_y *= -1if rect2.top <= 0 and speed_2_y < 0 :speed_2_y *= -1elif rect2.bottom >= height and speed_2_y > 0:speed_2_y *= -1#以 HH:MM:SS 的格式 输出当前时间 form_time1 = time.strftime("%H:%M:%S", time.localtime())print('rect2 to bottom', 'time= ', form_time1)# rect1 和 rect 2的碰撞collide_threshold = 20if rect1.colliderect(rect2): if abs(rect1.top - rect2.bottom) < collide_threshold and speed_1_y < 0:speed_1_y *= -1if abs(rect1.bottom - rect2.top) < collide_threshold and speed_1_y > 0:speed_1_y *= -1if abs(rect1.left - rect2.right) < collide_threshold and speed_1_x < 0:speed_1_x *= -1if abs(rect1.right - rect2.left) < collide_threshold and speed_1_x > 0:speed_1_x *= -1# Draw the rectpygame.draw.rect(screen, color1, rect1)pygame.draw.rect(screen, color2, rect2)while True:# Handle eventsfor event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()screen.fill((30, 30, 30))update_rect()# Update the displaypygame.display.flip()# Cap the frame rateclock.tick(60)