无法检测 Pygame 中的多个矩形碰撞
我一直在开发一个简单的 Pygame 项目,该项目涉及模拟开放区域中的运动传感器灯,并创建了多个送货骑手、吸烟者和平民的实例。当用户处于一定距离内时,地面上的灯就会亮起。我面临的问题是,当物体与驱动程序发生碰撞时, CollideRect 根本不会触发(使用 print 语句进行测试)。理想情况下,除了司机和吸烟者之外,所有平民都应该相互碰撞和反射。
这是我的虚拟原型的记录: LUmen 模拟器
显示设置和距离函数
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
对象实例化
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,但无济于事
我可以知道吗是否有更有效的方法来解决这个问题?我正在考虑使用精灵而不是位块传送,但不确定它是否会有什么不同。另外,我是 Pygame 的新手,所以任何帮助或建议将不胜感激!
I'm been working on a simple Pygame project that involves simulating motion sensor lights in open areas, and have created multiple instances of delivery riders, smokers and civilians. When users are within a certain distance, the lights on the ground would light up. The problem I faced was, when objects came into collision with the drivers, colliderect did not trigger at all (tested with print statements). Ideally all the civilians should collide and reflect off one another except the driver and smokers.
Here is a recording of my virtual prototype:
LUmen Simulator
Display setup and distance function
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
Instantiation of 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()
Running the game
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()
I have tried euclidean distance but it only worked for the edges of the display (gif)
I also tried implementing colliderect logic here https://youtu.be/1_H7InPMjaY, but to no avail
May I know if there is a more efficient way to go about this? I was thinking of using sprites instead of blit, but not sure if it would be any different. Also, I'm new to Pygame, so any help or suggestions would be appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您必须在碰撞测试之前更新矩形的位置:
You have to update the position of the rectangle before the collision test: