Brandyn
Brandyn

Reputation: 1017

Adding Lighting Pygame

I have created a day and nigh cycle in a game of mine by drawing a rectangle over the screen and having it's alpha change constantly. However, I obviously want to add some lighting to the game. Is there a way to kind of set the alpha of a particular part of a rectangle to 0 using pygame? Or is there perhaps another way of going about this whole lighting thing?

This is how my daylight cycle works (it is quite bad and the night is longer, but it is only for testing):

#Setting up lighting
game_alpha = 4 #Keeping it simple for now
game_time = 15300
time_increment = -1
alpha_increment = 1

#Main Game Loop:
if float(game_time)%game_alpha == 0:
       game_alpha += alpha_increment
       print "Game Alpha: ",game_alpha
       print "Game Time: ", game_time
if game_time < 0:
       time_increment = 1
       alpha_increment = -1
elif game_time >= 15300:
       time_increment = -1
       alpha_increment = 1

    game_shadow = pygame.Surface((640, 640))
    game_shadow.fill(pygame.Color(0, 0, 0))
    game_shadow.set_alpha(game_alpha)
    game_shadow.convert_alpha()
    screen.blit(game_shadow, (0, 0))

Upvotes: 2

Views: 1618

Answers (1)

trevorKirkby
trevorKirkby

Reputation: 1897

While there may be a way to assign different alpha channels to different pixels, this would be difficult and if you were doing it per-pixel it would significantly slow down your program (if you are really determined to do this, the closest thing I could find was pygame.Surface.set_at). It seems that you probably are best off just breaking down the screen into smaller surfaces. You could even achieve an easy gradient by making them overlap. This way you can set various brightnesses to areas, to get both effects. Below is a basic example of a tile grid used to achieve what you want:

tiles = []
column = []
for row in range(10):
    for column in range(10):           #These dimensions mean that the screen is broken up into a grid of ten by ten smaller tiles for lighting.
        tile = pygame.Surface((64, 64))
        tile.fill(pygame.Color(0, 0, 0))
        tile.set_alpha(game_alpha)
        tile.convert_alpha()
        column.append(tile)
    tiles.append(column)               #this now gives you a matrix of surfaces to set alphas to

def draw():                            #this will draw the matrix on the screen to make a grid of tiles
    x = 0
    y = 0
    for column in tiles:
        for tile in column:
            screen.blit(tile,(x,y))
            x += 64
        y += 64

def set_all(alpha):
    for column in tiles:
        for tile in column:
            tile.set_alpha(alpha)

def set_tile(x,y,alpha):        #the x and y args refer to the location on the matrix, not on the screen. So the tile one to the right and one down from the topleft corner, with the topleft coordinates of (64,64), would be sent as 1, 1
    Xindex = 0
    Yindex = 0
    for column in tiles:
        for tile in column:
            if Xindex == x and Yindex == y:
                tile.set_alpha(alpha)            #when we find the correct tile in the coordinates, we set its alpha and end the function
                return
            x += 1
        y += 1

This should give you what you want. I also included some functions to access the set of tiles. Set_all will change the alpha of the whole screen by a certain amount, set_tile will only change the alpha of one tile, and draw will draw all of the tiles. You could improve upon this model more by overlapping tiles to get more exact lighting and gradients, and by making a tile class to inherit pygame.Surface, that will manage things like the tile's position.

Upvotes: 1

Related Questions