pastebin - collaborative debugging tool
alicesucks.kpaste.net RSS


life
Posted by Anonymous on Wed 5th Jan 2011 23:42
raw | new post

  1. # coding=UTF-8
  2. import sys, os
  3. import math
  4. import time
  5. import random
  6.  
  7. import tkFileDialog
  8. import Tkinter
  9.  
  10. import pyglet
  11. from pyglet.window import key, mouse
  12. from pyglet import clock
  13.  
  14. import fileutils
  15. from lifepattern import LifePattern
  16.  
  17. # CONSTANTS
  18.  
  19. OFF_COLOR = (200, 200, 200)
  20.  
  21. # VARIABLES
  22. root = Tkinter.Tk()
  23.  
  24. window = pyglet.window.Window(width=800, height=600)
  25. window.set_caption('Conway\'s Game Of Life')
  26.  
  27. # grid
  28. curX = 0
  29. curY = 0
  30.  
  31. gridDims = {}
  32.  
  33. # cells
  34. cellBatch = pyglet.graphics.Batch()
  35. cellVLists = []
  36.  
  37. curOnCells = set()
  38. otherOnCells = set()
  39.  
  40. cellDims = {}
  41. curCellDim = 15.0
  42.  
  43. # input
  44. mVars = {}
  45. keys = key.KeyStateHandler()
  46.  
  47. # text
  48. infoDoc = pyglet.text.document.UnformattedDocument('')
  49. infoDoc.set_style(None, None,
  50.         {'color': (0, 0, 0, 255),
  51.         'background_color': (255, 255, 255, 255),
  52.         'font_name': 'Arial',
  53.         'font_size': 12})
  54.  
  55. infoLayout = pyglet.text.layout.TextLayout(infoDoc)
  56. infoLayout.anchor_y = 'bottom'
  57.  
  58. # misc
  59. isRunning = False
  60.  
  61. curPattern = None
  62.  
  63. # 0 = 0°
  64. # 1 = 90° clockwise
  65. # 2 = 180°
  66. # 3 = 270°
  67. rotation = 0
  68.  
  69. # FUNCTIONS
  70. def configGrid(desiredCellDim):
  71.     '''
  72.     resets the graphical aspect of the grid, the number and size of cells.
  73.     does not affect actual cell on/off data.
  74.  
  75.     desiredCellDim is the desired width/height of the cell in pixels.
  76.     actual size will vary slightly to fit a whole number of rows and columns on screen.
  77.  
  78.     this should be called when zooming in/out and when window changes size.
  79.     '''
  80.     cellDims['w'] = window.width / (window.width // desiredCellDim)
  81.     cellDims['h'] = window.height / (window.height // desiredCellDim)
  82.     cellDims['borderW'] = 1.0 if cellDims > 1 else 0.0
  83.  
  84.     gridDims['wInCells'] = int(round(window.width / cellDims['w']))
  85.     gridDims['hInCells'] = int(round(window.height / cellDims['h']))
  86.  
  87.     # clear vertex list
  88.     del cellVLists[:]
  89.     # no way to clear a Batch :(
  90.     global cellBatch
  91.     cellBatch = pyglet.graphics.Batch()
  92.     for x in xrange(gridDims['wInCells']):
  93.         cellVLists.append([])
  94.         for y in xrange(gridDims['hInCells']):
  95.             blitX, blitY = x * cellDims['w'], y * cellDims['h']
  96.             cellVLists[-1].append(cellBatch.add(4, pyglet.gl.GL_QUADS, None,
  97.                 ('v2f', (blitX + cellDims['borderW'] / 2, blitY + cellDims['borderW'] / 2,
  98.                     blitX + cellDims['w'] - cellDims['borderW'] / 2, blitY + cellDims['borderW'] / 2,
  99.                     blitX + cellDims['w'] - cellDims['borderW'] / 2, blitY + cellDims['h'] - cellDims['borderW'] / 2,
  100.                     blitX + cellDims['borderW'] / 2, blitY + cellDims['h'] - cellDims['borderW'] / 2)),
  101.                 ('c3B', OFF_COLOR * 4)
  102.             ))
  103.     updateGrid()
  104.  
  105. def resetMVars():
  106.     mVars['curChange'] = None
  107.     mVars['cellsPassed'] = set()
  108.  
  109. def changeCell(x, y, which, updateOnCells = True):
  110.     '''
  111.     updates the display of cell.
  112.    
  113.     if updateOnCells is True, also changes curOnCells
  114.     '''
  115.     if which == 'on':
  116.         desired = True
  117.     elif which == 'off':
  118.         desired = False
  119.     else:
  120.         raise ArgumentError, '3rd argument must be "on" or "off"'
  121.     if updateOnCells:
  122.         if desired:
  123.             curOnCells.add((x, y))
  124.         else:
  125.             curOnCells.discard((x, y))
  126.     x, y = x - curX, y - curY
  127.     if (x < gridDims['wInCells'] and x >= 0 and
  128.             y < gridDims['hInCells'] and y >= 0):
  129.         if desired:
  130.             cellVLists[x][y].colors = (0, 0, 0) * 4
  131.         else:
  132.             cellVLists[x][y].colors = OFF_COLOR * 4
  133.  
  134. def updateGrid():
  135.     for x in xrange(curX, curX + gridDims['wInCells']):
  136.         for y in xrange(curY, curY + gridDims['hInCells']):
  137.             if (x, y) in curOnCells:
  138.                 cellVLists[x - curX][y - curY].colors = (0, 0, 0) * 4
  139.             else:
  140.                 cellVLists[x - curX][y - curY].colors = OFF_COLOR * 4
  141.  
  142. _counts = {}
  143. def runOne():
  144.     global curOnCells, otherOnCells
  145.     _counts.clear()
  146.     otherOnCells.clear()
  147.     for cell in curOnCells:
  148.         for x in xrange(cell[0] - 1, cell[0] + 2):
  149.             for y in xrange(cell[1] - 1, cell[1] + 2):
  150.                 if (x, y) != cell:
  151.                     try:
  152.                         _counts[(x, y)] += 1
  153.                     except KeyError:
  154.                         _counts[(x, y)] = 1
  155.     for cell in _counts:
  156.         if _counts[cell] == 3 or (_counts[cell] == 2 and cell in curOnCells):
  157.             otherOnCells.add(cell)
  158.     for cell in curOnCells - otherOnCells:
  159.         changeCell(cell[0], cell[1], 'off', updateOnCells = False)
  160.     for cell in otherOnCells - curOnCells:
  161.         changeCell(cell[0], cell[1], 'on', updateOnCells = False)
  162.     curOnCells, otherOnCells = otherOnCells, curOnCells
  163.  
  164. def insertPattern(x, y, pattern):
  165.     unencoded = pattern.getUnencoded()
  166.     for dy, line in enumerate(unencoded):
  167.         for dx, cell in enumerate(line):
  168.             if rotation == 0:
  169.                 changeCell(x + dx, y - dy, 'on' if cell else 'off')
  170.             elif rotation == 1:
  171.                 changeCell(x + pattern.height - dy, y - dx, 'on' if cell else 'off')
  172.             elif rotation == 2:
  173.                 changeCell(x + pattern.width - dx, y - pattern.height + dy, 'on' if cell else 'off')
  174.             elif rotation == 3:
  175.                 changeCell(x + dy, y - pattern.width + dx, 'on' if cell else 'off')
  176.  
  177. def setInfoText():
  178.     infoDoc.text = (' Current pattern: %s' % str(curPattern)
  179.             + (' ' if curPattern else ' - press enter to open a pattern')
  180.             + u' || Rotation: %d° CW' % (rotation * 90))
  181.  
  182. # EVENTS
  183. @window.event
  184. def on_draw():
  185.     window.clear()
  186.     if keys[key.UP] or keys[key.DOWN] or keys[key.RIGHT] or keys[key.LEFT]:
  187.         global curX, curY
  188.         curY += (keys[key.UP] - keys[key.DOWN]) * int(20 / cellDims['w'])
  189.         curX += (keys[key.RIGHT] - keys[key.LEFT]) * int(20 / cellDims['w'])
  190.         updateGrid()
  191.     cellBatch.draw()
  192.     infoLayout.draw()
  193.  
  194. @window.event
  195. def on_mouse_press(x, y, button, modifiers):
  196.     if button == mouse.LEFT:
  197.         cellX, cellY = int(x // cellDims['w']) + curX, int(y // cellDims['h']) + curY
  198.         if (cellX, cellY) in curOnCells:
  199.             mVars['curChange'] = 'off'
  200.         else:
  201.             mVars['curChange'] = 'on'
  202.         changeCell(cellX, cellY, mVars['curChange'])
  203.         mVars['cellsPassed'].add((cellX, cellY))
  204.     elif button == mouse.RIGHT:
  205.         cellX, cellY = int(x // cellDims['w']) + curX, int(y // cellDims['h']) + curY
  206.         if curPattern:
  207.             insertPattern(cellX, cellY, curPattern)
  208.  
  209. @window.event
  210. def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
  211.     if buttons & mouse.LEFT:
  212.         # draw through all cells in line dragged through
  213.         factor = math.sqrt(x * x + y * y)
  214.         dx, dy = dx / factor, dy / factor
  215.         for i in xrange(int(factor)):
  216.             cellX, cellY = int(x // cellDims['w']) + curX, int(y // cellDims['h']) + curY
  217.             if ((cellX, cellY) not in mVars['cellsPassed'] and
  218.                     cellX >= curX and cellX < curX + gridDims['wInCells'] and
  219.                     cellY >= curY and cellY < curY + gridDims['wInCells']):
  220.                 if (cellX, cellY) in curOnCells and mVars['curChange'] == 'off':
  221.                     changeCell(cellX, cellY, mVars['curChange'])
  222.                 elif (cellX, cellY) not in curOnCells and mVars['curChange'] == 'on':
  223.                     changeCell(cellX, cellY, mVars['curChange'])
  224.                 mVars['cellsPassed'].add((cellX, cellY))
  225.             x -= dx
  226.             y -= dy
  227.  
  228. @window.event
  229. def on_mouse_release(x, y, button, modifiers):
  230.     resetMVars()
  231.  
  232. @window.event
  233. def on_key_press(symbol, modifiers):
  234.     if symbol == key.SPACE:
  235.         global isRunning
  236.         isRunning = not isRunning
  237.     elif symbol == key.C:
  238.         curOnCells.clear()
  239.         updateGrid()
  240.     elif symbol == key.PLUS:
  241.         global curCellDim
  242.         curCellDim += 1
  243.         configGrid(curCellDim)
  244.     elif symbol == key.MINUS:
  245.         global curCellDim
  246.         curCellDim -= 1
  247.         configGrid(curCellDim)
  248.     elif symbol == key.ENTER:
  249.         global curPattern
  250.         filename = tkFileDialog.askopenfilename()
  251. ##        root.destroy()
  252.         if filename:
  253.             curPattern = LifePattern(filename)
  254.             setInfoText()
  255.     elif symbol == key.R:
  256.         global rotation
  257.         rotation = (rotation + 1) % 4
  258.         setInfoText()
  259.  
  260. # CLOCK
  261. def runPerFrame(dt):
  262.     if isRunning:
  263.         runOne()
  264.  
  265. # INIT
  266. root.withdraw()
  267.  
  268. resetMVars()
  269. window.push_handlers(keys)
  270.  
  271. clock.schedule(runPerFrame)
  272.  
  273. configGrid(curCellDim)
  274.  
  275. setInfoText()
  276.  
  277. pyglet.app.run()

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}





All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at