Transcript 3 - Arinoid - The Paddle
Hello and welcome to scriptedfun.com screencast number 3. Today, we will continue building our game Arinoid by adding a paddle. We will use the paddle to deflect the ball, and we want to be able to control it using the mouse.

The paddle image is contained in our sprite sheet. However, the image spans two tiles, which means that we cannot just extract the paddle image from the sprite sheet and use it as is. We have to get rid of the boundary at the middle. We can do this by extracting the left and right halfs of the paddle image, and joining them together. We will do these things without resorting to manual image editing. Since we want to be able to use the sprite sheet without manually editing it, we will do all the image manipulations within our program.

The first thing that we have to do is get the numbers needed to extract the left half of the paddle. We will pass these numbers to spritesheet.imgat, which will extract the image for us.

We also have to get the numbers for the right side of the paddle.
paddle = pygame.Surface((55, 11)).convert()
# left half
paddle.blit(spritesheet.imgat((261, 143, 27, 11)), (0, 0))
# right half
paddle.blit(spritesheet.imgat((289, 143, 28, 11)), (27, 0))
paddle.set_colorkey(paddle.get_at((0, 0)), RLEACCEL)
return paddle
Let us write a function that will produce the paddle image. The first step is to define a surface on which we will have the finished product, the paddle. Our surface is 11 pixels in height, corresponding to the height of each of the half-paddles. Since the width in pixels of the left half of the paddle is 27 while the width in pixels of the right half is 28, we just have to add these numbers to get 55, the width of the entire paddle, and use this number as the width of the surface.
Then, we use spritesheet.imgat to extract the image of the left half of the paddle, then we blit the left half to the left side of our new surface.
Then, we do the same thing with the right half of the paddle, blitting the image to the right side of the surface. We do this by placing the left edge of the half-paddle image at x = 27. This ensures that both paddle images are seamlessly connected.
Then, we want to set a colorkey for our image, so that it will blend seamlessly with the background, instead of looking rectangular.
When setting the colorkey, we have to make one of the pixel colors transparent. Since the upper left corner pixel of the sprite surface is not actually part of the actual paddle, but a part of the background, we took its color, and set pixels of this color as transparent. Again, we use the flag RLEACCEL to make using the surface fast.
Finally, we return the paddle image, making it ready for use. And that’s it - we have a paddle graphic that we can use!
In pygame, game elements are usually defined by deriving from the pygame Sprite class. Let us define a Paddle class which we will use later on to make our paddle appear on the screen and make it move using the mouse. The __init__ method that we have defined here will be called every time a new Paddle instance is made.
To attach the paddle image that we have made earlier to our Paddle class, we set the image attribute of our Paddle class to our paddle image.
Also, we have to make our paddle aware of its surroundings, the world it is in. In order for the Paddle class to access the world it is in, which is actually contained in the variable arena, we can define the attribute arena for our Paddle class and set it to our arena variable.
In screencast number 1, we defined the variable all, which is a pygame RenderUpdates group, whose contents will be displayed on the screen. Since we want to make our paddle appear on the screen, we have to place instances of the Paddle class inside the RenderUpdates group all. We can accomplish this in two steps. First, let us define the attribute containers, which states the group or groups which we want instances of our class to belong to, and make this contain the RenderUpdates group all.
def __init__(self):
pygame.sprite.Sprite.__init__(self, self.containers)
self.rect = self.image.get_rect()
self.rect.bottom = self.arena.rect.bottom - self.arena.tileside
def update(self):
self.rect.centerx = pygame.mouse.get_pos()[0]
self.rect.clamp_ip(self.arena.rect)
Whenever we derive from the pygame Sprite class, we have to call its __init__ method. We can pass the containers attribute to the __init__ method of the pygame Sprite class to make sprite instances belong to the groups contained in the attribute containers. Since we let the containers attribute of the Paddle class contain the RenderUpdates group all, this command will place instances of the Paddle sprite in the RenderUpdates group all. Since we have already laid down the game loop code in screencast number 1, simply placing instances of sprites in the group all will make them appear on the screen. So our paddle will appear on the screen!
To display pygame Sprite instances on the screen using pygame render groups, our Sprite instances should have two attributes - the image attribute and the rect attribute. The image attribute, which we have already taken care of when we attached the paddle graphic to the Paddle class, is the actual image which our pygame render group will put on the screen. The rect will determine where the image will be on the screen. To make the rect for our paddle, we just have to call the get_rect() method of our paddle surface.
Next, we have to determine where to place the paddle on the screen. Definitely, we want it to be at the bottom area of our playing field. To do this, we can set the y-coordinate of the bottom edge of our paddle to correspond to the top edge of the last row of tiles in the playing field. We do this by taking the y-coordinate of the bottom edge of the playing field, subtracting the length of one tile edge from it, and making the resulting value the y-coordinate of the bottom edge of the paddle image.
At this point, we can define the update method of our sprite. This method is called every time the update function of the group it belongs to is called. In general, this is the rendering group which contains all the sprites, such as the group named all in our code. Since we call the update method of the group all during every iteration of our game loop, we should expect this update function to be called once per frame.
For our paddle, we want it to follow the x-coordinate of the mouse to allow it to move along the bottom area of our playing field. To do this, we may set the x-coordinate of its center to correspond to the x-coordinate of the mouse pointer, which is obtained by taking the first element, which is indexed 0 as shown in the code, of the ordered pair corresponding to the position of the mouse, which is obtained by calling pygame.mouse.get_pos().
We are free to move the mouse pointer anywhere in the entire screen, even outside the playing field or even outside the game window. Of course, we do not want to see the paddle go out of the playing field even when the x-coordinate of the mouse pointer goes out of bounds. To restrict the paddle inside the playing field, we can use the built-in clamping functions of pygame. This particular piece of code restricts the rect of the paddle inside the rect of the playing field, ensuring that the paddle doesn’t go outside the playing field.
Finally, we can go inside our main function again and make an instance of our paddle, which makes it present on the screen and in our game. We store our Paddle instance inside a variable so that we can easily access it later on.
And we are done! Finally, we have put a sprite on the screen, and we actually have something that we can interact with. Adding other game elements, which are usually represented as sprites, should be easier for us later on, since the procedure should be more or less similar to the one we did here.
I would love to hear from you! I really encourage you to leave a comment on the site. For the next screencast, we will be adding the ball to the game, together with some basic physics. Thank you so much and I hope to see you again for the next screencast!
License
This work is published under a Creative Commons Attribution 2.5 License.


February 8th, 2007 at 7:04 am
I am a fan of game design, and C and C++. I have to well, good job out it that way.