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:
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!