1

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:

  • tela is the screen
  • (255, 255, 255) is the color
  • self.a and self.b are the position and direction respectively
  • and width is its weight

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?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • If you're asking how to draw anti-aliased lines, see [Pygame draw anti-aliased thick line](https://stackoverflow.com/questions/30578068/pygame-draw-anti-aliased-thick-line). – martineau Jul 25 '21 at 22:45
  • Thanks for reaching out. I went trough each row of the mentioned document but still wasn't able to find the answer. Would you be able to be more specif on the answer? Maybe giving an example? Thanks again martineau. – Filipe Rebollo Jul 25 '21 at 23:00

1 Answers1

4

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

martineau
  • 119,623
  • 25
  • 170
  • 301