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
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.
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.