1

I'm making a game and have a fish sprite with alpha colour pink, I want to change the colour pink on to something else, so fo instance here I tried to change it to orange but instead it made it red because I think it's blending somehow? Is there a way I can fill in just the alpha pixels or specify a colour to change?

fish sprite

Thanks, all the best

self.image = pygame.image.load(os.path.join(game_folder,"boxfish.png")).convert()
self.image.set_colorkey(Colour.pink)
self.rect = self.image.get_rect()
self.image.fill(Colour.orange,special_flags = 3)
Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • Can you please add the fish picture on the question? Do you want the entire background to be colored, or do you only want to tint an area "inside" the fish? – Rabbid76 Jun 25 '20 at 14:55
  • I want the pink in the fish to be any colour I like, green, blue etc – Joe Ovenden Jun 25 '20 at 16:54

2 Answers2

2

A very quick way of doing it is just to use transform.threshold.

Or you can use this function

def change_color(img, oldcolor, newcolor):
    for x in range(img.get_width()):
        for y in range(img.get_height()):
            pixel_color = img.get_at((x, y))  # Preserve the alpha value.
            if oldcolor == pixel_color:
                img.set_at((x, y), newcolor)  # Set the color of the pixel.
xszym
  • 928
  • 1
  • 5
  • 11
  • `transform.threshold` sounds like a great way to do it. Do you have an example handy? I can't get it to work quickly. – Kingsley Jun 25 '20 at 22:31
  • Got it: `pygame.transform.threshold( pink_fish_image, new_image, PINK_COLOUR, set_color=desired_colour, inverse_set=True )`. But you need to make a new/copy of the image, or another surface for the destination. Great suggestion! It helped me learn something new. – Kingsley Jun 25 '20 at 22:40
  • Thank for pointing out `transform.threshold()`. Like Kingsley, I was unaware of that method and it looks handy. The question I have is why you didn't actually use that in your answer? Since the libraries are usually coded in C, it is likely WAY faster than the python routine you actually answered with. Can I suggest you update your answer to at least include a version using that too? – Glenn Mackintosh Jun 26 '20 at 00:35
  • Thank you very much this is great! – Joe Ovenden Jun 26 '20 at 10:31
2

Since the entire sprite "colour" is filled with pink, a neat way to solve this issue is to make the sprites main colour transparent, and then overlay it onto a same-sized rectangle of the desired hue.

First make a fish with a transparent background (I used TheGIMP to edit it).

clear fish
clear_fish.png

Then in your sprite class (or however you want to implement it), create a pygame.Surface the same size, filling it with the desired colour. Then blit() the clear-fish image on top of the coloured surface.

fish_image = pygame.image.load( 'clear_fish.png' )  # un-coloured fish
fish_rect  = fish_image.get_rect()

# Apply some coloured scales to the fish
fish_scales= pygame.Surface( ( fish_rect.width, fish_rect.height ) )
fish_scales.fill( colour )
fish_scales.blit( fish_image, (0,0) )
fish_image = fish_scales               # use the coloured fish

example window

Ref: Full Example Code ~

import pygame
import random

# Window size
WINDOW_WIDTH    = 600
WINDOW_HEIGHT   = 600
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54)


### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("1-Fish, 2-Fish, Pink Fish, Clear Fish")

class FishSprite( pygame.sprite.Sprite ):
    def __init__( self, colour ):
        pygame.sprite.Sprite.__init__( self )
        self.image = pygame.image.load( 'clear_fish.png' )
        self.rect  = self.image.get_rect()

        # Apply some coloured scales to the fish
        fish_scales= pygame.Surface( ( self.rect.width, self.rect.height ) )
        fish_scales.fill( colour )
        fish_scales.blit( self.image, (0,0) )
        self.image = fish_scales                # use the coloured fish

        # Start position is randomly across the screen
        self.rect.center = ( random.randint(0, WINDOW_WIDTH), random.randint(0,WINDOW_HEIGHT) )

    def update(self):
        # Just move a bit
        self.rect.x += random.randrange( -1, 2 )
        self.rect.y += random.randrange( -1, 2 )


### Sprites
fish_sprites = pygame.sprite.Group()
fish_sprites.add( FishSprite( ( 255, 200,  20 ) ) )  # add some fish
fish_sprites.add( FishSprite( ( 255,  20, 200 ) ) )
fish_sprites.add( FishSprite( (  55,  00, 200 ) ) )
fish_sprites.add( FishSprite( (  20, 200,  20 ) ) )

### 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
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click add a fish
            mouse_pos     = pygame.mouse.get_pos()
            random_red    = random.randint( 50, 250 )
            random_green  = random.randint( 50, 250 )
            random_blue   = random.randint( 50, 250 )
            random_colour = ( random_red, random_green, random_blue )
            fish_sprites.add( FishSprite( random_colour ) ) 

    # Update the window, but not more than 60fps
    fish_sprites.update()
    window.fill( DARK_BLUE )
    fish_sprites.draw( window )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)


pygame.quit()
Kingsley
  • 14,398
  • 5
  • 31
  • 53