Time for Action – using matplotlib in Pygame

In this recipe, we take the position coordinates of the previous section and make a graph of them.

  1. To integrate matplotlib with Pygame, we need to use a non-interactive backend; otherwise matplotlib will present us with a GUI window by default. We will import the main matplotlib module and call the use() function. Call this function immediately after importing the main matplotlib module and before importing other matplotlib modules:
    import matplotlib as mpl
       
    mpl.use("Agg")
  2. We can draw non-interactive plots on a matplotlib canvas. Creating this canvas requires imports, creating a figure and a subplot. Specify the figure to be 3 by 3 inches large. More details can be found at the end of this recipe:
    import matplotlib.pyplot as plt
    import matplotlib.backends.backend_agg as agg
    
    fig = plt.figure(figsize=[3, 3])
    ax = fig.add_subplot(111)
    canvas = agg.FigureCanvasAgg(fig)
  3. In non-interactive mode, plotting data is a bit more complicated than in the default mode. Since we need to plot repeatedly, it makes sense to organize the plotting code in a function. Pygame eventually draws the plot on the canvas. The canvas adds a bit of complexity to our setup. At the end of this example, you can find more detailed explanation of the functions:
    def plot(data):
       ax.plot(data)
       canvas.draw()
       renderer = canvas.get_renderer()
    
       raw_data = renderer.tostring_rgb()
       size = canvas.get_width_height()
    
       return pygame.image.fromstring(raw_data, size, "RGB")

    The following screenshot shows the animation in action. You can also view a screencast in the code bundle (matplotlib.mp4) and on YouTube at: https://www.youtube.com/watch?v=t6qTeXxtnl4.

    Time for Action – using matplotlib in Pygame

    We get the following code after the changes:

    import pygame, sys
    from pygame.locals import *
    import numpy as np
    import matplotlib as mpl
    
    mpl.use("Agg")
    
    import matplotlib.pyplot as plt
    import matplotlib.backends.backend_agg as agg
    
    fig = plt.figure(figsize=[3, 3])
    ax = fig.add_subplot(111)
    canvas = agg.FigureCanvasAgg(fig)
    
    def plot(data):
       ax.plot(data)
       canvas.draw()
       renderer = canvas.get_renderer()
    
       raw_data = renderer.tostring_rgb()
       size = canvas.get_width_height()
    
       return pygame.image.fromstring(raw_data, size, "RGB")
    
    pygame.init()
    clock = pygame.time.Clock()
    screen = pygame.display.set_mode((400, 400))
    
    pygame.display.set_caption('Animating Objects')
    img = pygame.image.load('head.jpg')
    
    steps = np.linspace(20, 360, 40).astype(int)
    right = np.zeros((2, len(steps)))
    down = np.zeros((2, len(steps)))
    left = np.zeros((2, len(steps)))
    up = np.zeros((2, len(steps)))
    
    right[0] = steps
    right[1] = 20
    
    down[0] = 360
    down[1] = steps
    
    left[0] = steps[::-1]
    left[1] = 360
    
    up[0] = 20
    up[1] = steps[::-1]
    
    pos = np.concatenate((right.T, down.T, left.T, up.T))
    i = 0
    history = np.array([])
    surf = plot(history)
    
    while True: 
       # Erase screen
       screen.fill((255, 255, 255))
    
       if i >= len(pos):
          i = 0
          surf = plot(history)
    
       screen.blit(img, pos[i])
       history = np.append(history, pos[i])
       screen.blit(surf, (100, 100))
    
       i += 1
    
       for event in pygame.event.get():
          if event.type == QUIT:
             pygame.quit()
             sys.exit()
    
       pygame.display.update()
       clock.tick(30)

What just happened?

The following table explains the plotting related functions:

Function

Description

mpl.use("Agg")

This function specifies to use the non-interactive backend

plt.figure(figsize=[3, 3])

This function creates a figure of 3 by 3 inches

agg.FigureCanvasAgg(fig)

This function creates a canvas in non-interactive mode

canvas.draw()

This function draws on the canvas

canvas.get_renderer()

This function gets a renderer for the canvas

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

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