Pygame image mouse click renders image badly

36 阅读2分钟

在使用 Pygame 创建一个简单的启动按钮时,遇到如下问题:

  • 当用户点击按钮时,按钮图像应从原始图像更新到另一个稍微不同的图像,但图像更新后显示效果很差,并且第二个图像无法正常显示。
  • 图像加载代码如下:
def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', name
        raise SystemExit, message
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()
  • 鼠标和按钮对象代码如下:
class Mouse(pygame.sprite.Sprite):
    """moves a hand on the screen, following the computer mouse"""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
        self.clicking = 0
        self.image, self.rect = load_image('game_mouse.jpg', -1)

    def update(self):
        "move the hand based on the computer mouse position"
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.clicking:
            self.rect.move_ip(5, 10)

    def click(self, target):
        "returns true if the hand collides with the target"
        if not self.clicking:
            self.clicking = 1
            hitbox = self.rect.inflate(-5, -5)
            return hitbox.colliderect(target.rect)

    def unclick(self):
        self.clicking = 0


class Button(pygame.sprite.Sprite):
    """Button class used for all menus.  Handles events"""
    def __init__(self, original_image_source, clicked_image_source, location_coordinates):
        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
        self.original_image_source = original_image_source
        self.clicked_image_source = clicked_image_source
        self.location_coordinates = location_coordinates
        self.clicked = 0
        self.image, self.rect = load_image(original_image_source, -1)
        self.rect.midtop = location_coordinates

    def update(self):
        "update on click or unclick"
        if self.clicked:
            self.image, self.rect = load_image(self.clicked_image_source, -1)
            self.rect.midtop = self.location_coordinates
        else:
            self.image, self.rect = load_image(self.original_image_source, -1)
            self.rect.midtop = self.location_coordinates

    def set_clicked(self):
        self.clicked = 1

    def set_unclicked(self):
        self.clicked = 0
  • 主方法代码如下:
def main():

    # Initialise screen
    pygame.init()
    screen = pygame.display.set_mode((1000, 600))
    pygame.display.set_caption('States of Matter')
    pygame.mouse.set_visible(0)

    background = pygame.Surface(screen.get_size())
    background = background.convert()
    background.fill((250, 250, 250))

    mouse = Mouse()
    start_button = Button("start_button_original.jpg", "start_button_clicked.jpg", (background.get_width()/2,background.get_height()/3))
    all_sprites = pygame.sprite.RenderPlain((mouse, start_button))
    clock = pygame.time.Clock()

    while 1:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                return
            elif event.type == MOUSEBUTTONDOWN:
                if mouse.click(start_button):
                    start_button.set_clicked()
            elif event.type == MOUSEBUTTONUP:
                mouse.unclick()
                start_button.set_unclicked()

        all_sprites.update()

        screen.blit(background, (0, 0))
        all_sprites.draw(screen)
        pygame.display.flip()

if __name__ == '__main__': main()

2. 解决方案

为了解决上述问题,可以对图像加载代码进行修改,以确保图像在更新后能够正常显示。

具体修改如下:

def load_image_fixed(name, colorkey=None):
    fullname = os.path.join('data', name)
    image = pygame.image.load(fullname)
    image = image.convert_alpha()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()

在将图像加载到内存后,使用 convert_alpha() 将图像转换为具有透明通道的图像,这样就可以避免在更新图像时出现显示错误。

此外,还可以修改按钮的 update() 方法,以确保图像在更新后能够正确显示。

修改后的代码如下:

def update(self):
    "update on click or unclick"
    if self.clicked:
        self.image, self.rect = load_image_fixed(self.clicked_image_source, -1)
        self.rect.midtop = self.location_coordinates
    else:
        self.image, self.rect = load_image_fixed(self.original_image_source, -1)
        self.rect.midtop = self.location_coordinates

通过这些修改,图像在更新后能够正常显示,问题得到解决。