Title: Blinds Wipe Effect

Author: Gareth Noyce (g at korruptor.demon.co.uk)
Submission date: March 3, 2002

Description: A white-to-black 'blinds' transition effect

Download: blinds.zip

pygame version required: Any, with surfarray
SDL version required: Any
Python version required: Any, with Numeric

Comments: Garath Noyce wows us with another Numeric-powered pygame effect. This time it's a 'blinds' transition, familiar to anyone who's ever had to sit through a powerpoint presentation. Here we fade from white to black, and from right to left - it should be pretty easy to do a bitmap fade, or to change the direction of the wipe. The numeric code is as difficult to follow as usual, but Mr. Noyce's 'extreme' approach to commenting should guide you through.

Messages: 0

"""Blinds.py -- Gareth Noyce (aka Korruptor) v1.0 -- Testcode for Seal Basher...


This is a little effect to produce a window blind effect. Another useful transtion...

This version just blits a white background and performs the blinds effect over the top
of that. It also uses an 8bit palette, however, it's easy to move to a real colou
version, and using numeric's subtract() function, you could easily draw the blinds
over a bitmap... Have a play...

The routine itself is fairly simple (as usual for me!):

We intially divvy up the screen into eight chunks (blind_cut).

We then draw an initial blind at the far right of the screen by drawing two black columns seperated by
blind_cut number of columns, we then fill these (fade) shades darker than what they where previously 

With this intial blind drawn, we can loop from left to right across the surfarray (jumping blind_cut number of cols), 
looking for black columns, which indicate the start of a blind. When we find one, we look for the blind inside the
black columns, and if found we decrease the blind's width by drawing two more black columns, one either side of the blind, 
and fill the center of the blind (fade) shades darker...

If we passed five black columns whilst looking for the inside of the blind, we draw a new blind to the left of the one 
we're working on, which will be picked up and worked on in the next iteration.

If we find no blind to fade, we skip the loop, unless we're at the left hand edge of the screen, in which case
we exit out of the function...

Phew! It's probably easier to read the code! ;-)

The function itself takes a surfarray, the dimensions of the array, and a surface to blit
the effect onto. It also doesn't return until it's complete, but it should be fairly
easy to remove this and control the function "more directly"...

>>> One thing to be aware of: Make sure the fade amount gives you enough 'steps' for the width of the blind on a given screen 
    resolution. Two large a number will see the blind pop back to a white fill half way through the transtion...

Have fun...



import pygame
from pygame.surfarray import *
from pygame.locals import *
from Numeric import *


RES = array((640,480))
COLOUR_MAP = [[]] * 256


def main():
	" Initialises display, fills a dummy screen to white, calls the blind effect..."

	# Init pygame, grab an 8bit display...

	#setup a surface for the display, and a palette which we'll use...
	screen_surface 	= pygame.display.set_mode(RES, 0, 8)

    	# setup the screen palette... (Just greyscale 8bit for this hacK)	
	for i in range(0,256):
        	COLOUR_MAP[i] = (i),(i),(i)

	# Slap the palette onto the screen...

	# Fill the screen with white, as we know we'll fade up to white for the effect, so this will always be our base colour...

	# Create a surfarray of the screen for hacking on...
	screen_map = pygame.surfarray.array2d(screen_surface)

	# Quick ping of the display...

	# Call the blinds function...
	blinds(screen_map, RES, screen_surface, 6)
	# Print out a little message, and exit...
	print "Blinds transition, Korruptor 2002"

def blinds(map,size, screen, fade):
	"Using a 256 colour palette, this function will draw a blinds effect across the screen, leaving a black background..."

	# Calculate the width of each "blind"
	blind_cut = size[0]/8

	#:::::Initial setup for the first blind:::::

	# Draw a black column on the far right column of the screen
	map[size[0]-1][0:size[1]] = 0

	# Grab the colour on the column "inside" of what will become the blind 
	# (white in this example, but I'm trying to be palette agnostic)...
	current_col = map[size[0]-1][0]

	# Fill the "inside" of the blind 'fade' shades darker...
	for i in range (1,blind_cut):
		map[size[0]-(i+1)][0:size[1]]= current_col - fade

	# Fill the start of this blind with black so we have something to find in our loop...
	map[size[0]-blind_cut][0:size[1]]= 0

	#:::::Initial Blind Setup Completed:::::

	# That's the first blind created, we now go into our "find and fill" loop until the screen has transitioned...
	# We'll trip this sentinal when wecan figure out we're finished...
	fin = 0
	while not(fin):

		# From left to right of the screen, move in blind_cut steps...
		for i in range (0,size[0]-1,blind_cut):
			# And see if we've found the start of a blind (a black column)
			if (map[i][0]== 0):
				# We've found the start of a blind!
				j = 1

				# move inward over the black columns...
				# until we find the blind which we'll need to fill...
				while (j<blind_cut) and (map[i+j][0]==0):

				# Here's where we do our 'exit' checks, and prevent any out of bounds surfarray access
				# If we've traveresed the full width of a blind and found nothing to fill, we know 
				# we can ignore this one and continue with the loop...
				if (j == blind_cut):

					# But! We need to make sure we're not at the far left of the screen...
					# if that's the case, we know we're done here... :-)
						fin = 1
					# Ok, the transition isn't complete yet, so we'll just jump out of this loop...
				# Here's the "business" end of the blinds routine...
				# we've found the inside of the blind, so, we decrease it's width
				# by adding a black coloumn to the left and right of the blind... 
				map[i+j][0:size[1]] = 0
				map[(i+blind_cut)-(j)][0:size[1]] = 0

				# Now we've got to fill the inside of the blind, so grab it's current colour...
				current_col = map[i+j+1][0]

				# ...and fill the inside of the blind 'fade' shades darker...
				for k in range((i+j+1),(i+(blind_cut-j))-1):
					map[k][0:size[1]] = current_col - fade

				# if we've reached the criteria where we make a new blind
				if j==5:
					# start it off, this will give us something to trip over in the next iteration of the loop


		# Blit this iteration to the screen and show it...
		blit_array(screen, map)


if __name__ == '__main__': main()

Main - Repository - Submit - News