无法在 Pygame 中检测到多个矩形冲突
Unable to detect multiple Rect Collisions in Pygame
我一直在从事一个简单的 Pygame 项目,该项目涉及在开放区域模拟运动传感器灯,并创建了多个送货员、吸烟者和平民的实例。当用户在一定距离内时,地面上的灯会亮起。我遇到的问题是,当 objects 与 driver 发生碰撞时,colliderect 根本没有触发(用 print 语句测试)。理想情况下,除了 driver 和吸烟者之外,所有平民都应该相互碰撞和反射。
这是我的虚拟原型的录音:
LUmen Simulator
显示设置和距离功能
screen = width,height = 800,600
fps = 60
cellsize = 50
padding = 40 # create identations from the window
rows = cols = (width - 50) // cellsize
print(rows, cols)
def euclid_dist(mX, mY, x, y): # distance to grid
dist = math.sqrt((mX - x)**2 + (mY - y)**2)
if dist <= 80:
return True
else:
return False
objects
的实例化
class Cell_1: # sample of user object
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = random.randrange(20, height-20) #y position
self.x_speed = 2
self.y_speed = 2
self.image = char # pre-loaded img
self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))
def wander(self):
self.x += self.x_speed
self.y += self.y_speed
if self.x <= 30 or self.x >= width - 30:
self.x_speed *= -1
elif self.y <= 30 or self.y >= height - 30:
self.y_speed *= -1
def draw(self):
surface.blit(self.image, (self.x, self.y))
class Cell_2:
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = random.randrange(20, height-20) #y position
self.x_speed = 2
self.y_speed = 2
self.image = char # pre-loaded img
self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))
def wander(self):
self.x += self.x_speed
self.y += self.y_speed
if self.x <= 30 or self.x >= width - 30:
self.x_speed *= -1
elif self.y <= 30 or self.y >= height - 30:
self.y_speed *= -1
def draw(self):
surface.blit(self.image, (self.x, self.y))
class Driver:
# make driving linear
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = height - 20 #bottom of screen
self.y_speed = 12
self.x_speed = 12
self.image = char3
self.image = pygame.transform.scale(self.image, (cellsize+20, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center = (self.x, self.y))
def wander(self):
if self.y <= 20: # height
self.y = height
self.x = random.randrange(20, width-20)
else:
self.y -= self.y_speed
def draw(self):
surface.blit(self.image, (self.x, self.y))
rects = []
cells_1 = []
for i in range(2):
cell = Cell_1()
cells_1.append(cell)
rects.append(cell) # for collision detection
cells_2 = []
for i in range(2):
cell = Cell_2()
cells_2.append(cell)
rects.append(cell)
driver = Driver()
运行游戏
while running:
warm_col = (255, random.randint(0, 255), 0)
surface.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
# upon closing the window with mouse
running = False
driver.wander()
driver.draw()
for npc in cells_1:
npc.wander()
npc.draw()
for npc in cells_2:
npc.wander()
npc.draw()
for rectangle in rects:
if (rectangle.rect.colliderect(driver.rect)):
rectangle.x_speed *= -1
rectangle.y_speed *= -1
(mX, mY) = pygame.mouse.get_pos()
char1 = pygame.transform.scale(char1, (cellsize-10, cellsize+20))
surface.blit(char1, (mX, mY))
for row in range(rows):
for col in range(cols):
for i in rects:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
for i in cells_1:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
for i in cells_2:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(driver.x, driver.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
pygame.display.update()
pygame.time.Clock().tick(fps)
pygame.mouse.set_visible(False)
pygame.quit()
我试过欧几里得距离,但它只适用于显示器的边缘 (gif)
我也尝试在此处实现碰撞逻辑 https://youtu.be/1_H7InPMjaY,但无济于事
我可以知道是否有更有效的方法来解决这个问题?我正在考虑使用 sprites 而不是 blit,但不确定是否会有任何不同。另外,我是 Pygame 的新手,所以任何帮助或建议都将不胜感激!
您必须在碰撞测试之前更新矩形的位置:
driver.rect.x = round(self.y)
driver.rect.y = round(self.y)
for rectangle in rects:
rectangle.rect.x = round(rectangle.x)
rectangle.rect.y = round(rectangle.y)
if rectangle.rect.colliderect(driver.rect):
rectangle.x_speed *= -1
rectangle.y_speed *= -1
我一直在从事一个简单的 Pygame 项目,该项目涉及在开放区域模拟运动传感器灯,并创建了多个送货员、吸烟者和平民的实例。当用户在一定距离内时,地面上的灯会亮起。我遇到的问题是,当 objects 与 driver 发生碰撞时,colliderect 根本没有触发(用 print 语句测试)。理想情况下,除了 driver 和吸烟者之外,所有平民都应该相互碰撞和反射。
这是我的虚拟原型的录音: LUmen Simulator
显示设置和距离功能
screen = width,height = 800,600
fps = 60
cellsize = 50
padding = 40 # create identations from the window
rows = cols = (width - 50) // cellsize
print(rows, cols)
def euclid_dist(mX, mY, x, y): # distance to grid
dist = math.sqrt((mX - x)**2 + (mY - y)**2)
if dist <= 80:
return True
else:
return False
objects
的实例化class Cell_1: # sample of user object
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = random.randrange(20, height-20) #y position
self.x_speed = 2
self.y_speed = 2
self.image = char # pre-loaded img
self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))
def wander(self):
self.x += self.x_speed
self.y += self.y_speed
if self.x <= 30 or self.x >= width - 30:
self.x_speed *= -1
elif self.y <= 30 or self.y >= height - 30:
self.y_speed *= -1
def draw(self):
surface.blit(self.image, (self.x, self.y))
class Cell_2:
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = random.randrange(20, height-20) #y position
self.x_speed = 2
self.y_speed = 2
self.image = char # pre-loaded img
self.image = pygame.transform.scale(self.image, (cellsize, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center= (self.x, self.y))
def wander(self):
self.x += self.x_speed
self.y += self.y_speed
if self.x <= 30 or self.x >= width - 30:
self.x_speed *= -1
elif self.y <= 30 or self.y >= height - 30:
self.y_speed *= -1
def draw(self):
surface.blit(self.image, (self.x, self.y))
class Driver:
# make driving linear
def __init__(self):
self.x = random.randrange(20, width-20) #x position
self.y = height - 20 #bottom of screen
self.y_speed = 12
self.x_speed = 12
self.image = char3
self.image = pygame.transform.scale(self.image, (cellsize+20, cellsize+20))
self.rect = pygame.Surface.get_rect(self.image, center = (self.x, self.y))
def wander(self):
if self.y <= 20: # height
self.y = height
self.x = random.randrange(20, width-20)
else:
self.y -= self.y_speed
def draw(self):
surface.blit(self.image, (self.x, self.y))
rects = []
cells_1 = []
for i in range(2):
cell = Cell_1()
cells_1.append(cell)
rects.append(cell) # for collision detection
cells_2 = []
for i in range(2):
cell = Cell_2()
cells_2.append(cell)
rects.append(cell)
driver = Driver()
运行游戏
while running:
warm_col = (255, random.randint(0, 255), 0)
surface.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
# upon closing the window with mouse
running = False
driver.wander()
driver.draw()
for npc in cells_1:
npc.wander()
npc.draw()
for npc in cells_2:
npc.wander()
npc.draw()
for rectangle in rects:
if (rectangle.rect.colliderect(driver.rect)):
rectangle.x_speed *= -1
rectangle.y_speed *= -1
(mX, mY) = pygame.mouse.get_pos()
char1 = pygame.transform.scale(char1, (cellsize-10, cellsize+20))
surface.blit(char1, (mX, mY))
for row in range(rows):
for col in range(cols):
for i in rects:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
for i in cells_1:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
for i in cells_2:
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(i.x, i.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
for row in range(rows):
for col in range(cols):
x = col * cellsize + padding
y = row * cellsize + padding
within_dist = euclid_dist(mX, mY, x, y)
npc_within = euclid_dist(driver.x, driver.y, x, y)
if within_dist == True or npc_within == True:
pygame.draw.circle(surface, warm_col, (x,y), 3)
pygame.display.update()
pygame.time.Clock().tick(fps)
pygame.mouse.set_visible(False)
pygame.quit()
我试过欧几里得距离,但它只适用于显示器的边缘 (gif) 我也尝试在此处实现碰撞逻辑 https://youtu.be/1_H7InPMjaY,但无济于事
我可以知道是否有更有效的方法来解决这个问题?我正在考虑使用 sprites 而不是 blit,但不确定是否会有任何不同。另外,我是 Pygame 的新手,所以任何帮助或建议都将不胜感激!
您必须在碰撞测试之前更新矩形的位置:
driver.rect.x = round(self.y)
driver.rect.y = round(self.y)
for rectangle in rects:
rectangle.rect.x = round(rectangle.x)
rectangle.rect.y = round(rectangle.y)
if rectangle.rect.colliderect(driver.rect):
rectangle.x_speed *= -1
rectangle.y_speed *= -1