pythonpygletcellular-automata

Pyglet- Moving many shapes at once


I am making a langton's ant cellular automata program, and I want the user to be able to pan and zoom. Right now, I have all my rectangles (grid squares) stored as a dictionary, and to move/zoom, I iterate through all of them and apply the transformation needed.

def zoom(self, factor, center_x, center_y):
    for x in range(WIDTH):
        for y in range(HEIGHT):
            rect =  self.rects[x][y]
            self.rects[x][y].x = (rect.x - center_x)*factor + center_x
            self.rects[x][y].y = (rect.y - center_y)*factor + center_y
            self.rects[x][y].width = rect.width * factor
            self.rects[x][y].height = rect.height * factor

However, with the amount of rectangles (32,000), it takes a second or to do pan and zoom. Is there any better way of doing it than this? Thanks!

Here is the full code


Solution

  • Yes. Use OpenGL transformation matrices to apply transformations. These will be calculated on the GPU for performance gain.

    pyglet.graphics.Group lets you group together such transformations in order to apply them automatically to Pyglet primitives when drawing them.

    Example

    We create a CameraGroup that pans and zooms objects into view.

    import pyglet.gl as gl
    import pyglet.shapes
    
    class CameraGroup(Group):
        def __init__(self, window, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.win = window
    
        def set_state(self):
            gl.glPushMatrix()
            x = -(self.win.x - self.win.width // 2)
            y = -(self.win.y - self.win.height // 2)
            gl.glTranslatef(x, y, 0.0)
            gl.glScalef(self.win.factor, self.win.factor, 1.0)
    
        def unset_state(self):
            gl.glPopMatrix()
    

    The example assumes you have the properties center_x, center_y and factor on your window.

    Apply the group by attaching it to Pyglet objects.

    cam_group = CameraGroup(main_win)
    rect = pyglet.shapes.Rectangle(250, 300, 400, 200, color=(255, 22, 20), batch=batch, group=cam_group)
    

    When rect gets rendered the group transformations area applied automatically.

    You can also construct more complex groups if needed.