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

[pygame] Masking Test: Simulated Lighting



I was thinking about how to simulate a lighting effect in Pygame: a character with a portable light source in a dark room. The code below does something like that by creating a black "mask" covering the screen, then cutting a partially-transparent hole in it around a certain point. For extra fanciness it's not just a circle of "light" but a bunch of inefficiently-drawn concentric circles of varying alpha. By applying the mask to a blue screen with a few white squares, you get a scene that looks dark except where a light source has been drawn.

Besides moving the light sources, using this in a game would probably require blitting pre-drawn circles/gradients onto a fresh mask each frame, rather than calling pygame.draw.circle over and over. It'd also look funny unless you either ordered the light sources to draw the brightest last, or somehow summed the RGBA values at each pixel from every light source. The second method would be more realistic, since that way colored lights would merge rather than one overriding the other. It'd also be possible to draw a hole in a non-black background like a layer of vines or clouds.

Does this method make sense? Is there a better way of doing it short of using OpenGL?

Kris

------


## <code> SCREEN_SIZE = (800,600)

light_size = 100
light_location = (200,200)

## Setup
import pygame
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE)

## A black mask for the screen.
mask = pygame.surface.Surface(SCREEN_SIZE).convert_alpha()
mask.fill((0,0,0,255))

## An inefficiently-drawn shaded "light"
radius = 200
t = 255
delta = 3
while radius > 50:
    pygame.draw.circle(mask,(0,0,0,t),light_location,radius)
    t -= delta
    radius -= delta
pygame.draw.circle(mask,(0,0,0,95),light_location,radius)

## A sharp-edged white "light"
pygame.draw.circle(mask,(0,0,0,0),(400,275),50)

## A red-tinted "light"
pygame.draw.circle(mask,(192,0,0,128),(300,375),50)

## A blue screen with a couple of white squares
screen.fill((0,0,255))
pygame.draw.rect(screen,(255,255,255),(100,100,100,100))
pygame.draw.rect(screen,(255,255,255),(300,250,100,100))

## Cover the screen with the partly-translucent mask
screen.blit(mask,(0,0))

## Make it so
pygame.display.update()
## </code>