pygame fully transparent surface - python

I'm trying to make a color picker that changes color over time. I have the logic but the process is really slow, the idea is to have a square that changes color and overlap a PNG grayscale gradient onto it so that the program can be faster. The problem is that I can't seem to download the gradient with the transparency.
import sys, pygame
pygame.init()
#VARIABLES
width = 255
height = 255
background = (255, 0, 0)
foreground = (230, 100, 45)
mySurf = pygame.Surface((255, 255))
mySurf.set_alpha(0)
mySurf.fill((200,0,200))
#SCREEN
screen = pygame.display.set_mode((width, height))
screen.fill((0, 0, 0))
#CODE
for x in range(255):
s = pygame.Surface((1, 255))
s.set_alpha(255-x)
s.fill((255, 255, 255))
mySurf.blit(s, (x, 0))
for y in range(255):
s = pygame.Surface((255, 1))
s.set_alpha(y)
s.fill((0, 0, 0))
mySurf.blit(s, (0, y))
pygame.image.save(mySurf, "gradient.png")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()

You have to create a surface with a format that hast an alpha channel per pixel. Use the SRCALPHA flag:
mysurf = pygame.surface((255, 255))
mySurf = pygame.Surface((255, 255), pygame.SRCALPHA)
Note, with the flag each pixel has its own alpha value (RGBA format), without the flag the surfaces hast just 1 global alpha value and can not store different alpha values for the pixels (RGB format)
Complete example:
import sys, pygame
pygame.init()
#VARIABLES
width = 255
height = 255
background = (255, 0, 0)
foreground = (230, 100, 45)
mySurf = pygame.Surface((255, 255))
mySurf.set_alpha(0)
mySurf.fill((200,0,200))
#SCREEN
screen = pygame.display.set_mode((width, height), pygame.SRCALPHA)
#CODE
s = pygame.Surface((1, 255), pygame.SRCALPHA)
for x in range(255):
s.fill((255, 255, 255, 255-x))
mySurf.blit(s, (x, 0))
s = pygame.Surface((255, 1), pygame.SRCALPHA)
for y in range(255):
s.fill((0, 0, 0, y))
mySurf.blit(s, (0, y))
pygame.image.save(mySurf, "gradient.png")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()

Related

Why don't three R, G and B circles blend correctly?

I am trying to represent the RGB color model using python + pygame.
I wanted to get the following:
So then, I wrote the following code:
import pygame, sys
from pygame.locals import *
ALPHA = 100
TRANSPARENT = (255,0,255)
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0,100)
GREEN = (0,255,0,100)
BLUE = (0,0,255,100)
pygame.init()
size=(800,500)
screen= pygame.display.set_mode(size)
surf1 = pygame.Surface(size)
surf1.fill(TRANSPARENT)
surf1.set_colorkey(TRANSPARENT)
pygame.draw.circle(surf1, BLUE, (430, 280), 60 )
surf2 = pygame.Surface(size)
surf2.fill(TRANSPARENT)
surf2.set_colorkey(TRANSPARENT)
pygame.draw.circle(surf2, GREEN, (370, 280), 60 )
surf3 = pygame.Surface(size)
surf3.fill(TRANSPARENT)
surf3.set_colorkey(TRANSPARENT)
pygame.draw.circle(surf3, RED, (400, 220), 60 )
surf1.set_alpha(ALPHA)
surf2.set_alpha(ALPHA)
surf3.set_alpha(ALPHA)
while True :
screen.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.blit(surf1, (0,0))
screen.blit(surf2, (0,0))
screen.blit(surf3, (0,0))
pygame.display.flip()
But instead of getting the RGB color model, I got this, with colors incorrectly blended:
Does anybody know what it could be? Thanks!
This should work:
import pygame, sys
from pygame.locals import *
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0, 100)
GREEN = (0, 255, 0, 100)
BLUE = (0, 0, 255, 100)
pygame.init()
size = (800, 500)
screen = pygame.display.set_mode(size)
surf1 = pygame.Surface(size)
surf1.fill(BLACK)
surf1.set_colorkey(BLACK)
pygame.draw.circle(surf1, BLUE, (430, 280), 60)
surf2 = pygame.Surface(size)
surf2.fill(BLACK)
surf2.set_colorkey(BLACK)
pygame.draw.circle(surf2, GREEN, (370, 280), 60)
surf3 = pygame.Surface(size)
surf3.fill(BLACK)
surf3.set_colorkey(BLACK)
pygame.draw.circle(surf3, RED, (400, 220), 60)
surf4 = pygame.Surface(size)
surf4.set_colorkey(BLACK)
surf4.blit(surf1, (0, 0), special_flags=pygame.BLEND_RGB_ADD)
surf4.blit(surf2, (0, 0), special_flags=pygame.BLEND_RGB_ADD)
surf4.blit(surf3, (0, 0), special_flags=pygame.BLEND_RGB_ADD)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(WHITE)
screen.blit(surf4, (0, 0))
pygame.display.flip()
You want to add the colors at the intersections of the circles, hence use the BLEND_RGB_ADD flag.
I created a fourth surface since you wanted a white background.

