Translations of this page:

Step 005 - Frame-based Movement

screenshot screenshot
simple version pretty version

Code Discussion

Frame-based Movement

In this code example, the ball surface seems to move around. Keep in mind that the ball surface is not moving at all, it is just blitted to another position each frame (each cycle of the main loop). This movement is a frame-based movement and will depend on the actual frame-rate that your computer manages to display. Thus, the same pygame program will run slower on old or busy computers than on fast machines.

Manipulate the size of the pygame window (screen) or the workload of your computer (by moving big applications around) and you should notice that the ball needs a different amount of time to cross the screen.

Vectors

The new variables dx and dy are variables to control the speed of the ball surface (in pixels per second). You could call (dx, dy) a speed vector. Because integer values would mean a minimum visible movement of one pixel per frame, dx and dy are decimal values (float). In the mainloop, the current movement is added to the current position (resulting in a float value). Because pygame is (yet) unable to blit at the position of a half-pixel, the position is rounded to integer values just for blitting.

#calculate new center of ball 
ballx += dx
#bally += dy # y movement deactivated
# paint the ball    
screen.blit(ball, (round(ballx,0), round(bally,0)))    

Line too long

The pygame.display.set_caption line is too long to fit comfortably in this wiki. Here is the code line in its natural length:

    pygame.display.set_caption("FPS: %.2f X: %.2f Y: %.2f dx: %.2f dy:%.2f" % (clock.get_fps(), ballx, bally, dx, dy))

In Python, you can split a code line into several lines if:

  • you split between opening ( and closing ) brackets
  • you have two strings enclosed in -signs where the second string directly follows the first string. Python will interpred those two strings as one large string. See the source code example below.
  • a line ends with space and backslash \ see this example:
result = 5 + 7 + \
+ 10
print result # result is 5+7+10=22

Bouncing off Walls

If the ball (surface) hits the edge of the screen, the speed vector component dx or dy are inverted by multiplying with -1 to make sure that the ball surface position ballx or bally stay inside of the screen.

    # bounce ball if out of screen
    if ballx < 0:
        ballx = 0
        dx *= -1 

Drawing on the Screen

You can draw on any pygame surface, even directly on the screen. While all changed surfaces need to be blitted again on the screen to make their changes visible, the screen surface is updated with the pygame.display.flip() command each frame (main loop cycle). Because the whole background is blitted on top of the screen (practically cleaning the screen) each frame, you are free to experiment with moving pictures.

Note that the random module has to be imported at the start of the program.

import random # after importing pygame

The next code-lines draw an glittering, pulsating circle. add this code inside the mainloop:

    # ----- pulsating circle -----------
    colour = (random.randint(0,255),random.randint(0,255),random.randint(0,255))
    if radius > 100 or radius < 5:
        dr *= -1
    radius += dr
    pygame.draw.circle(screen, colour , (100,100), radius, 2) # draw pulsating circle
    # -------- end of pulsating circle -------

Documentation

Source Code on Github

To run this example you need:

file in folder download comment
005_frame_based_movement.py pygame Download the whole Archive with all files from Github:
https://github.com/horstjens/ThePythonGameBook/archives/master
simple version
005_frame_based_movement_pretty.py pygame pretty version

Simple Version

View/Edit/Download the file directly in Github: https://github.com/horstjens/ThePythonGameBook/blob/master/pygame/005_frame_based_movement.py

If using Python 3, be sure to replace the division operators in the following line:

pygame.draw.circle(background, (0,0,200), (screenrect.width/2, screenrect.height/2), screenrect.width/3)

with the ”//” operator to truncate the quotients and return integers, rather than floating point numbers. And remember that print is now a function.

click reload in your browser if you see no code here:

Pretty Version

(by yipyip)

Note that this version move more objects than the simple version. View/Edit/Download the file directly in Github:

click reload in your browser if you see no code here:

Comment this Ptage


en/pygame/step005.txt · Last modified: 2014/01/09 11:07 (external edit)