[pygame ex] Fun with alpha. (punch a hole in a Surface)

[pygame ex] Fun with alpha. (punch a hole in a Surface)

Postby Mekire » Sat Apr 27, 2013 5:26 am

Here are some examples of ways to "punch a hole" in a surface. Three methods are illustrated here (well 2 methods and one personal experimentation actually).

The first uses a regular convert surface with a color-key. This is found below in the function make_hole. With this method you are fairly restricted on how much you can play with the alpha, but you can still have two types (clear and semi-clear if desired). You can play with changing the fill color and the set_alpha value to illustrate.

The second method uses convert_alpha surface. This is found in the function make_hole_alpha. This method is perhaps simpler than the previous but possibly a little slower. Here you can play with changing the fill color which includes the alpha value with it.

Lastly I implemented another version of the convert_alpha to create a gradient effect in the function gradient_hole. I'm still trying to improve this one but it is quite fun. So far you can change the amount the alpha drops per step, the shape of the next steps ellipse (how much to decrease the size of the width/height of the rect by), and of course the fill color. I used an actual pygame.Color here instead of a regular tuple so that I could change and get the alpha value more easily.

To try each technique just uncomment the desired method call and comment out the other two in the Control.update() method.

The hole will follow the mouse cursor.
Code: Select all
import pygame as pg
import sys,os

class Control:
    def __init__(self):
        self.done = False
        self.Clock = pg.time.Clock()
        self.rect = pg.Rect((0,0,600,600))

    def event_loop(self):
        keys = pg.key.get_pressed()
        for event in pg.event.get():
            if event.type == pg.QUIT or keys[pg.K_ESCAPE]:
                self.done = True

    def make_hole(self,Surf):
        hole = pg.Surface((Surf.get_size())).convert()
        hole.set_colorkey((255,0,255))
        hole.fill((0,0,0)) #Experiment with changing this color.
        pg.draw.ellipse(hole,(255,0,255), self.rect)
##        hole.set_alpha(200)  #Uncomment and experiment with changing this value.
        Surf.blit(hole,(0,0))

    def make_hole_alpha(self,Surf):
        hole = pg.Surface((Surf.get_size())).convert_alpha()
        hole.fill((255,255,255,200)) #Experiment with changing this color
        pg.draw.ellipse(hole,(0,0,0,0), self.rect)
        Surf.blit(hole,(0,0))

    def gradient_hole(self,Surf):
        hole = pg.Surface((Surf.get_size())).convert_alpha()
        Color = pg.Color(50,0,0,255) #Experiment with changing this color
        hole.fill(Color)

        step = (-50,-10) #Change ammount to shrink each rect by
        alpha_step = 20 #Change amount to change transparency per step
        steps = min(self.rect.width//abs(step[0]),self.rect.height//abs(step[1]))
        shrink_rect = self.rect.copy()

        for i in range(steps):
            if Color.a-alpha_step >= 0:
                Color.a -= alpha_step
            else:
                Color.a = 0
            pg.draw.ellipse(hole,Color,shrink_rect)
            shrink_rect.inflate_ip(step)
            #inflate should auto-adjust center, but in the case of a step of -1,-1 it fails.
            shrink_rect.center = self.rect.center
        Surf.blit(hole,(0,0))

    def update(self,Surf):
        """Uncomment the version you want to test."""
        self.rect.center = pg.mouse.get_pos()
        Surf.blit(FRACTAL,(0,0))
##        self.make_hole(Surf)
##        self.make_hole_alpha(Surf)
        self.gradient_hole(Surf)

    def main(self,Surf):
        while not self.done:
            self.event_loop()
            self.update(Surf)
            pg.display.update()
            self.Clock.tick(60)

if __name__ == "__main__":
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pg.init()
    SCREENSIZE = (1000,650)
    SCREEN = pg.display.set_mode(SCREENSIZE)
    FRACTAL = pg.image.load("frac.jpg").convert()
    RunIt = Control()
    RunIt.main(SCREEN)
    pg.quit();sys.exit()

I used the image found here:
http://www.oneness4all.com/wp-content/uploads/2009/04/fractal17.jpg
renamed to "frac.jpg"

-Mek

Edit: Fixed a division glitch when using python 3.
User avatar
Mekire
 
Posts: 977
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Return to Game Development

Who is online

Users browsing this forum: No registered users and 2 guests