Python graphics question:pixel scrolling

Raymond Luxury-Yacht rlyacht at gmail.com
Fri Aug 29 10:57:10 EDT 2008


To learn python, I've been trying to write a simple graphics program
which displays a 1D cellular automaton's evolution.  The last time I
wrote this program, it was in C for a CGA adaptor (!) in which the
display was mapped to two interlaced blocks of memory, and scrolling
up two lines of pixels was very simple and very smooth.  The code
below works, and uses pygame for the graphics.  But the scrolling is
quite flickery when using large windows.  I'm sure that the code
contains various neophyte python errors, and I'd appreciate any
comments on that, but my main question is how I ought to have coded it
in order to have the scrolling be smooth.  I did see a comment on a
pygame site saying that pygrame should not be used for side-scrollers,
to which this is similar.  Is there a better way with python?

p.s. It can be run without any args and will select an interesting
rule. To change resolution to see the flickering get worse, change
HEIGHT and WIDTH.

# Simple 1D Cellular Automaton
#
# The world is a line of cells in which each cell has a state of 0 - 3
# The states change according to a rule that specifies a new state as
a function
# of the sum of a cell's state and those of its nearest neighbors
# Since the sum can be between 0 = 0+0+0 and 9 = 3+3+3, the rule can
be represented
# by an array of 10 integers, each between 0 and 3.
#
# To represent this graphically, each state will correspond to a color
on a row
# of window.
#
# The first generation is initialized to have a single 1 in the middle
of the bottom row
# When a new generation is computed, the preceding generations will be
scrolled up and the
# new generation displayed on the bottom line.

import pygame
from pygame.locals import *
import numpy
import sys
#import pdb

WIDTH = 300  #width of screen
HEIGHT = 300 #height of screen
MIDDLE = WIDTH/2

COLORS =   [  0x000000, 0xFF0000,  0x00FF00,  0x0000FF ]
COLORNUM = {}
for i in range(len(COLORS)):
    COLORNUM[ COLORS[i]] = i

#pdb.set_trace()
pygame.surfarray.use_arraytype ('numpy')

def main():
    # Default to an interesting rule if none is given
    if len(sys.argv) < 2:
        rule_string = "0322301013"
    else:
        rule_string = sys.argv[1]  # assume it's there
    rule = [ COLORS[int(d)] for d in rule_string ]

    pygame.display.init()

    screen = pygame.display.set_mode((WIDTH,HEIGHT),DOUBLEBUF)
    pixels = pygame.surfarray.pixels2d(screen)

    max_width = len(pixels)-1
    max_height = len(pixels[0])-1

    pixels[MIDDLE,-1] =  COLORS[1]
    trpix = numpy.transpose( pixels )
    old = trpix[-1]
    while True:
        new = numpy.zeros( max_width + 1)

        # Note wrap-around allows us to avoid having 0 be a special
case
        for i in range(0, max_width):
            new[i] = rule [COLORNUM[ old[i-1] ] + COLORNUM[ old[i] ] +
COLORNUM[ old[i+1] ]]

        new[max_width] =   rule[COLORNUM[ old[max_width-1] ] +
COLORNUM[ old[max_width] ] + COLORNUM[ old[0] ]]

        # Exit if 'q' is pressed
        for e in pygame.event.get():
            if e.type == KEYDOWN:
                if e.key == K_q:
                    exit(0)

        # Scroll and update the bottom row. Note that we don't have to
assign
        # pixels to be transpose(trpix).
        trpix[0:-1] = trpix[1:]
        trpix[-1] = new
        pygame.display.update()


main()



More information about the Python-list mailing list