Over the past couple of months, we have been browsing through python and pygame creating a small game to play. At the end of tutorial two we ended up with a "character" we can move around the screen, but that is never the full story. Before we move on to the all important conflict of our game, we are going to need something....a sprite class.
It is true that pygame has its own little sprite class, but it really doesn't fill all our needs. Most basically, it does not really provide a simple positioning system or a sprite image, at least not in a strait forward manner. This is why we are going to create one in our tutorial today.
Today we will not be working with our previous code, but rather we will create and test a sprite class we can implement later on. This is actually a fairly simple process, with the implementation part being the more difficult. It can be, however, a bit tedious, so let's get started.
Like always, let's top the file with some imports, or in this case, a single import:
Pygame is all we are going to need here. Now, Python classes are fairly simple things. As with any class in most languages, however, it all starts with the class keyword:
That's it, that's all the declaration we need. But, we need to fill the class now, and like any good programmer, we start with a constructor. In python classes we use the __init__ method for the constructor, which goes inside our class definition of course:
def __init__(self, image, x, maxX, y, maxY):
self.x = x
self.y = y
self.image = image
self.rectangle = pygame.Rect(
x, y, image.get_width(), image.get_height())
self.maxX = maxX - image.get_width()
self.maxY = maxY - image.get_height()
So what we have here is a really basic constructor. All it does is set a bunch of variables, but they are variables that are pretty important. First we have the sprite image and position. Next we have a rectangle object, which we set up for use in collision detection. We will talk about this rectangle a little later on. Finally we set up some boundary variables, which are used in determining where the sprite can go. In this case we have to take into account the sprite's size because the position origin is found at the top left corner.
So, you may have also noticed that we are passing in a self object. All class methods in python MUST pass in a self reference. This allows us to access all of the variables and methods of our class inside that method. In the case of our constructor, we need it to set up all our new class variables, which is accomplished simply by using self.variable = something. There is no type declaration or even access keyword needed.
In python there is no concept of access built in. You cannot make things private or public, they simply are accessible all the time, everywhere. It is just a fact we have to deal with. But we can keep some of the OOP principals by using the self object variables instead of external ones.
So, keeping in the spirit of object-orientation here, we need to create a set of manipulator methods for the position of the sprite. Here is what I came up with:
return (self.x, self.y)
def AddX(self, x):
self.x = self.x + x
def SubX(self, x):
self.x = self.x - x
def AddY(self, y):
self.y = self.y + y
def SubY(self, y):
self.y = self.y - y
These methods allow us to modify the position of the sprite, as well as get the position. These methods are technically not needed, but it makes things a little easier. Also, we can add other things to these methods if we want, you never know what we might want to do to the position.
What we have to do now is create an Update method, which will take care of everything that we would do in the course of drawing the sprite. Let me just show you the method first:
if self.x < 0:
self.x = self.maxX
if self.x > self.maxX:
self.x = 0
if self.y < 0:
self.y = self.maxY
if self.y > self.maxY:
self.y = 0
self.rectangle.move_ip(self.x, self.y)
if scr != None:
scr.blit(self.image, self.GetPosition())
So the first thing we are doing here is checking the position, making sure it is within the bounds we set. If it is not, we set it back to something valid. I have set this bounds check up to scroll to the other side of the screen if it goes off the other side. This is just a little something fun, which can be fixed with a second of tweaking.
After we have a valid position worked out, we move the sprite rectangle to the new position. Finally, if a screen object is passed in, we go ahead and draw the sprite. It makes life a lot easier.
So, now we have a nice little sprite class of our own, but what to do with it? Well, just testing our new class requires a pretty good amount of code, so I am going to just give you a small summary, and leave the rest of the code in the included file:
transColor = spriteCanImg.get_at((1,1))
spriteCanImg.set_colorkey(transColor)
spriteCanImg.convert()
#Inside the game loop
sprite.AddX(10)
sprite.AddY(10)
sprite.Update(screen)
As you can see, all we have to do is call a few methods and we can manipulate our sprite effectively. Since all the variables can also be directly accessed we can change the image as we want or mess around with the position without using the manipulator methods. But the one thing you will notice is that we create an image object outside of the sprite object. This is done for a very good reason.
In python, when you pass objects around, the default action is to pass a reference. This means that we can have 100 sprite objects that all use the same image object. This saves a lot of resources. We could add an image object to the sprite class, but it is much more efficient in the end to create images outside of the sprite object and pass the reference to it.
So this is our sprite object. The only real thing missing is collision detection, which we will be going over in the next tutorial. For now you have a pretty good start. I hope you enjoyed the tutorial and learned from it. Just remember, when you need coding help, all you have to do is Switch On The Code!
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.