Python 如何在pygame中有效屏蔽曲面

Python 如何在pygame中有效屏蔽曲面,python,pygame,masking,Python,Pygame,Masking,我在pygame中屏蔽了一个曲面,正如在回答问题时建议的那样,在每一帧更新屏蔽和屏蔽曲面。虽然使用他的方法可以实现这一点,但帧速率会立即下降,这是因为在任何时候只有一个曲面的实例被渲染到屏幕上 是我想要遮罩的图像,也是它在应用程序上的外观。这些其他圆并不重要,它们是按顺序创建的,并在彼此的顶部绘制。我尝试将图像压缩到100kb(比原始大小大10倍多),但这只起了一点点作用。它仍然运行得很差 这在pygame上可能吗?如果是,那怎么办 以下是本课程的相关课程: class NoiseCircle(

我在pygame中屏蔽了一个曲面,正如在回答问题时建议的那样,在每一帧更新屏蔽和屏蔽曲面。虽然使用他的方法可以实现这一点,但帧速率会立即下降,这是因为在任何时候只有一个曲面的实例被渲染到屏幕上

是我想要遮罩的图像,也是它在应用程序上的外观。这些其他圆并不重要,它们是按顺序创建的,并在彼此的顶部绘制。我尝试将图像压缩到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上用PyGame1.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
def圆(r、x0、y0、dest、value):
x1=int(r/math.sqrt(2))
h=[]
x=x1
而(一):
x+=1
如果x==r:
h、 附加(ch/3)
打破
ch=int(数学sqrt(r**2-x**2))
h、 附加(ch)
p=0
dest[x0-x1:x0+x1+1,y0-x1:y0+x1+1]=值
而p

更新: 首先,自定义循环函数的运行速度大约是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
pygame.init()
w=800
h=600
DISP=pygame.display.set_模式((w,h),0,24)
clock=pygame.time.clock()
噪声=pygame.表面(w,h))
填充噪声((110,0,10))
color24bit=(169163144)#RGB
颜色=(169163144255)#RGB a
颜色a=(169163144112)#r g b a
Layer=pygame.Surface((w,h),flags=pygame.SRCALPHA)
图层填充(颜色)#(169、163、144、255)
Layer_colorkey=pygame.Surface((w,h))
图层\u颜色键填充(颜色24位)
颜色键=(50,50,50)
图层颜色键。设置颜色键(颜色键)
打印噪波。get_bitsize(),Layer.get_bitsize(),Layer_colorkey.get_bitsize())
掩码=numpy.zero((w,h),数据类型=numpy.uint8)
掩码[:]=255
t=0
cur\u time=pygame.time.get\u ticks()
旧时间=现在时间
# 1. 具有每像素alpha和自定义遮罩阵列的blit
当t<0时:
圆圈(2964003012)
圆圈(15、400、300、遮罩、255)
put_alpha(图层、遮罩)
噪声。blit(层,(0,0))
显示blit(噪音,(0,0))
t+=1
# 2. 具有每像素alpha和绘图功能的blit
当t<0时:
pygame.draw.circle(图层,颜色a,(400300),296,0)
pygame.draw.circle(图层,颜色,(400300),15,0)
噪声。blit(层,(0,0))
显示blit(噪音,(0,0))
t+=1
# 3. 带颜色键的blit
当t<1时:
pygame.draw.circle(图层颜色键,颜色键,(400300),296,0)
pygame.draw.circle(图层颜色键,颜色,(400300),15,0)
噪声。blit(图层颜色键,(0,0))
显示blit(噪音,(0,0))
t+=1
cur\u time=pygame.time.get\u ticks()
DT=当前时间-旧时间
打印“时间:”,DT
结论:
1.应用自定义遮罩阵列的完整alpha:速度最慢,但您可以完全控制遮罩形式,并可以使用透明度产生酷炫效果。
2.完全alpha+只需使用内置的绘图功能,只需使用所需的alpha值定义颜色。稍微快一点(ITPC),但无法直接控制颜色值。

3.带颜色键的正常24位曲面。比上述速度快2倍,但没有自定义透明度

你能展示一下你正在使用的代码吗?否则很难说你的代码在哪里可以改进。应该更改
self.center
还是
self.radius
?如果没有,那么您不必每次调用
draw
时都进行blit/draw on
self.masked
。只需执行一次,然后使用生成的曲面在
surf
上进行闪电显示。是的,圆圈会扩展并可以更改位置/中心。您是否在代码的其他位置使用
self.masked
self.mask
self.masked
self.noise\u图像的大小是否相同?为什么它们很大?1)
self.masked
self.mask
是NoiseCircle对象的属性,因此它们在每个实例中都会使用。除此之外,第2)条曲面很大,因为圆有可能会扩展,直到达到显示尺寸,而不会在其顶部绘制任何其他圆。我可以根据需要增加曲面的大小,但我认为这需要更多的处理时间,并决定将其设置为最大大小(显示大小)