Blending two pygame.Color objects together

I am wondering how to blend two pygame.Color objects and cannot find a solution after extensive reasearch.
I have created two pygame.Color objects and would like to create a new object who's colour value is the two colours blended together.
import pygame
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
#If I want to blend white and red with the option of how much dominace each should have what code would I write
Use the pygame.Color.lerp function to linear interpolation to the given Colors.
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
pink = white.lerp(red, 0.5)
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((500, 100))
clock = pygame.time.Clock()
white = pygame.Color(255, 255, 255)
red = pygame.Color(255, 0, 0)
pink25 = white.lerp(red, 0.25)
pink50 = white.lerp(red, 0.5)
pink75 = white.lerp(red, 0.75)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
pygame.draw.circle(window, white, (50, 50), 45)
pygame.draw.circle(window, pink25, (150, 50), 45)
pygame.draw.circle(window, pink50, (250, 50), 45)
pygame.draw.circle(window, pink75, (350, 50), 45)
pygame.draw.circle(window, red, (450, 50), 45)
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()

How to make a circular countdown timer in Pygame?

How can i make this kind of countdown in Pygame? (i'm looking for how could i make the circle's perimeter decrease, that's the issue, because displaying the time isn't hard )
Keep in mind that how long the perimeter of the circle is and the displayed time should be in proportion with each other.
Just use pygame.draw.arc and specify the stop_angle argument depending on the counter:
percentage = counter/100
end_angle = 2 * math.pi * percentage
pygame.draw.arc(window, (255, 0, 0), arc_rect, 0, end_angle, 10)
Minimal example:
import pygame
import math
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 100
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
def drawArc(surf, color, center, radius, width, end_angle):
arc_rect = pygame.Rect(0, 0, radius*2, radius*2)
arc_rect.center = center
pygame.draw.arc(surf, color, arc_rect, 0, end_angle, width)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
drawArc(window, (255, 0, 0), (100, 100), 90, 10, 2*math.pi*counter/100)
pygame.display.flip()
pygame.quit()
exit()
Sadly the quality of pygame.draw.arc with a width > 1 is poor. However this can be improved, using cv2 and cv2.ellipse:
import pygame
import cv2
import numpy
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 100
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
def drawArcCv2(surf, color, center, radius, width, end_angle):
circle_image = numpy.zeros((radius*2+4, radius*2+4, 4), dtype = numpy.uint8)
circle_image = cv2.ellipse(circle_image, (radius+2, radius+2),
(radius-width//2, radius-width//2), 0, 0, end_angle, (*color, 255), width, lineType=cv2.LINE_AA)
circle_surface = pygame.image.frombuffer(circle_image.flatten(), (radius*2+4, radius*2+4), 'RGBA')
surf.blit(circle_surface, circle_surface.get_rect(center = center))
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
drawArcCv2(window, (255, 0, 0), (100, 100), 90, 10, 360*counter/100)
pygame.display.flip()
pygame.quit()
exit()

How to make transparent pygame.draw.circle [duplicate]

This question already has answers here:
Draw a transparent rectangles and polygons in pygame
(4 answers)
Closed 2 years ago.
How to make pygame.draw.circle transparent (add alpha level), as for "surface" "set_alpha"?
I found a solution only in changing the color of pygame.draw.circle to less bright
You've to use a pygame.Surface. Create a Surface with a per pixel alpha image format. e.g:
radius = 100
circle = pygame.Surface((radius*2, radius*2), pygame.SRCALPHA)
And draw a transparent circle on it. The color of the circle has to have an alpha channel < 255 (e.g. 128):
pygame.draw.circle(circle, (255, 0, 0, 128), (radius, radius), radius)
blit() the Surface to the window. e.g.:
window.blit(circle, (100, 100))
Example:
import pygame
pygame.init()
wndsize = (400, 400)
window = pygame.display.set_mode(wndsize)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
pygame.draw.rect(window, (0, 0, 255), (0, 0, 200, 400))
radius = 100
circle = pygame.Surface((radius*2, radius*2), pygame.SRCALPHA)
pygame.draw.circle(circle, (255, 0, 0, 128), (radius, radius), radius)
window.blit(circle, (100, 100))
pygame.display.flip()
You can create surface with alpha channel
surface1 = screen.convert_alpha()
fill it with transparent color -
surface1.fill([0,0,0,0])
draw circle using color [R,G,B,Alpha]
pygame.draw.circle(surface1, (255, 0, 0, 128), (300, 300), 200)
and blit it on screen
screen.blit(surface1, (0,0))
But alpha always mix object color with background color so it makes it less bright.
import pygame
pygame.init()
screen = pygame.display.set_mode((800,600))#, depth=32)
surface1 = screen.convert_alpha()
surface1.fill([0,0,0,0])
pygame.draw.circle(surface1, (255, 0, 0, 128), (325, 250), 100)
surface2 = screen.convert_alpha()
surface2.fill([0,0,0,0])
pygame.draw.circle(surface2, (0, 255, 0, 128), (475, 250), 100)
surface3 = screen.convert_alpha()
surface3.fill([0,0,0,0])
pygame.draw.circle(surface3, (0, 0, 255, 128), (400, 350), 100)
screen.fill([255,255,255]) # white background
screen.blit(surface1, (0,0))
screen.blit(surface2, (0,0))
screen.blit(surface3, (0,0))
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
pygame.quit()
Example on GitHub: furas/python-examples/pygame/transparency

How do you create rect variables in python pygame

I am programming in Python with the pygame library. I want to know how to make a rectangle variable, something like:
import ...
rect1 = #RECT VARIABLE
rect2 = #RECT VARIABLE
Just do
pygame.Rect(left, top, width, height)
this will return you a Rect object in pygame
Perhaps something like this will work?
import pygame
# your whole code until you need a rectangle
rect1 = pygame.draw.rect( (x_coordinate, y_coordinate), (#a rgb color), (#size of rect in pixels) )
If you want a red rectangle with 100x150 size in 0x50 position, it will be:
rect1 = pygame.draw.rect( (0, 50), (255, 0, 0), (100, 150) )
To insert it into the screen you use:
pygame.screen_you_have_created.blit(rect1, 0, 50)
For rectangle draw pattern is : pygame.Rect(left, top, width, height)
You can modify this code according to your need.
import pygame, sys
from pygame.locals import *
pygame.init()
windowSurface = pygame.display.set_mode((500, 400), 0, 32)
pygame.display.set_caption('Title')
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
basicFont = pygame.font.SysFont(None, 48)
message = 'Hello '
text = basicFont.render(message, False, WHITE, BLUE)
textRect = text.get_rect()
textRect.centerx = windowSurface.get_rect().centerx
textRect.centery = windowSurface.get_rect().centery
windowSurface.fill(WHITE)
pixArray = pygame.PixelArray(windowSurface)
pixArray[480][380] = BLACK
del pixArray
windowSurface.blit(text, textRect)
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == K_ESCAPE:
pygame.quit()
sys.exit()

Categories

Resources