python - pygame.Surface 和鼠标之间的碰撞检测不起作用

标签 python pygame pygame-surface

我正在尝试制作像素艺术 Canvas 。

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 个独特的曲面,这很有效。然后我尝试实现每个 block 和鼠标之间的碰撞检测,但失败了。

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)

然后我对它可能失败的原因进行了不同的测试。这是其中之一。我将更改单个 block 的颜色,在我们的例子中是第 10 个 block self.__blocks[10].fill((255, 0, 0))为红色,这样我们就知道要单击哪个框。然后我们将尝试检查该特定 block 的碰撞。

def testBlock(self, pos):
    block = self.__blocks[10].get_rect()
    if block.collidepoint(pos[0], pos[1]):
        print(block.x)

它不起作用,但奇怪的是它适用于第一个 block (在第 0 个索引中),并且无论我测试哪个表面,它都只适用于第一个 block 。任何有关如何解决此问题的想法将不胜感激。以下是复制并粘贴代码。

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()

最佳答案

当您在 Surface 上调用 .get_rect() 时,它不知道其当前位置,因为那不是 Surface 信息。所以在碰撞检测之前需要将位置分配给 Rect。

使用当前的代码布局,您可以在构建期间执行此操作。由于 Canvass block 位置现在保存在 __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 - pygame.Surface 和鼠标之间的碰撞检测不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63430350/

相关文章:

python - Python 3.3 的 Pygame 安装

python-3.x - Pygame set_alpha 不适用于尝试的背景淡入淡出

pygame - 使用 pygame 以编程方式创建和填充 8 位表面的最快方法

python - 在两列之间进行匹配并从 Pandas 中的另一列中获取值(value)

python - 对导出到excel的字典进行排序?

python - 如何使用 PCA 和 scikit-learn 进行标准化

python - Pygame粒子效果

python - Django 将 isoformat 字符串日期时间转换为元组并出现错误

python - 重新启动游戏(重置滚动屏幕)

python - 如何用Pygame画一个棋盘并移动棋盘上的棋子?