Python pygame.Surface和鼠标之间的碰撞检测不工作
我正在尝试为像素艺术制作画布Python pygame.Surface和鼠标之间的碰撞检测不工作,python,pygame,pygame-surface,Python,Pygame,Pygame Surface,我正在尝试为像素艺术制作画布 class Canvas: def __init__(self): self.__blocks = [] self.__positions = [] for i in range(1830): self.__blocks.append(pygame.Surface((20, 20)).convert()) for y in range(30): y
class Canvas:
def __init__(self):
self.__blocks = []
self.__positions = []
for i in range(1830):
self.__blocks.append(pygame.Surface((20, 20)).convert())
for y in range(30):
y *= 20
for x in range(61):
x = x* 20
self.__positions.append([x, y])
self.__color = False
def draw(self, window):
for i in range(1830):
self.__color = not self.__color
if self.__color:
self.__blocks[i].fill((200, 200, 200))
else:
self.__blocks[i].fill((50, 50, 50))
window.blit(self.__blocks[i], (self.__positions[i][0]
, self.__positions[i][1]))
在这里,我试图生成并绘制1830个独特的曲面,这很有效。然后我尝试在每个块和鼠标之间实现碰撞检测,但失败了
def collided(self, pos):
for i in range(1380):
block = self.__blocks[i].get_rect()
if block.collidepoint(pos[0], pos[1]):
print(block.x, block.y)
然后我做了不同的测试,看看为什么会失败。这是其中之一。我将更改单个块的颜色,在本例中是第10个块self.\u块[10]。将((255,0,0))
填充为红色,以便我们知道单击哪个框。然后,我们将尝试检查该特定块的碰撞
def testBlock(self, pos):
block = self.__blocks[10].get_rect()
if block.collidepoint(pos[0], pos[1]):
print(block.x)
它不起作用,但奇怪的是它对第一个块(在第0个索引中)起作用,并且无论我测试哪个曲面,它都只对第一个块起作用。任何关于如何解决这一问题的想法都将不胜感激。下面是复制和粘贴代码
import pygame
pygame.init()
win = pygame.display
D = win.set_mode((1220, 600))
class Canvas:
def __init__(self):
self.__blocks = []
self.__positions = []
for i in range(1830):
self.__blocks.append(pygame.Surface((20, 20)).convert())
for y in range(30):
y *= 20
for x in range(61):
x = x* 20
self.__positions.append([x, y])
self.__color = False
self.testBlock = 10
def draw(self, window):
for i in range(1830):
self.__color = not self.__color
if self.__color:
self.__blocks[i].fill((200, 200, 200))
else:
self.__blocks[i].fill((50, 50, 50))
self.__blocks[self.testBlock].fill((255, 0, 0)) # Changing the color for testing
window.blit(self.__blocks[i], (self.__positions[i][0]
, self.__positions[i][1]))
def test(self, pos):
block = self.__blocks[self.testBlock].get_rect()
if block.collidepoint(pos[0], pos[1]):
print(block.x, block.y)
canvas = Canvas()
while True:
D.fill((0, 0, 0))
pygame.event.get()
mousepos = pygame.mouse.get_pos()
canvas.draw(D)
canvas.test(mousepos)
win.flip()
在曲面上调用
.get_rect()
时,它不知道其当前位置,因为这不是曲面信息。因此,您需要在碰撞检测之前将位置指定给Rect
使用当前的代码布局,您可以在构建期间执行此操作。由于画布块位置现在保留在\uuuu rects
列表中,因此\uuu positions
列表变得多余
class Canvass:
def __init__(self):
self.__blocks = []
self.__rects = []
for y in range( 30 ):
for x in range( 61 ):
self.__blocks.append(pygame.Surface((20, 20)).convert())
self.__rects.append( self.__blocks[-1].get_rect() )
self.__rects[-1].topleft = ( x, y )
self.__color = False
self.testBlock = 10
这将为您提供一个简单的测试:
def collided(self, pos):
hit = False
for i in range( len( self.__rects ) ):
if ( self.__rects[i].collidepoint( pos[0], pos[1] ) ):
print( "Click on block %d" % ( i ) )
hit = True
break
return hit, i
.get_rect()
为rect提供块大小但位置(0,0)
您在\u位置中有实际位置,您需要
.get_rect(topleft=self.__positions[self.testBlock])
但是最好在开始时获取rect并设置其位置,以后不要使用get_rect()
您还可以使用self.image
创建类Pixel
类似于类Sprite
的类Pixel
,以保持曲面和self.rect
以保持其大小和位置。然后您可以使用组
检查与所有像素的冲突
编辑:
使用类创建类像素并将所有像素保留在
它还处理事件(MOUSEBUTTONDOWN
)以在单击任何像素时更改其颜色
在\uu块中
只有一个只有大小的曲面
和get\uu rect()
始终提供位置为(0,0)
的矩形,但实际位置为\uu位置
-您应该将两者都保留在pygame.rect中,并检查与此rect的冲突。也许最好使用self.image
创建类Sprite
,以保持曲面和self.rect
以保持大小和位置。我添加了Sprite
、Group
和MOUSEBUTTONDOWN
的示例,以在单击时更改任何块。
def test(self, pos):
block = self.__blocks[self.testBlock].get_rect(topleft=self.__positions[self.testBlock])
if block.collidepoint(pos[0], pos[1]):
print(block.x, block.y)
import pygame
# --- classes ---
class Pixel(pygame.sprite.Sprite):
def __init__(self, x, y, color, width=20, height=20):
super().__init__()
self.color_original = color
self.color = color
self.image = pygame.Surface((20, 20)).convert()
self.image.fill(self.color)
self.rect = pygame.Rect(x, y, width, height)
def handle_event(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
if self.color != self.color_original:
self.color = self.color_original
else:
self.color = (255,0,0)
self.image.fill(self.color)
# event handled
return True
# event not handled
return False
class Canvas:
def __init__(self):
# create group for sprites
self.__blocks = pygame.sprite.Group()
# create sprites
self.__color = False
for y in range(30):
y *= 20
for x in range(61):
x *= 20
self.__color = not self.__color
if self.__color:
color = (200, 200, 200)
else:
color = (50, 50, 50)
self.__blocks.add(Pixel(x, y, color))
# changing the color for testing
self.testBlock = 10
all_sprites = self.__blocks.sprites()
block = all_sprites[self.testBlock]
block.image.fill((255, 0, 0))
def draw(self, window):
# draw all sprites in group
self.__blocks.draw(window)
def test(self, pos):
# test collision with one sprite
all_sprites = self.__blocks.sprites()
block = all_sprites[self.testBlock]
if block.rect.collidepoint(pos):
print(block.rect.x, block.rect.y)
def handle_event(self, event):
for item in self.__blocks:
if item.handle_event(event):
# don't check other pixels if event already handled
return True
# --- main ---
pygame.init()
win = pygame.display
D = win.set_mode((1220, 600))
canvas = Canvas()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
canvas.handle_event(event)
#mousepos = pygame.mouse.get_pos()
#canvas.test(mousepos)
# draws (without updates, etc)
#D.fill((0, 0, 0)) # no need clean screen if it will draw all elements again
canvas.draw(D)
win.flip()