Python graphics question:pixel scrolling

  • Thread starter Raymond Luxury-Yacht
  • Start date
R

Raymond Luxury-Yacht

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

#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 = rule [COLORNUM[ old[i-1] ] + COLORNUM[ old ] +
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()
 
P

Paul Boddie

 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?

There are "side-scrollers" written in Python including impressive
games like these:

http://www.pygame.org/project/406/
http://www.pygame.org/project/381/

I see that you're using the surfarray module, which is probably what
you want to do if you're accessing the screen at a pixel level (as
opposed to blitting sprites). My experiences with Numeric/numpy and
Pygame are limited to recolouring bitmaps, but it's certainly possible
to refresh a reasonable size of surface at a decent rate on reasonably
fast hardware. One important hint whose relevance I'm not sure about
here is that you should attempt to avoid frequent format and bit depth
conversions; for sprites and images this usually involves converting
them to the same format as the display surface, but I can imagine that
there may be implications for surfarrays, too.

I hope this gives you some ideas, anyway.

Paul
 
D

Diez B. Roggisch

Raymond said:
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?

You need to to double-buffering. Just as in the old days...

http://www.pygame.org/docs/tut/intro/intro.html

Look for pygame.display.flip()

Diez
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top