Thursday, November 29, 2012

Improving the 2D game engine


My quick guide on how to implement 2D sprite animation in Python/Pygame seems to be getting a steady stream of hits. For this reason, I am currently working on improving the quality of the guide and expanding my explanations.

I am also working on improving the engine itself. First, I want to remove the hard-coded pixel dimensions for the sprite frames and simply have the dimensions instead computed.

Secondly, I want to improve the quality of the sprites being used.

Lastly, I want to add some extra features such as basic collision detection.

Because I am busy with work, family, and school, you can probably expect to see the upgraded guide sometime around the end of December or early January.

Tuesday, October 23, 2012

Python/Pygame: 2D sprite animation, JRPG style

This entry is now outdated. Please see the updated entry here

---

Here's a basic example of how to implement 2D animation using Python and Pygame (an SDL wrapper for Python). I am going to be using the following sprite sheet, which is a 2D version of Serge from the game Chrono Cross (created by the user poxy at the chaos-project.com forums).


Looking at the above sprite sheet, the upper-left image will be our base image (frame 1). We will not use column three at all because the animation looks better without it. So we will be cycling through images 1, 2, and 4 in each row.

As for the coding, we are going to create a class called Serge that extends the pygame.sprite.Sprite class. First I'll show you the whole code, then we'll go through it piece by piece.


Now, let's talk about what is actually happening in this code.

Here's a breakdown of the first 14 lines:
Line 3: Our class Serge will extend the pygame.sprite.Sprite class.
Line 4: The position parameter will be used so that we can indicate the sprite's position when we draw it to the screen.
Line 5: We load our sprite sheet and assign it to sheet.
Line 6: We use the set_clip() method in order to display only frame 1 of our sprite sheet.
Line 7: We assign our current image to the clipped area.
Line 8: Create a rect object to correspond to our image.
Line 9: Assign position so that it corresponds to the upper-left pixel of our rect.
Line 10: Assign our current frame to 0; this variable will be used later to cycle through the frames.
Lines 11-14: Create 4 dictionaries to store the pixel coordinates for our walking animation frames.

Lines 16-20:
In order to animate our character, we need to repeatedly cycle through three frames. In lines 16-20 we create a method to handle this.

Lines 22-27:
We create a method to clip the area of each frame. First we have to check whether we are dealing with multiple frames (movement) or a single frame (standing). If the character is moving, the frames are handled by the get_frame() method. If the character is simply standing, the frame is handled directly by Pygame's built-in functions.

Lines 29-52:
Next, update() relies on the previous two methods by passing them the dictionaries (in the case of movement) or single frames and moving the sprite in the correct direction using the built-in pygame.sprite.Sprite rect.x and rect.y values. Then it sets the current image to the appropriate clipped area.

Lines 54-78:
Lastly, we create the method handle_event() to handle keypresses. Depending on what key is pressed, we pass a state (in this case a string) to the update() method which carries out all work described above. update() animates the character and moves him across the screen based on what key is pressed.

We can save this as serge.py. With all that out of the way, our main.py file is very simple.


In line 8 we create an instance of our Serge class called 'player', and position its upper-left pixel at the x-y coordinates (150, 150). We then create a simple main loop, call our event handler (line 19), make a blue background (line 20), and draw 'player' on the screen (line 21). In order to control the animation and movement speed, we set the clock.tick() value to 10.

Output:


If you run from source, the animation will be smoother. With some very basic tweaking and more advanced sprite sheets, you can greatly improve the quality of the animation by adding more frames, and using the code above you could easily add a running option.

Hopefully this gives you a general idea of how to implement sprite animation in Python and Pygame.

Sunday, October 7, 2012

Quick Guide: Deploying your first Django app to the cloud in about 10 commands

(This guide works with Windows, Mac, and Linux, but you will have to be comfortable with the command line.)

1) https://openshift.redhat.com/app/ << Create a free OpenShift account. When prompted, don't create your first OpenShift app at this time, however.

2) https://openshift.redhat.com/community/get-started << Install all required tools for using OpenShift if you don't already have them. (Skip sections 3-5 on the page that deal with creating/configuring your first app. You'll do that below.) In Ubuntu, for example, you'll need to do the following to install the client tools:

$ sudo apt-get install ruby rubygems git
$ sudo gem install rhc
$ rhc setup

3) https://github.com/openshift/django-example << Follow the instructions on this page. Specifically:

$ rhc app create -a django -t python-2.6
$ cd django
$ git remote add upstream -m master git://github.com/openshift/django-example.git
$ git pull -s recursive -X theirs upstream master
$ git push

4) There is no step four. Following these steps exactly, you've just built and deployed your first Django app in about 10 commands. You can begin customizing the Django example in /django/ and, when you're ready, simply:

$ git commit -am "Comments about your changes"
$ git push

Maybe all this 'cloud' stuff isn't so gimmicky after all. And if Google search trends are anything to go by, learning the Django framework is probably a sensible allocation of your time.