Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pygame.Surface和鼠标之间的碰撞检测不工作_Python_Pygame_Pygame Surface - Fatal编程技术网

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