[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Masking Test: Simulated Lighting (Follow-Up)



Kris Schnee wrote:
But a problem appeared in trying to make the process more efficient, by drawing a lightmask on its own, once, then each blitting it onto the black mask, then blitting the black mask onto the screen. Doing it that way would be better for complex, gradient lights such as the big one seen in my previous code. That is, you'd make a (radius*2,radius*2) surface that's black with a gradually-shaded circle of translucency, once, then blit it onto solid black each frame. But when I tried that,
Pygame took me too literally.

Try the following code. It uses a gradient light.

import pygame

SCREENSIZE = [800, 600]
LIGHTSIZE = 400
NIGHTCOLOR = [0, 0, 0, 200]

def CreateLight():
    gradient = pygame.Surface([LIGHTSIZE, LIGHTSIZE], 0, 8)
    gradient.set_palette([[x, x, x] for x in range(256)])
    a = NIGHTCOLOR[3]
    gradient.fill((a, a, a))
    r = LIGHTSIZE/2
    for i in range(r):
        c = (a * (r-i))/r
        pygame.draw.circle(gradient, [c, c, c], [r, r], r-i)
        c -= 1
    return gradient

def CreateBackground():
    bg = pygame.Surface(SCREENSIZE, pygame.SRCALPHA, 32).convert_alpha()
    bg.fill((0, 0, 128, 255))
    bg.fill((255, 0, 0, 255), (50, 50, 100, 100))
    return bg

def CreateNight():
    pic = pygame.Surface(SCREENSIZE, pygame.SRCALPHA, 32).convert_alpha()
    pic.fill(NIGHTCOLOR)
    return pic

def CreateAlpha():
    pic = pygame.Surface(SCREENSIZE, 0, 8)
    pic.set_palette([[x, x, x] for x in range(256)])
    a = NIGHTCOLOR[3]
    pic.fill([a, a, a])
    return pic

def RefreshNight(night, alpha, light, x, y):
a = NIGHTCOLOR[3]
alpha.fill([a, a, a])
r = LIGHTSIZE/2
alpha.blit(light, [x-r, y-r])
pygame.surfarray.pixels_alpha(night)[:, :] = pygame.surfarray.pixels2d(alpha)


def main():
pygame.init()
screen = pygame.display.set_mode(SCREENSIZE, 0, 32)
bg = CreateBackground()
circle = CreateLight()
night = CreateNight()
alpha = CreateAlpha()
done = 0
x, y = 400, 300
while not done:
RefreshNight(night, alpha, circle, x, y)
screen.blit(bg, (0, 0))
screen.blit(night, (0, 0))
pygame.display.flip()
pygame.event.pump()
for event in pygame.event.get():
if (event.type == pygame.QUIT) or \
(event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
done = True
break
elif event.type == pygame.MOUSEMOTION:
x, y = event.pos
pygame.quit()


main()