1

I have this script that creates a star in Pygame.

import pygame

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400

DARK_BLUE  = (   3,   5,  54)
STARRY     = ( 230, 255, 80 )


### initialisation
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
pygame.display.set_caption("Star")


# Define a star
centre_coord = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
star_points  = [ (165, 151), (200, 20), (235, 151), (371, 144), (257, 219),
                 (306, 346), (200, 260), (94, 346), (143, 219), (29, 144)   ]

# Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

    # Re-draw the window
    window.fill( DARK_BLUE )                             # background fill
    pygame.draw.polygon( window, STARRY, star_points )   # Draw the star
    pygame.display.flip()                                # Update the display

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()

Is there a way I can modify this to have a striped shape within the star. I've looked and I can't find many resourced to do this. I've tried this in both pygame and psychopy. I'm open to rewriting the entire script if there is a better way to do this.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
3141592654
  • 13
  • 3

1 Answers1

1

Create a striped image of the size of the star. You can arrange and color the strips as you like. For example:

stripes = pygame.Surface(window.get_size())
stripes.fill(STARRY)
offset_x = 400
for x in range(-offset_x, 400, 20):
    if (x//20) % 2 == 0:
        pts = [(x, 0), (x+20, 0), (x+20+offset_x, 400), (x+offset_x, 400)]
        pygame.draw.polygon(stripes, "red", pts)

After that you have to use the texture to draw the polygon. There are 2 ways to do this.


Option 1

You can use pygame.gfxdraw.textured_polygon(), which draws a textured polygon. Import the pygame.gfxdraw module:

import pygame.gfxdraw

Finally draw the shape with pygame.gfxdraw.textured_polygon():

pygame.gfxdraw.textured_polygon(window, star_points, stripes, 0, 0)

Option 2

If you don't want to use the gfxdraw module you have to clip the image. Create a mask from the star points in the size of the image:

mask_image = pygame.Surface(stripes.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(mask_image, (255, 255, 255), star_points)
mask = pygame.mask.from_surface(mask_image)

Create a clipped striped image using the mask of the striped image. This is also explained in on one of my earlier answers: How to free transform image in pygame?.

star_stripes = mask.to_surface(setsurface = stripes.convert_alpha(), unsetcolor = (0, 0, 0, 0))

Minimal examples of both solutions:

Option 1

import pygame
import pygame.gfxdraw

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400

DARK_BLUE  = (   3,   5,  54)
STARRY     = ( 230, 255, 80 )

### initialisation
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
pygame.display.set_caption("Star")

# Define a star
centre_coord = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
star_points  = [ (165, 151), (200, 20), (235, 151), (371, 144), (257, 219),
                 (306, 346), (200, 260), (94, 346), (143, 219), (29, 144)   ]

stripes = pygame.Surface(window.get_size())
stripes.fill(STARRY)
offset_x = 400
for x in range(-offset_x, 400, 20):
    if (x//20) % 2 == 0:
        pts = [(x, 0), (x+20, 0), (x+20+offset_x, 400), (x+offset_x, 400)]
        pygame.draw.polygon(stripes, "red", pts)

# Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

    # Re-draw the window
    window.fill( DARK_BLUE )                             # background fill
    pygame.gfxdraw.textured_polygon(window, star_points, stripes, 0, 0)
    pygame.display.flip()                                # Update the display

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()

Option 2

import pygame

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400

DARK_BLUE  = (   3,   5,  54)
STARRY     = ( 230, 255, 80 )

### initialisation
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ) )
pygame.display.set_caption("Star")

# Define a star
centre_coord = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
star_points  = [ (165, 151), (200, 20), (235, 151), (371, 144), (257, 219),
                 (306, 346), (200, 260), (94, 346), (143, 219), (29, 144)   ]

stripes = pygame.Surface(window.get_size())
stripes.fill(STARRY)
offset_x = 400
for x in range(-offset_x, 400, 20):
    if (x//20) % 2 == 0:
        pts = [(x, 0), (x+20, 0), (x+20+offset_x, 400), (x+offset_x, 400)]
        pygame.draw.polygon(stripes, "red", pts)

mask_image = pygame.Surface(stripes.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(mask_image, (255, 255, 255), star_points)
mask = pygame.mask.from_surface(mask_image)
star_stripes = mask.to_surface(setsurface = stripes.convert_alpha(), unsetcolor = (0, 0, 0, 0))

# Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

    # Re-draw the window
    window.fill( DARK_BLUE )                             # background fill
    window.blit(star_stripes, (0, 0))
    pygame.display.flip()                                # Update the display

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • @3141592654 You can draw diagonal strips with `pygame.draw.polygon`. See the answer. – Rabbid76 Jul 07 '23 at 14:27
  • *"The other thing is that you could rotate the surface after drawing straight lines"*. No, you can't. The surface will not be filled with stripes on the corners, but with a uniform color (If you are talking about `pygame.transform.rotate`). Anyway, creating the stripes is not the main point of the question. The main point is to apply a pattern or texture only to a specific shape, but not to a rectangular area. – Rabbid76 Jul 07 '23 at 19:42
  • @3141592654 Use "Option 2" and `pygame.draw.circle(mask_image, (255, 255, 255), center, radius)` instead of `pygame.draw.polygon(mask_image, (255, 255, 255), star_points)`. See also https://stackoverflow.com/questions/64075338/how-to-make-circular-surface-in-pygame/64075812#64075812 and https://github.com/Rabbid76/PyGameExamplesAndAnswers/blob/master/documentation/pygame/pygame_clipping.md – Rabbid76 Jul 20 '23 at 20:49