NoCodeNoBlunder
NoCodeNoBlunder

Reputation: 105

Pygame drawing antialiased shape and then blitting to main window

I want to draw antialiased shapes. I know you can use the pygame's gfxdraw module to accomplish this. However, it does seem to work only when drawing directly on the main window which is not suitable for me because I intend to use masks for collision checking. Therefore a different surface is needed to create a mask that represents the circle.

How can you achieve this in pygame?

Minimal working example:

import pygame as pg
from pygame import gfxdraw

WIDHT, HEIGHT = 1200, 800
WIN = pg.display.set_mode((WIDHT, HEIGHT))

RADIUS = 80
WHITE = (255, 255, 255)
GREEN = (0, 200, 0)
RED = (200, 0, 0)
TRANS = (1, 1, 1)

class Circle(pg.sprite.Sprite):
    def __init__(self,
                 radius: int,
                 pos: tuple[int, int],
                 color: tuple[int, int, int]):

        super().__init__()
        self.radius = radius
        self.color = color

        self.image = pg.surface.Surface((radius*2, radius*2))
        self.image.fill(TRANS)
        self.image.set_colorkey(TRANS)

        self.rect = self.image.get_rect(center=(pos[0], pos[1]))
        pg.gfxdraw.aacircle(self.image, self.rect.width//2, self.rect.height//2, radius, color)
        pg.gfxdraw.filled_circle(self.image, self.rect.width//2, self.rect.height//2, radius, color)
        self.mask = pg.mask.from_surface(self.image)

    def draw(self):
        WIN.blit(self.image, self.rect)


def main():
    circle_1 = Circle(RADIUS, (500, 500), GREEN)

    running = True
    while running:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                running = False

        WIN.fill(WHITE)

        circle_1.draw()
        pg.gfxdraw.filled_circle(WIN, 700, 500, RADIUS, RED)
        pg.gfxdraw.aacircle(WIN, 700, 500, RADIUS, RED)

        pg.display.update()


if __name__ == "__main__":
    main()

Upvotes: 2

Views: 184

Answers (1)

Rabbid76
Rabbid76

Reputation: 210968

You need to create a transparent pygame.Surface with the per pixel alpha format. Use the SRCALPHA flag:

self.image = pg.surface.Surface((radius*2, radius*2))

self.image = pg.surface.Surface((radius*2, radius*2), pg.SRCALPHA)

However, for the highest quality, I suggest using OpenCV/cv2 (e.g. How to make a circular countdown timer in Pygame?)

Upvotes: 2

Related Questions