Why is Surface.unlock failing to unlock the surface for blitting?

孤者浪人 提交于 2020-01-04 12:49:31

问题


I'm trying to apply a numpy array of alpha values to a surface. I'm able to do so, but the surface remains locked after this operation such that I cannot blit the surface to my display.

Below is a simple test case, using the alpha array, g, pickled here.

import pygame as pg

pg.init()
screen = pg.display.set_mode((600, 600))

s = pg.Surface((100, 100)).convert_alpha()
s.fill((126, 126, 126))  # make it grey
pxa = pg.surfarray.pixels_alpha(s)  # reference the alpha values

pxa[::] = g  # g is the array of alpha values
del pxa  # shouldn't deleting the array be enough to unlock the surface?
s.unlock()  # explicitly unlock for good measure

s.get_locked()  # returns True

So what gives? I tried blitting the surface to screen anyway, but (predictably) I get an error about s still being locked.

Advice would be most welcome!


回答1:


Make a sprite class and put the values in an update function. This way, the array will be created and destroyed within the scope of the function. Here's an example in which you can make the grey block transparent by pressing the space bar:

import pygame
from pygame.locals import QUIT, KEYDOWN, K_ESCAPE, K_SPACE, SRCALPHA


class Game(object):
    def __init__(self):
        pygame.init()
        self.width, self.height = 800, 800
        pygame.display.set_caption("Surfarray test")
        self.screen = pygame.display.set_mode((self.width, self.height))
        self.background = pygame.Surface((self.width, self.height))
        self.background.fill((255, 255, 255))
        self.background.convert()
        self.bar = pygame.Surface((200, 100))
        self.bar.fill((255, 0, 0))
        self.bar.convert()

        self.sprite = pygame.sprite.GroupSingle()
        self.sprite.add(CustomSprite(pygame.Rect(5, 5, 100, 100)))

    def input(self):
        for event in pygame.event.get():

            if event.type == QUIT:
                return False

            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    return False
                if event.key == K_SPACE:
                    # make bar transparent by pressing the space bar
                    self.sprite.update()

    def main(self):
        while True:
            if self.input() is False:
                return False
            self.draw()

    def draw(self):
        self.screen.blit(self.background, (0, 0))
        self.screen.blit(self.bar, (5, 5))
        self.sprite.draw(self.screen)
        pygame.display.update()


class CustomSprite(pygame.sprite.Sprite):
    def __init__(self, rect):
        pygame.sprite.Sprite.__init__(self)
        self.rect = rect
        # SRCALPHA flag makes the pixel format include per-pixel alpha data
        self.image = pygame.Surface((rect.width, rect.height), SRCALPHA)
        self.image.convert_alpha()
        self.image.fill((126, 126, 126))

    # magic happens here
    def update(self):
        pxa = pygame.surfarray.pixels_alpha(self.image)
        pxa[:] = 100  # make all pixels transparent

if __name__ == "__main__":
    game = Game()
    game.main()


来源:https://stackoverflow.com/questions/19058022/why-is-surface-unlock-failing-to-unlock-the-surface-for-blitting

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!