Creating Environment for our Object with PyGame




Welcome to part 14 of the intermediate Python programming tutorial series. In this tutorial, we're going to be creating the PyGame environment for our object.

Code from the previous tutorial:

class Blob:
    
    def __init__(self, color):
        self.x = random.randrange(0, WIDTH)
        self.y = random.randrange(0, HEIGHT)
        self.size = random.randrange(4,8)
        self.color = color

    def move(self):
        self.move_x = random.randrange(-1,2)
        self.move_y = random.randrange(-1,2)
        self.x += self.move_x
        self.y += self.move_y
        
        if self.x < 0: self.x = 0
        elif self.x > WIDTH: self.x = WIDTH
        
        if self.y < 0: self.y = 0
        elif self.y > HEIGHT: self.y = HEIGHT

Okay, we've got ourselves a decent start to a Blob. Let's go ahead and add the code for the environment, which the Blob will simply interact in:

import pygame
import random

WIDTH = 800
HEIGHT = 600
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)

game_display = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Blob World')
clock = pygame.time.Clock()

This is just some super basic starting code and constants. The colors are RGB tuples. If you would like to know more about PyGame, you can check out the PyGame tutorial series, but you can probably pick up all you need from this tutorial. You can also watch the video-version of this tutorial to get a bit more information for each line as we type it out.

Now we're going to have the beginnings of a function that handles the drawing of the environment:

def draw_environment():
    game_display.fill(WHITE)
    pygame.display.update()

In graphics processing, it's true that a lot of math and such might be involved, but, in general, the most likely-to-cause-a-hangup-process is actually updating pixel values on the screen. Thus, generally, the process for a simple game is something like: run game logic/calcs, "draw" the next frame in the background without actually showing it, updating individual parts, then, when full updated and ready, push it to the screen. In our case, we're just filling the screen with white, then using the .update method to push the latest frame to the screen.

Now for the main function and the if name statement:

def main():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        draw_environment()
        clock.tick(60)

if __name__ == '__main__':
    main()

In our case, this will run infinitely, unless we hit a pygame.QUIT event (user hits the "X" to close the window). For each loop in the while True, we check for a quit event, then draw the environment, and use the clock to control our FPS. In this case, we're setting FPS to 60. Just because we set it to 60, it doesn't mean it will actually run at 60 FPS, it just wont go any faster. PyGame runs on your CPU, and as you just learned, is going to default to running on a single core, so it's not the ideal starting environment. Converting PyGame to being a multiprocessing engine is quite a challenge, and we're not going to do that here, but we can make sure our actual game logic runs in a separate process or multiple processes to make sure PyGame at least gets a core all to itself.

At this point, we can run our code:

import pygame
import random

WIDTH = 800
HEIGHT = 600
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)

game_display = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Blob World')
clock = pygame.time.Clock()


class Blob:
    
    def __init__(self, color):
        self.x = random.randrange(0, WIDTH)
        self.y = random.randrange(0, HEIGHT)
        self.size = random.randrange(4,8)
        self.color = color

    def move(self):
        self.move_x = random.randrange(-1,2)
        self.move_y = random.randrange(-1,2)
        self.x += self.move_x
        self.y += self.move_y
        
        if self.x < 0: self.x = 0
        elif self.x > WIDTH: self.x = WIDTH
        
        if self.y < 0: self.y = 0
        elif self.y > HEIGHT: self.y = HEIGHT


def draw_environment():
    game_display.fill(WHITE)
    pygame.display.update()
    
def main():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        draw_environment()
        clock.tick(60)

if __name__ == '__main__':
    main()

All we get, however, is just the white environment. We want our blob to be here too! Let's create a Blob object, and then add it to our environment:

To start, we need to actually create a Blob object, all we've done so far is just create the class. We can do this in the main function:

def main():
    red_blob = Blob(RED)
    ...

In this case, we're specifying the one argument that the Blob class wants (color, as described in the __init__ method) as RED, so the color attribute of the Blob will be the red. Now let's pass the blob object when we call the draw_environment function:

        draw_environment(red_blob)

and:

def draw_environment(blob):
    game_display.fill(WHITE)
    pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size)
    pygame.display.update()

The game_display.fill(WHITE) will fill the entire screen with white, then we draw the blob as a circle, then we update the display. Notice how we can reference things like blob.color and blob.size, we're able to do that through our use of the self in defining the class methods.

If we run this, we get a blob on the screen:

intermediate Python tutorials

Now what if we want this blob to dance? We just need to call blob.move() in the draw_environment function, pretty much anywhere, but we'll just add it to the end:

def draw_environment(blob):
    game_display.fill(WHITE)
    pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size)
    pygame.display.update()
    blob.move()

Full code up to this point:

import pygame
import random

WIDTH = 800
HEIGHT = 600
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)

game_display = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Blob World')
clock = pygame.time.Clock()


class Blob:
    
    def __init__(self, color):
        self.x = random.randrange(0, WIDTH)
        self.y = random.randrange(0, HEIGHT)
        self.size = random.randrange(4,8)
        self.color = color

    def move(self):
        self.move_x = random.randrange(-1,2)
        self.move_y = random.randrange(-1,2)
        self.x += self.move_x
        self.y += self.move_y
        
        if self.x < 0: self.x = 0
        elif self.x > WIDTH: self.x = WIDTH
        
        if self.y < 0: self.y = 0
        elif self.y > HEIGHT: self.y = HEIGHT


def draw_environment(blob):
    game_display.fill(WHITE)
    pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size)
    pygame.display.update()
    blob.move()
    
def main():
    red_blob = Blob(RED)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        draw_environment(red_blob)
        clock.tick(60)

if __name__ == '__main__':
    main()

Now, if you run it, you should get a nice wiggling blob!

The next tutorial:





  • Intermediate Python Programming introduction
  • String Concatenation and Formatting Intermediate Python Tutorial part 2
  • Argparse for CLI Intermediate Python Tutorial part 3
  • List comprehension and generator expressions Intermediate Python Tutorial part 4
  • More on list comprehension and generators Intermediate Python Tutorial part 5
  • Timeit Module Intermediate Python Tutorial part 6
  • Enumerate Intermediate Python Tutorial part 7
  • Python's Zip function
  • More on Generators with Python
  • Multiprocessing with Python intro
  • Getting Values from Multiprocessing Processes
  • Multiprocessing Spider Example
  • Introduction to Object Oriented Programming
  • Creating Environment for our Object with PyGame
  • Many Blobs - Object Oriented Programming
  • Blob Class and Modularity - Object Oriented Programming
  • Inheritance - Object Oriented Programming
  • Decorators in Python Tutorial
  • Operator Overloading Python Tutorial
  • Detecting Collisions in our Game Python Tutorial
  • Special Methods, OOP, and Iteration Python Tutorial
  • Logging Python Tutorial
  • Headless Error Handling Python Tutorial
  • __str__ and __repr_ in Python 3
  • Args and Kwargs
  • Asyncio Basics - Asynchronous programming with coroutines