2009-12-25
Recently, I've been getting a lot of hits from people searching for "pyclutter examples". Unfortunately, the code that most people find is my hello world example that was written for Clutter 0.6 and since the API for Clutter has change quite a bit since I wrote that code, the code doesn't work with the latest stable release of Clutter.

I've considered updating the code to work with the more modern Clutter, but that wouldn't really be fun would it? Besides, someone has already updated the code. Thanks Ryan. Why don't I write another example? Don't mind if I do.

There is nothing new Clutter-wise in this example to differentiate it from the hello world example except that this code will run with the latest Clutter.


What we have here, is John Conway's Game of Life where each cell is a Clutter Rectangle.
#!/usr/bin/env python # copyright 2009 jezra lickter #this software is licensed under the GPLv3  http://www.gnu.org/licenses/gpl.txt import clutter import random class Game:     def __init__(self,cell_size):         self.cells = []         #create a clutter stage         self.stage clutter.Stage()         #set the stage size in x,y pixels         self.stage.set_size(500,500)         self.stage.set_title("The Game of Life")         self.stage_widthself.stage_height self.stage.get_size()         #define some clutter colors in rgbo (red,green,blue,opacity)         self.color_black =clutter.Color(0,0,0,255         self.color_green =clutter.Color(0,255,0,255)         self.color_blue =clutter.Color(0,0,255,255)         #set the clutter stages bg color to our black         self.stage.set_color(self.color_black)         #we will need to check on the key presses from the user         self.stage.connect('key-press-event'self.parseKeyPress)         self.stage.connect("destroy"self.quit)         '''fill the screen with rectangles'''         num_cols int(self.stage_width/cell_size)         num_rows int(self.stage_height/cell_size)         cells_to_create num_cols*num_rows         0         for row in range(num_rows):             0             self.cells.append( [] )             print "%i cells to create" % (cells_to_create)             for column in range(num_cols):                 #set the column index to a rect that is cell_size by cell_size                 self.cells[row].appendclutter.Rectangle() )                 self.cells[row][column].set_size(cell_size,cell_size)                 self.cells[row][column].set_position(x,y)                 #add this cell to the stage                 self.stage.add(self.cells[row][column])                 self.cells[row][column].set_color(self.color_green)                 self.cells[row][column].set_opacity(0)                 x+=cell_size             cells_to_create-=num_cols                          y+=cell_size         print "cells created"         #get some data about the rows         self.row_count  len(self.cells)         self.col_count len(self.cells[0])              self.cell_count self.row_count*self.col_count         #make a timer to do stuff for us         self.timeline clutter.Timeline(duration=500)         #when the timer finishes running, we want to determine the life         self.timeline.connect("completed",self.compute_life)         #increase linearly         alpha clutter.Alpha(self.timelineclutter.LINEAR)         #make some opacity behaviours that we will apply to the cells         self.dieBehaviour clutter.BehaviourOpacity(255,0,alpha)         self.aliveBehaviour clutter.BehaviourOpacity(0,255,alpha)              def parseKeyPress(self,actor,event):         if event.keyval == clutter.keysyms.q:             self.quit()         elif event.keyval == clutter.keysyms.c:             self.compute_life()         elif event.keyval == clutter.keysyms.r:             self.reseed()          def quit(self,widget=None):         clutter.main_quit()          def run(self):         self.stage.show_all()         self.seed_life()         self.compute_life()         clutter.main()              def reseed(self):         for in range(self.row_count):             for in range(self.col_count):                 if self.cells[r][c].get_opacity()>0:                     self.cells[r][c].set_opacity(0)         self.seed_life()              def seed_life(self):         print "adding random life"         #loop through the rows         for in range(self.row_count):         #loop through the columns             for in range(self.col_count):                 #generate a number                 random.randint(0,4)                 if i==0:                     # x,y is alive                     self.cells[r][c].set_opacity(255)              def compute_life(self,asset=None):         #detach all objects from the behaviors         self.dieBehaviour.remove_all()         self.aliveBehaviour.remove_all()         for in range(self.row_count):             for in range(self.col_count):                 if self.cells[r][c].get_opacity()>0:                     alive=True                 else:                     alive=False                 ln self.living_neighbors(r,c)                 if alive and ln<or ln>):                     #this cell will die; boohoo                     self.dieBehaviour.apply(self.cells[r][c] )                 elif not alive and ln==3:                     #this cell is now alive; damn zombies                     self.aliveBehaviour.apply(self.cells[r][c] )                                      #start the timeline again         self.timeline.start()                      def living_neighbors(self,r,c):         alive 0         r_min r-1         r_max r+1         c_min c-1         c_max c+1         if r==:             r_min=r         elif == self.row_count-1:             r_max=r         if c==:             c_min=c         elif == self.col_count-1:             c_max=c                      tr r_min         tc c_min         cells_computed=0         while not tr r_max:             tc c_min             while not tc c_max:                 if tr!=or tc!=):                     cells_computed+=1                     if self.cells[tr][tc].get_opacity()>0:                         alive+=1                 tc+=1             tr+=1         return alive          if __name__=="__main__":     game Game(5)     game.run()

When running the code: press "q" to quit, press "r" to reset.

One issue I have with this code is that when creating the rectangles for the cells, creation slows down significantly after creating about 3000 rectangles. The app runs fine when all of the cells are created, but the slow down during creation really irks me. Perhaps I need more RAM or I should write the code in Vala using SDL?

Now stop reading, and go play with colored rectangles.
Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
6 minus 4
Answer:
required
subscribe
 
2019
2016
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008