Filipe Rebollo
Filipe Rebollo

Reputation: 17

How to set alpha transparency property using pygame.draw.line?

I am trying to set transparency of a drawn line using pygame.draw.line(tela, (255, 255, 255), self.a, self.b, width=1), where:

Is there a direct simple way to do that? Is there a conceptual argument that prevent us to do it readily? Does everything have to have a complex answer?

Upvotes: 1

Views: 576

Answers (1)

martineau
martineau

Reputation: 123531

Below is an adaptation of @Yannis Assael's answer to his own question Pygame draw anti-aliased thick line that I referred you to. I've transformed into a function named aaline() and streamlined the code to try to make it more efficient and readable.

The function has been defined to have a calling sequence similar to the existing one named pygame.draw.aaline() for drawing single-pixel-wide lines make switching from on to the other a little easier.

from math import atan2, cos, hypot, sin
import pygame
import pygame.gfxdraw
from pygame.locals import *
import sys


def aaline(surface, color, start_pos, end_pos, width=1):
    """ Draws wide transparent anti-aliased lines. """
    # ref https://stackoverflow.com/a/30599392/355230

    x0, y0 = start_pos
    x1, y1 = end_pos
    midpnt_x, midpnt_y = (x0+x1)/2, (y0+y1)/2  # Center of line segment.
    length = hypot(x1-x0, y1-y0)
    angle = atan2(y0-y1, x0-x1)  # Slope of line.
    width2, length2 = width/2, length/2
    sin_ang, cos_ang = sin(angle), cos(angle)

    width2_sin_ang  = width2*sin_ang
    width2_cos_ang  = width2*cos_ang
    length2_sin_ang = length2*sin_ang
    length2_cos_ang = length2*cos_ang

    # Calculate box ends.
    ul = (midpnt_x + length2_cos_ang - width2_sin_ang,
          midpnt_y + width2_cos_ang  + length2_sin_ang)
    ur = (midpnt_x - length2_cos_ang - width2_sin_ang,
          midpnt_y + width2_cos_ang  - length2_sin_ang)
    bl = (midpnt_x + length2_cos_ang + width2_sin_ang,
          midpnt_y - width2_cos_ang  + length2_sin_ang)
    br = (midpnt_x - length2_cos_ang + width2_sin_ang,
          midpnt_y - width2_cos_ang  - length2_sin_ang)

    pygame.gfxdraw.aapolygon(surface, (ul, ur, br, bl), color)
    pygame.gfxdraw.filled_polygon(surface, (ul, ur, br, bl), color)


if __name__ == '__main__':

    # Define some colors.
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    AQUA = (0, 255, 255)
    ORANGE = (255, 165, 0)
    YELLOW = (255, 255, 0)

    # Window size.
    WIDTH, HEIGHT = 800, 600

    # Set up pygame.
    pygame.init()

    # Set up window for display.
    window = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
    pygame.display.set_caption('Wide Transparent Lines')

    # Set background color of window.
    window.fill(BLACK)

    a = (0, 0)
    b = (WIDTH, HEIGHT)

    LINE_COLOR = ORANGE
    fw = 255 / (WIDTH-1)
    fh = 255 / (HEIGHT-1)
    width = 3

    # Draw an opaque diagonal line then those on either side with
    # ever-increasing transparency.
    color = LINE_COLOR + (255,)  # Add transparency to color.
    aaline(window, color, (0, 0), (WIDTH, HEIGHT), width)

    for x in range(0, WIDTH, 25):
        color = LINE_COLOR + (int(fw*x),)  # Add transparency to color.
        aaline(window, color, (0, 0), (x, HEIGHT), width)

    for y in range(0, HEIGHT, 25):
        color = LINE_COLOR + (int(fh*y),)  # Add transparency to color.
        aaline(window, color, (0, 0), (WIDTH, y), width)

    # Copy window to screen.
    pygame.display.update()

    # Run the game loop.
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

For testing and demonstration purposes, there's a driver at the end that calls it in some loops. Below is a screenshot of what's displayed. The lines become progressively more transparent as one of their end points gets further and further away from the the center diagonal of the rectangle.

screenshot of what program displays

Upvotes: 4

Related Questions