2010-08-27 7 views
6

mam dwa obrazy:Aktywny teksturowanie z pygame (możliwe koncepcje co do zbadania?)

Mask Texture

Chciałbym zasadniczo „wyciąć” czarny kształt z płytki tekstury tak, że w końcu z czegoś wzdłuż tych linii:

Cutout

wyjątkiem przezroczysty wokół kształtu. Czy to możliwe za pomocą pygame? Ten przykład musiałem stworzyć w GIMP.

Dodatkowo, czy byłoby to zbyt wydajne, aby zrobić to dla każdej klatki dla kilku duszków w środowisku czasu rzeczywistego? (30+ klatek na sekundę)

Odpowiedz

5

Zrobiłem rozwiązanie, jednak nie jest ono najlepsze ani dla prędkości, ani dla piękna. Możesz użyć podwójnego blittingu z ustawieniem koloru dla przezroczystości. W ten sposób maska ​​powinna mieć tylko dwa kolory: czarny i biały. Należy pamiętać, że nie można tego użyć w przypadku obrazów z pikselami alfa (RGBA) tylko dla obrazów RGB. Inne ograniczenie polega na tym, że zaleca się, aby rozmiar tekstury i obraz maski był taki sam (jeśli nie, należy użyć obszarów do blendingu).

słowami, krok po kroku:

  • utworzyć powierzchnię maski. Tło powinno być biały (255,255,255), maskowane części powinny być czarna (0,0,0)
  • utworzyć lub załadować teksturę na powierzchni
  • ustawiony na kolor kluczowy przezroczystości dla maski dla koloru czarnego
  • Blit maskę na teksturę (lub na kopię tekstury). w tym momencie czarne części maski nie zostały pobrudzone do tekstury, ponieważ ustawiliśmy czarny kolor na przezroczysty za pomocą metody set_colorkey, aby ustawić kolor biały tekstury (lub kopii tekstury) na biały. pamiętaj, że nasza obecna powierzchnia tekstur ma białe i teksturowane części.
  • blit tekstury na ekranie. białe części nie będą blittowany powodu musimy ustawić go przezroczysta z kolor klucza

przykładowy kod:

#!/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() 

Polecam nie używać jpg jak maska ​​z powodu jego stratny format, ja polecam bmp lub png (bmp jest lepszy). Pamiętaj, że nie wykorzystuje alfa więc krawędzie nie będą wygładzane tak, że nie jest to miłe rozwiązanie w 2010 roku :)

Oto zrzut ekranu z wynikiem: masked blitting

Edit: Witam ponownie,

Zrobiłem kilka testów z blendingiem z BLEND_ADD, a wyniki były obiecujące.Oto kod:

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() 

A wynik: result

Dzięki takiemu rozwiązaniu można uzyskać na piksel alfa teksturowania. Należy pamiętać, że maska ​​powinna być obrazem z kanałem alfa, więc nie można użyć jpg. Najlepszym rozwiązaniem jest png.

obrazu tekstury (texture.jpg): texture

Maska obrazu (mask2.png): mask

5

Jeśli używasz obrazów z pre-renderowane alfa i mieszanie dodatków, można dostać maski alfa-mieszane:

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() 

Gdzie background.png i mask.png są:

background.png + mask.png = result

+0

Hej dzięki. Zamierzam spróbować tego dziś wieczorem. – agscala