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.