PyGame : Tutorial PT2 (Drawing objects to the screen)

So its that time of the week … I apologise if the tutorials are slow in being published as I’m working on a few other projects in my spare time and want these tutorials to be correctly written so I don’t get you in to any bad habits or poor coding situations … (I’ve been reading the documentation for pygame A LOT) so without further a do, here’s pygame tutorial part 2. (Click here for part 1)

In the last tutorial we covered setting up the basic game window and initialising pygame.

In this tutorial were going to be drawing some simple shapes and text to the screen and moving them around using the keyboard.

There are some minor modifications to last weeks code I will explain these as we go along.

normal = from original tutorial
bold = added or modified

import pygame
from pygame.locals import *

wWIDTH = 640 # game window width
wHEIGHT = 480 # game window height
loc = [0, 0] # location data

The above code is pretty much the same as last week apart from the loc[0,0] (loc[x,y]) variable this is going to be used to store the xy location of the player.
Here we set the variables both equal to zero. These numbers represent the players starting position so x=0 and y=0 would result in the player starting in the top left hand corner.

def main():

r = 1
while(1): # do for a while (game loop)

for event in pygame.event.get(): # handle events

if event.type == QUIT: # ctrl+c

r = 0 # return 0 = (game is over)

elif event.type == KEYDOWN: # down arrow

if event.key == K_ESCAPE:

r = 0 # return 0 = (game is over)

if event.key == K_q: # q key pressed

r = 0

if event.key == K_LEFT:

loc[0] = loc[0] – 1 # move left

if event.key == K_RIGHT:

loc[0] = loc[0] + 1 # move right

if event.key == K_UP:

loc[1] = loc[1] – 1 # move up

if event.key == K_DOWN:

loc[1] = loc[1] + 1 # move down

So whats changed above well again most of the code is exactly the same but this time were trapping keys to trigger more events. In the first tutorial we trapped the escape key to make the game exit. Here we are trapping the arrow keys to change the variables held in the (loc) location variable. If the key is pressed down then add or subtract to the loc[x,y] variable depending on which key is being pressed (UP, DOWN, LEFT or RIGHT).

We will use the loc variable later to draw the objects to the screen.

# keep location visible on the screen
# check loc is not out of bounds (screen/window size)

if loc[0] < 0:

loc[0] = wWIDTH

if loc[0] > wWIDTH:

loc[0] = 0

if loc[1] < 0:

loc[1] = wHEIGHT

if loc[1] > wHEIGHT:

loc[1] = 0

The above code checks that the numbers stored in the loc(x,y) variable are within the bounds of the screen. If the bounds are exceeded the code keeps them on the screen. So if the object goes off the left of the screen it will appear on the right and also if the object / player moves off the bottom they will appear at the top and vice versa. The loc positions are compared to the window bounds (the variables we defined at the top of the code. wWIDTH amd wHEIGHT)

#fill the screen with black
GSURF.fill((0, 0, 0))

#draw stuff here …
#circle(Surface, color, pos, radius, width=0) -> Rect
#rect(top,left,width,height)
pygame.draw.circle(GSURF, (0, 255, 0), (loc[0], loc[1]), 6, 2)
pygame.draw.circle(GSURF, (255, 0, 0), (loc[0], loc[1]), 4)

pygame.draw.rect(GSURF, (0, 0, 255), [loc[0]-10, loc[1]-10, 20, 20], 3)
pygame.draw.ellipse(GSURF, (0,255,0), [loc[0]-30, loc[1]-10, 60, 20], 1)
pygame.draw.arc(GSURF, (255,0,0), [loc[0]-40, loc[1]-40, 80, 80], 3.141, 2*3.141, 1)
pygame.draw.line(GSURF, (0,0,255), [loc[0]-50, loc[1]-50], [loc[0]+50, loc[1]+50] , 1)

Here’s the good stuff … first of all we fill the canvas / surface black. Its important to draw the background colour first, if we drew the bg colour last we would just end up with a black screen no matter what we’d drawn underneath / first.

