使用pygame进行主动纹理化(可能?要研究哪些概念?)

时间:2010-08-27 00:16:03

标签: python pygame

我有两张图片:

Mask Texture

我想基本上从纹理贴片中“剪掉”黑色形状,以便我最终得到这些东西:

Cutout

除了透明的形状。这可能使用pygame吗?这个例子我必须在GIMP中创建。

另外,对于实时环境中的几个精灵来说,为每个帧执行此操作会不会太高性能? (每秒30帧以上)

2 个答案:

答案 0 :(得分:7)

我提出了一个解决方案,但无论是对速度还是美容,它都不是最好的。 您可以使用双重blitting并设置colorkeys以获得透明度。这样,面具应该只有两种颜色:黑色和白色。 请注意,对于RGB像素,每像素alpha(RGBA)的图像不能使用此功能。 其他限制是建议纹理和掩模图像的大小相同(如果不是,你应该使用blitting区域)。

用语言,一步一步地说:

  • 使用蒙版创建表面。背景应为白色(255,255,255),蒙面部分应为黑色(0,0,0)
  • 将纹理创建或加载到表面
  • 为黑色设置遮罩的透明度颜色键
  • 将蒙版blit到纹理上(或纹理的副本上)。此时,蒙版的黑色部分没有对纹理进行布局,因为我们使用set_colorkey方法将黑色设置为透明
  • 现在将纹理的颜色键(或纹理的副本)设置为白色。请记住,我们当前的纹理表面有白色和纹理部分。
  • 将纹理blit到屏幕上。由于我们已使用colorkey将其设置为透明,因此白色部分不会显示为blit

代码示例:

#!/usr/bin/python
# -*- coding:utf8 -*-

import pygame, sys

#init pygame
pygame.init()

#init screen
screen=pygame.display.set_mode((800,600))
screen.fill((255,0,255))

#loading the images
texture=pygame.image.load("texture.jpg").convert()
texture_rect=texture.get_rect()
texture_rect.center=(200,300)
mask=pygame.Surface((texture_rect.width,texture_rect.height)) # mask should have only 2 colors: black and white
mask.fill((255,255,255))
pygame.draw.circle(mask,(0,0,0),(texture_rect.width/2,texture_rect.height/2),int(texture_rect.width*0.3))
mask_rect=mask.get_rect()
mask_rect.center=(600,300)

tmp_image=texture.copy() # make a copy of the texture to keep it unchanged for future usage
mask.set_colorkey((0,0,0)) # we want the black colored parts of the mask to be transparent
tmp_image.blit(mask,(0,0)) # blit the mask to the texture. the black parts are transparent so we see the pixels of the texture there

tmp_rect=tmp_image.get_rect()
tmp_rect.center=(400,300)
tmp_image.set_colorkey((255,255,255))
screen.blit(texture,texture_rect)
screen.blit(mask,mask_rect)
screen.blit(tmp_image,tmp_rect)

pygame.display.flip()

while 1:
    event=pygame.event.wait()
    if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_q]):
        sys.exit()

我建议不要使用jpg作为掩码,因为它的格式有损,我建议使用bmp或png(bmp更好)。请记住它不使用alpha,因此边缘不会消除锯齿,所以它在2010年不是一个好的解决方案:))

以下是结果的屏幕截图: masked blitting

编辑: 嗨,再次,

我使用BLEND_ADD进行了一些测试,结果很有希望。这是代码:

import pygame, sys

#init pygame
pygame.init()

#init screen
screen=pygame.display.set_mode((800,600))
screen.fill((255,0,255))

#loading the images
texture=pygame.image.load("texture.jpg").convert_alpha()
texture_rect=texture.get_rect()
texture_rect.center=(200,300)
mask=pygame.image.load("mask2.png").convert_alpha()
mask_rect=mask.get_rect()
mask_rect.center=(600,300)

textured_mask=mask.copy()
textured_rect=textured_mask.get_rect()
textured_rect.center=400,300

textured_mask.blit(texture,(0,0),None,pygame.BLEND_ADD)

screen.blit(texture,texture_rect)
screen.blit(mask,mask_rect)
screen.blit(textured_mask,textured_rect)

pygame.display.flip()

while 1:
    event=pygame.event.wait()
    if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_q]):
        sys.exit()

结果: result

使用此解决方案,您可以获得每像素alpha纹理。请注意,掩码应该是带alpha通道的图像,因此无法使用jpg。最好用的是png。

纹理图像(texture.jpg): texture

Mask image(mask2.png): mask

答案 1 :(得分:5)

如果您正在使用具有预渲染alpha和添加剂混合的图像,则可以获得alpha混合蒙版:

import pygame
import sys

screen = pygame.display.set_mode( (800, 600) )
pygame.init()

background = pygame.image.load( "background.png" )
mask = pygame.image.load( "mask.png" )

# Create a surface to hold the masked image
masked_image = pygame.surface.Surface( background.get_size(), 0, mask )
# Blit the texture normally
masked_image.blit( background, (0,0) )
# Multiply by the pre-rendered, inverted mask
masked_image.blit( mask, (0,0), None, pygame.BLEND_MULT )

# masked_image now holds the 'cutout' of your texture blended onto a black
# background, so we need to blit it as such, i.e., using additive blending.
screen.fill( (0, 0, 0) )
screen.blit( masked_image, (10, 10), None, pygame.BLEND_ADD )

pygame.display.flip()

while True:
  event=pygame.event.wait()
  if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_q]):
    sys.exit()

background.pngmask.png的位置:

background.png + mask.png = result