Use an analog sensor as a video game controller

Bouncing Balls

Getting back to the __main__ function, on line 130 you draw the court for the first time and then initialize a ball object using the ball class (lines 10 to 34).

Within the __init__() function you set the starting point of the ball as the center of the screen on line 11 and define the ball itself, a PyGame object [4] on line 13.

On lines 14 and 15 you work out the ball's horizontal and vertical velocity (vx and vy). This is where knowing which side of the screen is shorter comes in handy. In this example the screen is higher than it's wide, so the vertical speed of the ball is faster than the horizontal speed.

The move() module (lines 17 to 20) is pretty self-explanatory. Each time the ball moves, you draw over the old image of the ball with the background color – in this case, black (line 18). Then you move the ball using the horizontal and vertical velocities (line 19), and redraw the ball in its new position (line 20).

The collision module (lines 22 to 27) is also self-explanatory. Look at lines 142 to 154. You'll see that, just after you move the ball, we check to see if the ball has collided with any part of the wall, any of the bricks, or the paddle. There is a very nifty PyGame module for this called collidelist() (line 23). Remember how you put all the blocks that make up the wall and all the blocks that make up the breakable bricks into lists? What you do in line 23 is ask the list if the ball has hit any of its elements. collidelist is also good enough to tell you which element you hit; you store this in the hit variable, so you can later work out which brick to delete from the screen… Presuming it was a brick you hit, of course.

Another thing that can happen when the ball hits an obstacle is that it bounces off (line 25). If it hits the top or bottom of a brick, the vertical velocity will change direction. Say its vy equals -1 (moving upwards). When it hits the bottom side of a brick it will change to +1 and start moving downwards. The problem is the collidelist just tells us if it has hit something, not where it's hit it. How then, do we figure out if the ball has hit a side, or top or bottom of an object? The good news is we can find out the horizontal and vertical center of any PyGame graphical object by looking at its centerx and centery attributes. Now look at Figure 6.

Figure 6: Calculating the horizontal distance between centers helps us figure out whether the ball hits a side or the bottom or the top of an object.

If the horizontal distance (line 30) between the centers of the ball and the object equals half the width of the ball + half the width of the other object (we can find out the width of an object by looking at its width attribute), that means the ball has hit a side (lines 31 and 32). Otherwise, the ball has hit the top or the bottom (lines 33 and 34). With that information, you can calculate which velocity you have to change.

Paddling Along

This is where your dial library comes into play… literally.

On line 135 you set up a paddle object within the __main__ module. Note that this is the last thing you do before you go into the game's main loop (lines 137 to 158). Remember this, as it will be important later.

The paddle class is defined from line 97 to 126. You initialize the object by creating a paddle attribute which is of type list (line 99). Why a list if there is only going to be one (1) paddle? This is because when you check what the ball is colliding with, you check against a list using PyGame's collidelist() (line 23). If we had the paddle as an individual object, then we would have to write a separate routine just for the paddle. That makes things too complicated! It's much easier to just make everything a list, have one module, ball.collision(), for everything, and be done with it.

Line 100 establishes the size of the paddle (relative to the size of the court and the bricks), makes a PyGame Rect object from it, then dumps it into the list you defined above.

On line 102 you set the horizontal limits for the court. You do this so the paddle doesn't go over the edge. On line 104 you set how much the paddle will move at each step when you twiddle the potentiometer.

Finally, you create a dial object on line 106! As you don't know at this stage what position the dial is in, you provisionally set it to zero (line 107) and move on to a calibration() module to figure it out (line 108).

The calibration() module (lines 112 to 114) is very simple – it is just a while loop that doesn't exit until the potentiometer is turned to its mid-point. Once that happens, you draw the paddle (line 110) and the main loop of the game, down in the __main__ function, starts (line 137).

When the program is run, it appears frozen to the player. You then twiddle the potentiometer looking for the mid-point. When you hit it, the paddle pops up and the ball starts moving.

The place() module in the paddle class (lines 116 to 123) calculates where the paddle is, based on the value read from the analog sensor on line 117. If the paddle has moved (line 119) you draw a black rectangle over the old paddle (line 120) to delete it, and call the draw() module from line 123 to re-draw the paddle in its new position.

Buy this article as PDF

Express-Checkout as PDF

Pages: 6

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content