pygame.draw.circle(GSURF, (0, 255, 0), (loc[0], loc[1]), 6, 2)
draws a green circle to the game surface at the location held in loc[x,y] make the radius 6 pixels and make the stroke / border 2 pixels wide
so this will not fill the circle

pygame.draw.circle(GSURF, (255, 0, 0), (loc[0], loc[1]), 4)
The above code is the same as the last snippet but will fill the circle in red (if the stroke isn’t provided the circle is filled.)

pygame.draw.rect(GSURF, (0, 0, 255), [loc[0]-10, loc[1]-10, 20, 20], 3)
Draws a red rectangle to the screen. Again the last parameter is optional if you omit this parameter the rectangle will be filled red.

pygame.draw.ellipse(GSURF, (0,255,0), [loc[0]-30, loc[1]-10, 60, 20], 1)
Draws an ellipse to the screen. Optional border parameter.

pygame.draw.arc(GSURF, (255,0,0), [loc[0]-40, loc[1]-40, 80, 80], 3.141, 2*3.141, 1)
Draws an arc to the screen. Last parameter represents line thickness.
NB. Arc start point and endpoints are measured in radiants.
These sound complicated but they are really easy.
Basically a circle contains 6.28 radiants. (2*pi).
A start point of 0 and endpoint of 3.141 would draw half a circle.
A start point of 0 and endpoint of 6.282 would draw a whole circle.
Degrees to radiants = 6.282 / 360 * Degrees

pygame.draw.line(GSURF, (0,0,255), [loc[0]-50, loc[1]-50], [loc[0]+50, loc[1]+50] , 1)
Draws a line from one point to another.

All the above shapes are drawn @ the location of the player.

myfont = pygame.font.SysFont(“monospace”, 15)
label = myfont.render(“Frame rate : ” + str(int(GCLOCK.get_fps())), 1, (255,255,0))
GSURF.blit(label, (loc[0], loc[1]))

# check the ‘pygame draw’ documentation for more information on other you can draw to the screen
# above are most of the basics.
pygame.display.flip() # update the screen
GCLOCK.tick() # update the clock

if r != 1:

break

return r

Above we define a font variable as myfont we use the default pygame fonts (which are all available in the documentation.) Next we make a label variable this variable is going to contain the frame rate as this variable isnt a string we have to use str() to convert the fps from a number to a string. (NB. I think I made a school boy error above. Fps is returned as an int, there is no need for the int() function u can remove this. Edit the code so it looks like this str(GCLOCK.get_fps()) ) Then we blit the label object to the screen at the specified location. display.flip() is used for double buffering (which is a whole other topic) ill cover it briefly here if we replaced the last frames image with the current one we were drawing in the loop bad things would happen basically double buffering displays the last drawn image until the next has been drawn and is ready to be displayed. Double buffering cuts out screen flicker.

tick() is then called to update the pygame clock and advance to the next frame. No numbers are passed in here. Before we were passing a number which will restrict or slow the pace of your game by a set amount depending on what number you use. This will also help us to determine accurately how many cycles the game is running at per second accurately.

if __name__ == “__main__”: # main function call

r = 1 # set variable for return value

pygame.init() # initialise python pygame

GCLOCK = pygame.time.Clock() # set game clock

GSURF = pygame.display.set_mode((wWIDTH, wHEIGHT)) # main game surface

pygame.key.set_repeat(1, 0) # repeat keys delay by 0

while r == 1: # quit on 0

r = main() # get return value from main loop (1 == OK … 0 == exit)

pygame.quit()

Here is the last bit of code (that initialises the whole game rather important) only one line changed here which is the keyboard repeat rate, this forces the keyboard to repeat key presses if they are held down for a specified period of time.

That concludes tutorial part two.

Here is a screen shot of what the code does …
Screenshot from 2013-07-09 01:58:41

Here is a link to the code …
GIST : https://gist.github.com/caffeinemonster/5953538
PASTE BIN : http://pastebin.com/sxchRZx7