Simulating with Pygame (Advanced)

As the last example, we will simulate life with Conway's Game of Life. The original game of life is based on a few basic rules. We start out with a random configuration on a two-dimensional square grid. Each cell in the grid can be either dead or alive. This state depends on the eight neighbors of the cell. Convolution can be used to evaluate the basic rules of the game. We will need the SciPy package for the convolution bit.

Getting ready

Install SciPy with either of the following two commands:

  • sudo pip install scipy
  • easy_install scipy

How to do it...

The following code is an implementation of Game of Life with some modifications:

  • Clicking once with the mouse draws a cross until we click again
  • The R key resets the grid to a random state
  • Pressing B creates blocks based on the mouse position
  • G creates gliders

The most important data structure in the code is a two-dimensional array holding the color values of the pixels on the game screen. This array is initialized with random values and then recalculated in the game loop. More information about the involved functions can be found in the next section. As previously mentioned, the following is the code:

import os, pygame
from pygame.locals import *
import numpy
from scipy import ndimage

def get_pixar(arr, weights):
  states = ndimage.convolve(arr, weights, mode='wrap')

  bools = (states == 13) | (states == 12 ) | (states == 3)

  return bools.astype(int)

def draw_cross(pixar):
   (posx, posy) = pygame.mouse.get_pos()
   pixar[posx, :] = 1
   pixar[:, posy] = 1

def random_init(n):
   return numpy.random.random_integers(0, 1, (n, n))

def draw_pattern(pixar, pattern):
     print pattern

     if pattern == 'glider':
      coords = [(0,1), (1,2), (2,0), (2,1), (2,2)]
     elif pattern == 'block':
      coords = [(3,3), (3,2), (2,3), (2,2)]
     elif pattern == 'exploder':
      coords = [(0,1), (1,2), (2,0), (2,1), (2,2), (3,3)]
     elif pattern == 'fpentomino':
      coords = [(2,3),(3,2),(4,2),(3,3),(3,4)]


     pos = pygame.mouse.get_pos()

     xs = numpy.arange(0, pos[0], 10)
     ys = numpy.arange(0, pos[1], 10)

     for x in xs:
        for y in ys:
           for i, j in coords:
               pixar[x + i, y + j] = 1


def main():
    pygame.init ()

    N = 400
    pygame.display.set_mode((N, N))
    pygame.display.set_caption("Life Demo")

    screen = pygame.display.get_surface()

    pixar = random_init(N)
    weights = numpy.array([[1,1,1], [1,10,1], [1,1,1]])

    cross_on = False

    while True:
       pixar = get_pixar(pixar, weights)

       if cross_on:
          draw_cross(pixar)

       pygame.surfarray.blit_array(screen, pixar * 255 ** 3)
       pygame.display.flip()

       for event in pygame.event.get():
         if event.type == QUIT:
             return
         if event.type == MOUSEBUTTONDOWN:
            cross_on = not cross_on
         if event.type == KEYDOWN:
            if event.key == ord('r'):
               pixar = random_init(N)
               print "Random init"
            if event.key == ord('g'):
               draw_pattern(pixar, 'glider')
            if event.key == ord('b'):
               draw_pattern(pixar, 'block')
            if event.key == ord('e'):
               draw_pattern(pixar, 'exploder')
            if event.key == ord('f'):
               draw_pattern(pixar, 'fpentomino')


if __name__ == '__main__':
    main()

Note

You should be able to view a screencast on YouTube at https://www.youtube.com/watch?v=NNsU-yWTkXM.

A screenshot of the game in action is shown as follows:

How to do it...

How it works...

We used some NumPy and SciPy functions that need explaining:

Function

Description

ndimage.convolve(arr, weights, mode='wrap')

This applies the convolve operation on the given array, using weights in wrap mode. The mode has to do with the array borders. See http://en.wikipedia.org/wiki/Convolution for the mathematical details.

bools.astype(int)

This converts the array of Booleans to integers.

numpy.arange(0, pos[0], 10)

This creates an array from 0 to pos[0] in steps of 10. So if pos[0] is equal to 1000, we will get 0, 10, 20 … 990.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset