如何在Pygame中有效地遮罩表面 [英] How to efficiently mask a surface in pygame

查看:100
本文介绍了如何在Pygame中有效地遮罩表面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据

I'm masking a surface in pygame as suggested by nkorth in response to the question is there any way to only blit or update in a mask, updating the mask and masked surfaces each frame. And while it is possible to achieve this using his method, the frame rate drops immediately, and that's with just one instance of this surface being rendered on the screen at any one time.

此处是我要遮罩的图像,并且此处是应用程序上的外观.其他这些圆圈并不重要,它们是按顺序创建的,并在彼此之上绘制.我尝试将图像压缩到100kb(是原始大小的10倍以上),但这只是有所帮助.它仍然运行不佳.

Here is the image I want to mask, and here is how it should look like on the application. These other circles are not important, they are created sequentially and are drawn on top of one another. I tried compressing the image to 100kb (more than 10 times it's original size), but that only helped a little bit. It still runs poorly.

在pygame上甚至有可能吗?如果是这样,那怎么办?

Is this even possible on pygame? If so, then how?

这是相应的课程:

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(),它负责对象的渲染.

The main loop just passes the display surface to draw() and that takes care of the object rendering.

推荐答案

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

It is hard to tell where is the bottleneck in you program. Probably it is draw.circle. Try with my code, it implements my own circle drawing algorithm (note, it is not precise circle). Tested with pygame 1.9.2 on Windows, quite slow computer - Atom 1.6 GHz, and it gives me around 40 milliseconds (see DT in code). Then try your implementation and see if it is faster or slower. It would be interesting to compare. BTW, what about using 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".这些是对应表面的位深度.对于这种特殊情况,这是最佳选择.


Update: First, the custom circle function acts ca 5 times slower than pygame's, so it is not what can slow things down. I've sumed up some performance results with various variants. First, make sure you use 24 bit surfaces everywhere, unless you want full 256 grades of transparency, this alone can give better results. If you run following example the output must give "24 32 24". Those are bit depths of corresponding surfaces. This would be optimal for this particular case.

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.带有自定义蒙版"数组的完整Alpha:最慢,但是您可以完全控制蒙版形式,并且可以制作具有透明效果的炫酷效果.
2. Full alpha +只需使用内置的绘制功能,只需使用所需的alpha值定义颜色即可.稍快一点(ITPC),但无法直接控制颜色值.
3.使用colorkey正常的24位表面.比上面的速度快2倍,但没有自定义透明度.

Conclusion:
1. Full alpha with applied custom Mask array: slowest, but you have full control of the mask form and can make cool effects with transparency.
2. Full alpha + just use built-in draw functions, just define color with needed alpha value. A litle bit faster (ITPC), but no direct control over color values.
3. Normal 24 bit surface with colorkey. 2x faster than above, but no custom transparency.

这篇关于如何在Pygame中有效地遮罩表面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