python - 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 *= 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.__blocks[10].fill((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()
一个 Surface 时,它不知道它的当前位置,因为那不是 Surface 信息。因此,您需要在碰撞检测之前将位置分配给 Rect。
使用您当前的代码布局,您可以在构建期间执行此操作。随着 Canvass 块位置现在保留在__rects
列表中,__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
推荐阅读
- python - Gzip 到 base64 编码将字符添加到 JSON 字符串
- php - Symfony 4. 为什么提交的表单只是部分填充模型?
- python - 列算术
- java - AES/EAX 加密与 JCE - EAX 中的 Mac 签入失败
- javascript - 如何将对象中的字符串值转换为数字?
- api - 如何在 openapi 3.0.2 中格式化 DELETE 方法?
- go - golang中结构概念需要帮助
- excel - 将公式向下拖动一列
- python - Celery:通过 Dockerfile 中的 CMD 传递 Docker 变量
- css - 当有多个 100vh 的部分时,如何为整个网页应用线性渐变?