python - 如何有效地掩盖pygame中的表面

标签 python pygame masking

我按照 nkorth 的建议在 pygame 中屏蔽了一个表面回答问题is there any way to only blit or update in a mask ,每帧更新蒙版和蒙版表面。虽然使用他的方法可以实现这一点,但帧速率会立即下降,而且任何时候只有一个该表面的实例被渲染在屏幕上。

Here是我要屏蔽的图像,here是它在应用程序上的样子。这些其他的圆圈并不重要,它们是按顺序创建的,并在另一个圆圈之上绘制。我尝试将图像压缩到 100kb(超过原始大小的 10 倍),但这只起到了一点点作用。它仍然运行不佳。

在 pygame 上这甚至可能吗?如果是,那又如何?

这是相应的类:

class NoiseCircle(Circle):

    def __init__(self, center=SCREEN_CENTER, radius=5):
        # init code

    ...

    def draw(self, surf):
        self.masked.blit(self.noise_image, (0, 0))
        self.mask.fill((0, 0, 0, 0))
        pygame.draw.circle(self.mask, (255, 255, 255), self.center, self.radius)
        self.masked.blit(self.mask, (0, 0), None, pygame.BLEND_RGBA_MULT)
        pygame.draw.circle(self.masked, (0, 0, 0), self.center, self.radius, 1)
        surf.blit(self.masked, (0, 0))

主循环只是将显示表面传递给 draw() 并负责对象渲染。

最佳答案

很难说你程序的瓶颈在哪里。可能是 draw.circle。试试我的代码,它实现了我自己的圆绘制算法(注意,它不是精确的圆)。在 Windows 上使用 pygame 1.9.2 进行测试,相当慢的计算机 - Atom 1.6 GHz,它给了我大约 40 毫秒(参见代码中的 DT)。然后尝试你的实现,看看它是更快还是更慢。比较一下会很有趣。顺便说一句,使用 colorkey 怎么样?

def circle(r, x0, y0, dest, value):
    x1 = int(r / math.sqrt(2))
    h = []
    x = x1
    while(1):
        x += 1
        if x == r:
            h.append(ch/3)
            break
        ch = int(math.sqrt(r**2-x**2))
        h.append(ch)
    p = 0
    dest[x0-x1:x0+x1+1, y0-x1:y0+x1+1] = value  
    while p < len(h):
        dest[x0+x1+p+1, y0-h[p]:y0+h[p]+1] = value
        dest[x0-x1-p-1, y0-h[p]:y0+h[p]+1] = value
        dest[x0-h[p]:x0+h[p]+1, y0-x1-p-1] = value
        dest[x0-h[p]:x0+h[p]+1, y0+x1+p+1] = value
        p += 1

def put_alpha(Dest, Src):                       # write alpha values
    ref = pygame.surfarray.pixels_alpha (Dest)
    numpy.copyto(ref, Src) 
    del ref


Layer = pygame.Surface ((w,h),flags = pygame.SRCALPHA)
Layer.fill(0xff4B432E)
Mask = numpy.zeros((w,h), dtype = numpy.uint8)
Mask[:] = 255
cur_time = pygame.time.get_ticks()
old_time = cur_time

circle(125, 400, 300, Mask, 125)
circle(75, 400, 300, Mask, 255)
put_alpha(Layer, Mask)

cur_time = pygame.time.get_ticks()
DT = cur_time - old_time
print DT

更新: 首先,自定义圆函数的运行速度比 pygame 慢 5 倍,所以它不会减慢速度。 我总结了一些不同变体的性能结果。首先,确保你在任何地方都使用 24 位表面,除非你想要完整的 256 级透明度,否则仅此一项就可以提供更好的结果。如果运行以下示例,输出必须为“24 32 24”。这些是相应表面的位深度。这对于这种特殊情况是最佳的。

pygame.init()
w = 800
h = 600
DISP = pygame.display.set_mode((w, h), 0, 24)
clock = pygame.time.Clock( ) 

Noise = pygame.Surface ((w,h))
Noise.fill((110,0,10))  
color24bit = (169, 163, 144)    # r g b
color = (169, 163, 144, 255)    # r g b a
color_a = (169, 163, 144, 112)  # r g b a
Layer = pygame.Surface ((w,h), flags = pygame.SRCALPHA)
Layer.fill(color)       # ( 169, 163, 144, 255)

Layer_colorkey = pygame.Surface ((w,h))
Layer_colorkey.fill(color24bit)
color_key = (50, 50, 50)
Layer_colorkey.set_colorkey(color_key)

print Noise.get_bitsize(), Layer.get_bitsize(), Layer_colorkey.get_bitsize()

Mask = numpy.zeros((w,h), dtype = numpy.uint8)
Mask[:] = 255

t=0
cur_time = pygame.time.get_ticks()
old_time = cur_time

# 1. blit with per-pixel alpha and custom Mask array
while t < 0:
    circle(296, 400, 300, Mask, 112)
    circle(15, 400, 300, Mask, 255)
    put_alpha(Layer, Mask)
    Noise.blit(Layer,(0,0))
    DISP.blit(Noise,(0,0))
    t += 1

# 2. blit with per-pixel alpha and draw functions
while t < 0:
    pygame.draw.circle(Layer, color_a, (400,300), 296, 0)
    pygame.draw.circle(Layer, color, (400,300), 15, 0)
    Noise.blit(Layer,(0,0))
    DISP.blit(Noise,(0,0))
    t += 1

# 3. blit with colorkey 
while t < 1:
    pygame.draw.circle(Layer_colorkey, color_key, (400,300), 296, 0)
    pygame.draw.circle(Layer_colorkey, color, (400,300), 15, 0)
    Noise.blit(Layer_colorkey,(0,0))
    DISP.blit(Noise,(0,0))
    t += 1

cur_time = pygame.time.get_ticks()
DT = cur_time - old_time
print "time:", DT

结论:
1. 应用自定义 mask 阵列的完整 alpha:最慢,但您可以完全控制 mask 形式,并可以制作出很酷的透明效果。
2. Full alpha + 只使用内置的绘制函数,只需要用需要的alpha值定义颜色。稍微快一点(ITPC),但不能直接控制颜色值。
3. 带色键的普通 24 位表面。比上面快 2 倍,但没有自定义透明度。

关于python - 如何有效地掩盖pygame中的表面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28692861/

相关文章:

python - 通过 Python 中的元组比较项目

python - 如何映射或排序两个不同数据帧的值?

Python Pygame如何将矩形放在屏幕中央

geometry - 通过 raphael js 圆形图像蒙版?

java - 属性文件中的屏蔽

c# - 将不同的参数传递给 C# 动态库

python - 如何使用 Python 和 PyGame 在 OpenGL 上显示 2D 形状

python - Pygame 滚动条播放音量低还是高。?

ios - 在不规则形状图像上添加相机图层 IOS

python - Django 1.6.5 中的 Syncdb 命令不会在 models.py 中创建新的模型类 - 表示表已存在