2

I'm trying to code the typical dvd bouncing screensaver. I am happy with it but I want to change the color of the logo everytime it hits the wall. I have used fill(), but the logo changes to a colored rectangle. I want to change the color of the logo, respecting the alpha channel of the image.

from pygame import *
import random

#set canvas size variables
width = 700
height = 450

#draw canvas
screen = display.set_mode((width,height))
display.set_caption('Graphics')

#initial XY coordinates where game starts
x = random.randint(1, width)
y = random.randint(1, height)

#import logo
logo_img = image.load('dvd_logo_alpha.png')

R = 255
G = 255
B = 255

def logo(x,y):
    screen.blit(logo_img, (x,y))

def Col():
    R = random.randint(100,255)
    G = random.randint(100,255)
    B = random.randint(100,255)

#speed of the logo
dx = 3
dy = 3

endProgram = False

while not endProgram:
    for e in event.get():
        if e.type == QUIT:
            endProgram = True

    #speed changes position XY
    x += dx
    y += dy

    #detection of collision with border of screen
    if y<0 or y>height-47:
        dy *= -1
        R = random.randint(100,255)
        G = random.randint(100,255)
        B = random.randint(100,255)
    if x<0 or x>width-100:
        dx *= -1
        R = random.randint(100,255)
        G = random.randint(100,255)
        B = random.randint(100,255)

    screen.fill((0))
    logo_img.fill((R,G,B)) #here is the problem I can not solve
    logo(x,y)
    display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Marc
  • 129
  • 1
  • 8

1 Answers1

1

First you have to create an image with an alpha channel, to make the transparent area of the png image invisible. Use pygame.Surface.convert_alpha() To create an surface with an alpha channel:

tintImage = image.convert_alpha()

To tint an image by pygame.Surface.fill(), the special_flags has too be set to BLEND_RGBA_MULT. This causes that the all the pixels of the image are multiplied by the color, rather then set by the color:

tintImage.fill((R, G, B, 255), None, BLEND_RGBA_MULT)

Note, since the image has to be tint by different colors, the original image has to be kept. Use the function logo to copy the image, and "tint" an "blit" the copy of the image:

def logo(x, y, color):
    tintImage = logo_img.convert_alpha()
    tintImage.fill((R, G, B, 255), None, BLEND_RGBA_MULT)
    screen.blit(tintImage, (x, y))

Call the function in the main loop of the program:

endProgram = False
while not endProgram:
    for e in event.get():
        if e.type == QUIT:
            endProgram = True

    #speed changes position XY
    x += dx
    y += dy

    #detection of collision with border of screen
    if y<0 or y>height-47:
        dy *= -1
        R = random.randint(100,255)
        G = random.randint(100,255)
        B = random.randint(100,255)
    if x<0 or x>width-100:
        dx *= -1
        R = random.randint(100,255)
        G = random.randint(100,255)
        B = random.randint(100,255)

    screen.fill((0))

    #logo_img.fill((R,G,B)) #here is the problem I can not solve
    logo(x, y, (R, G, B))

    display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    Thank you so much! It does work now!! I have learned a lot. Thanks:) – Marc Feb 12 '19 at 11:08
  • Hello, I would like to know if there's a performance impact with tintImage.fill((R, G, B, 255), None, BLEND_RGBA_MULT) I see you are running this code in the loop once but if I've got multiple occurences of that in my code, will it be bad ? – notproplayer 3 Aug 17 '20 at 09:21