簡體   English   中英

如何有效地屏蔽pygame中的表面

[英]How to efficiently mask a surface in pygame

我正在按照nkorth的建議屏蔽pygame中的表面以回答問題是否有任何方法只能在掩碼中進行blit或更新,每幀更新掩碼和蒙版表面。 雖然可以使用他的方法實現這一點,但幀速率會立即下降,而且這個表面的一個實例在任何時候都會在屏幕上呈現。

是我要掩蓋的圖像, 是應用程序的外觀。 這些其他圓圈並不重要,它們是按順序創建的,並且彼此重疊繪制。 我嘗試將圖像壓縮到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:最慢,但您可以完全控制蒙版形式,並可以透明地制作炫酷效果。
2.完整的alpha +只使用內置的繪圖功能,只需用所需的alpha值定義顏色。 比較快(ITPC),但沒有直接控制顏色值。
3.帶有colorkey的正常24位表面。 比上面快2倍,但沒有自定義透明度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM