Pygame easy as Py

Started by
12 comments, last by daviangel 16 years, 11 months ago
OK I'm thinking of starting my own Python/Pygame tutorial in this thread in part to help myself and others who are currently working with Python/Pygame. This came about due to the fact that I finally found a language/graphics API I can make 2D games in a reasonable amount of time and I hope to show that here. Also, it's an attempt to weed out the bugs in my personal pygame engine I dubbed gameEngine and you can see the bug here in this thread. So I'm gonna start all over from scratch without using my custom gameEngine and build up my Pirates clone in python/pgame. That was my main motivation was for learning to program in the first place to make a 2D pirates clone that I could customize to my taste. Also, by posting my progress here I will be able to keep track of how long it takes me since I will be adding little by little as I can find the time to do so. Anyways, lets get started and if anyone wants to add anything feel free to! First you need to have Python and pygame installed for your platform. I'm using Python 2.5.1 and pygame 1.7.1. I don't know if there is a 64bit version of pygame or how hard it would be to compile it from source so all this is on 32bit WinXP but if anyone knows about 64bit pygame support let me know. Now that we have Python and pygame installed the first thing you should do is make sure they are installed and working so do this: 1. Get into Python by using the command line or IDLE to get to the Python interactive shell. 2. Use the following command to import pygame into Python import pygame If pygame is installed correctly nothing will happen. If you get an error message on the other hand you pygame is not installed correctly and you'll need to fix it before you do anything else Pygame helps you easily create game in Python by providing the following: Display- a graphical display Surface- a rectangular area that contains an image Rect- used to determine size of objects and to detect whether 2 objects collide Input modules- lets the user interact with pygame using a mouse,keyboard or joystick Output modules- provides ways to send information back to the user includes audio output for background music and sound effects Utility modules- more modules to help make game programming easier like transformation functions that let you scale and rotate images, manage fonts, working with time I will use the IDEA/ALTER(dibbs to Andy Harris for this) acronoyms as a simple way to remeber all the details that go into getting a game started. Here's what it stands for: I-Import and Initialize D-Display E-Entitites A-Action A-Assign values L-Loop T-Time E-Events R-Refresh screen It's alot to remeber but onece you understand this basic framework you can use it for every game you write. Now I'm gonna break down the above even more so it makes more sense: I-Import and Initialize 1.Be sure pygame is installed on machine 2.Tell Python you gonna use pygame library import pygame 3.Initialize pygame pyame.init() D-Display 1.Create variable to represent the display screen 2.Call pygame.display.set_mode() function 3.Determine the size or resolution of screen 4.Specify any other parameters 5.Set up screen caption with display.set_caption() E-Entitites(things moving about on screen) 1.Create a variable called background to hold the background 2.Use pygame.Surface() to build a Surface object background = pygame.Surface(screen.get_size()) 3.Make the background the same size as the display 4.Convert the background to standard color format using convert() 5.Copy the converted image back to the background background = background.convert() 6.Change the color of the background background.fill((0,0,255)) # note using R,G,B values here A-Action(includes main or game loop) A-Alter Assign values to key variables 1.Create clock variable clock.pygame.time.Clock() 2.Create Boolean to manage game loop keepGoing = True L-Loop 1.Any time you want to end game set keepGoing to False while keepGoing: T-Time 1.Use tick() method to set maximum frame rate 30fps in our case clock.tick(30) E-Events 1.Get list of events that happened during this frame pygame.event.get() 2.Step through each element in the event list for event in pygame.event.get(): 3.Check the event type for now we are just looking for QUIT if event.type == pygame.QUIT: 4.Write some code for the event keepGoing = False R-Refresh screen Finally we get to see our hard work displayed to the screen in this step! To display the screen: 1.Copy the background image to screen using the screen.blit() method screen.blit(background,(0,0)) 2.Copy any foreground images to the screen using screen.blit() This means the first thing you draw will be on the bottom and successive images will appear on top 3.Flip the display - copies screen buffer to display hardware pygame.display.flip() The code for our first pygame program follows:

""" idea.py
    Simplest possible pygame display
    Demonstrates IDEA/ALTER model
    Note: Don't try to run any pygame stuff
    within IDLE will lockup!
    Jaime Moreno
    4/2/07
    """

#I - Import and initialize
import pygame
pygame.init()

#D - Display configuration
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption("Hello, world!")

#E - Entities (just background for now)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((100,60,25))

#A - Action (broken into ALTER steps)

  #A - Assign values to key variables
clock = pygame.time.Clock()
keepGoing = True

  #L - Set up main loop
while keepGoing:
    #T - Timer to set frame rate
    clock.tick(30)

    #E - Event handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keepGoing = False

    #R - Refresh display
    screen.blit(background, (0,0))
    pygame.display.flip()

# end main game loop





Copy the above sourcecode into a file and save it. I saved mine as idea.py as you can see in the comments. Now run it by either double-clicking on the file and if everything is setup correctly it will automatically run. If not go to your commandline and I assume Python is in your path and just type: python idea.py You should end up with something like the following image Image Hosted by ImageShack.us You can modify the following line to change the backround color background.fill((0,0,255))-will give you a blue background for example,etc : [Edited by - daviangel on July 19, 2007 8:58:20 PM]
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Advertisement
Excellent, just so im clear this is a tutorial for 2D game with python right?
EPIQ Games, Coming Soon..
Quote:Original post by Epiq
Excellent, just so im clear this is a tutorial for 2D game with python right?

Yup, I'm keeping is as simple as possible so no 3D only 2D.
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok now I'm going to show you how to display a jpg,bmp or any other supported format image file in pygame.
As you can see it's only like one or 2 new lines of code to our original code.
I wrapped the original idea program in a main function too. If you've done any amount of Python programming you should already know that you should put everything in a main function and put
if __name__ == "__main__":
main()
at the end of your code so it doesn't automatically run if it's imported as a module in some other Python code.
Otherwise it's just a matter of using pygame.image.load() function to load your desired image like so:
image = pygame.image.load("openingScreen.bmp") # use whatever image you have and make sure it's in the same directory or program will crash since no error checking done at all to keep code simple.
Also remeber to use convert() right after you load an image or will suffer a perfomance hit. Only time you would not use convert() is if you are making a paint or image processing program which we are not!
Finally, remember to blit the image on top of the background:
screen.blit(image, (0,0))
""" image.py    Illustrates drawing an imported image    Simplest possible pygame display    Demonstrates IDEA/ALTER model    Note: Don't try to run any pygame stuff    within IDLE will lockup!    Jaime Moreno    4/2/07    """#I - Import and initialize still in global scopeimport pygamepygame.init()def main():    #D - Display configuration    screen = pygame.display.set_mode((640,480))    pygame.display.set_caption("Display an image")    #E - Entities (just background for now)    background = pygame.Surface(screen.get_size())    background = background.convert() # don't use for image editors    background.fill((255,255,0))    # note lack of error checking if image not there program will crash!    image = pygame.image.load("openingScreen.bmp")    image = image.convert()    #A - Action (broken into ALTER steps)    #A - Assign values to key variables    clock = pygame.time.Clock()    keepGoing = True    #L - Set up main loop    while keepGoing:    #T - Timer to set frame rate        clock.tick(30)    #E - Event handling        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False        #R - Refresh display        screen.blit(background, (0,0))        #screen.blit(image, (250, 150))        screen.blit(image, (0,0))                pygame.display.flip()# end main game loop# Run main if this is the primary program# Note use of 2 underscoresif __name__ == "__main__":    main()  # call main function here

You should get your image displayed on the screen if everything goes right like this:


p.s. Once you got this program up and running try using screen.blit(image, (250, 150)) instead of screen.blit(image, (0,0)) and try to figure out what's happening. Hint:I gave the answer in my first post.
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok static images are lots of fun but moving stuff ie animation is even more so today I'm going to show you how to add animation to our simplistic IDEA/ALTER pygame framework.
All you need to do is add a few things like:
1. Build the object that will move usually outside the game loop in the entities otherwise your performance will suffer since you will be creating your object every frame ie 30 times a second!
2. Modify object data. That is create variables to hold your object's x and y values and then change them
3. Check for boundaries
Any time you move something you should see if it moved off the screen and if it do something about it. In this example we will use what they call Wrapping.
4. Refresh the screen.
Inside your game loop draw your object to the new position once it's updated

This is the source for today's example:
[source lang ="python"]""" moveBox.py    Illustrates basic motion using pygame    Uses IDEA/ALTER model    Note: Don't try to run any pygame stuff    within IDLE will lockup!    Jaime Moreno    4/2/07    """#I - Import and initializeimport pygamepygame.init()#D - Display configurationscreen = pygame.display.set_mode((640,480))pygame.display.set_caption("move a box!")#E - Entities (just background for now)# yellow backgroundbackground = pygame.Surface(screen.get_size())background = background.convert()background.fill((255,255,0))# make a red 25x25 boxbox = pygame.Surface((25,25))box = box.convert()box.fill((255,0,0)) # red box# set up some box variablesbox_x = 0box_y = 200#A - Action (broken into ALTER steps)  #A - Assign values to key variablesclock = pygame.time.Clock()keepGoing = True  #L - Set up main loopwhile keepGoing:    #T - Timer to set frame rate    clock.tick(30)    #E - Event handling    for event in pygame.event.get():        if event.type == pygame.QUIT:            keepGoing = False                #modify box value    box_x += 5    #check boundaries    if box_x > screen.get_width():          box_x = 0              #R - Refresh display    screen.blit(background, (0,0))    screen.blit(box,(box_x,box_y))    pygame.display.flip()# end main game loop

The code should be self explanatory from the comments. The only thing that might throw you for aloop is that computers don't use the standard Cartesian coordinate system you used in math so y is not postive going up and the origin(0,0) is not the center of your computer screen!
The origin is at the upper left of your screen
x increases as you move from left to right
the largest value for x is screen.get_width()
y increases downward!
the largest value for y is screen.get_height()

You should get something like the following picture except you can't see the box moving of course
Image Hosted by ImageShack.us
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok I was having 2nd thoughts about even posting this code since I really don't plan on using pygames drawing commands much in my game and don't care for them but I'm going to show them just in case someone needs them:
""" drawDemo.py    Illustrates pygame's drawing functions    Simplest possible pygame display    Demonstrates IDEA/ALTER model    Note: Don't try to run any pygame stuff    within IDLE will lockup!    Jaime Moreno    4/2/07    """#I - Import and initialize still in global scopeimport pygame, math # note we added math to get access for math.pi which we use in drawing arcpygame.init()def drawStuff(background):    """ given a surface, draws a bunch of things on it """    # draw a line from (5,100) to (100,100)    pygame.draw.line(background, (255,0,0), (5,100), (100,100))    # draw an unfilled square    pygame.draw.rect(background, (0,255,0), ((200,5), (100,100)),3)    # draw a filled circle    pygame.draw.circle(background, (0,0,255), (400,50), 45)    # draw an arc    pygame.draw.arc(background, (0,0,0), ((5,150), (100,100)),0, math.pi/2, 5)    # draw an ellipse    pygame.draw.ellipse(background, (0xCC, 0xCC, 0x00), ((150,150), (150,100)),0)    # note use of hex color codes in line above if you are into hex instead of RGB values    # draw lines    points = (        (370,160),        (370,237),        (372,193),        (411,194),        (412,237),        (412,160),        (412,237),        (432,227),        (436,196),        (433,230)        )    pygame.draw.lines(background, (0xFF, 0x00, 0x00), False, points, 3)    # draw polygon    points = (        (137,372),        (232,319),        (383,335),        (442,389),        (347,432),        (259,379),        (220,439),        (132,392)        )    pygame.draw.polygon(background, (0x33,0xff,0x33), points)    # compare normal and anti-aliased diagonal lines    pygame.draw.line(background, (0,0,0), (480,425), (550,325),1)    pygame.draw.aaline(background, (0,0,0), (500,425), (570,325), 1)        def main():    #D - Display configuration    screen = pygame.display.set_mode((640,480))    pygame.display.set_caption("Drawing commands")    #E - Entities (just background for now)    background = pygame.Surface(screen.get_size())    background = background.convert() # don't use for image editors    background.fill((255,255,255))    drawStuff(background)    #A - Action (broken into ALTER steps)    #A - Assign values to key variables    clock = pygame.time.Clock()    keepGoing = True    #L - Set up main loop    while keepGoing:    #T - Timer to set frame rate        clock.tick(30)    #E - Event handling        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False            elif event.type == pygame.MOUSEBUTTONUP:                print pygame.mouse.get_pos() # useful for debugging        #R - Refresh display        screen.blit(background, (0,0))        pygame.display.flip()# end main game loop# Run main if this is the primary program# Note use of 2 underscoresif __name__ == "__main__":    main()  # call main function here

As you can see you probably will need graph paper or some other method to use alot of these commands and even at that I feel it's too much work using 10 or more lines just to specify the points you are going to draw. Actually, if you end up doing any VB/C# system.drawing stuff it's pretty similar and alot more work.
The only thing I really found intersting in the above code is how you can check the mouse position for debugging purposes in the same loop we are checking for a quit command.
If you really want to know more about pygame's available drawing command and how they work just type help("pygame.draw") in a python idle to see what's available.
Oh and here's my screenshot:
Free Image Hosting at www.ImageShack.us
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok since I started getting into getting input from the user in the last post I'm going to post a more thorough example on reading the keyboard and mouse:
""" basicEvents.py    Demonstrates essential mouse    and keyboard events    Only reads one keypress at a time so     key combinations like ctrl+key won't work    Simplest possible pygame display    Demonstrates IDEA/ALTER model    Note: Don't try to run any pygame stuff    within IDLE will lockup!    Jaime Moreno    4/4/07    """#I - Import and initialize still in global scopeimport pygamepygame.init()def main():    #D - Display configuration    screen = pygame.display.set_mode((640,480))    pygame.display.set_caption("Press mouse and keys - look for output in console")    #E - Entities (just background for now)    background = pygame.Surface(screen.get_size())    background = background.convert() # don't use for image editors    background.fill(pygame.color.Color("yellow"))    #A - Action (broken into ALTER steps)    #A - Assign values to key variables    clock = pygame.time.Clock()    keepGoing = True    #L - Set up main loop    while keepGoing:    #T - Timer to set frame rate        clock.tick(30)    #E - Event handling        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False            elif event.type == pygame.KEYDOWN:                keyName = pygame.key.name(event.key)                print "key pressed:", keyName                if event.key == pygame.K_ESCAPE:                    keepGoing = False            elif event.type == pygame.MOUSEBUTTONDOWN:                print "mouse down:",                pygame.mouse.get_pos()            elif event.type == pygame.MOUSEBUTTONUP:                print "mouse up:", pygame.mouse.get_pos()                        #R - Refresh display        screen.blit(background, (0,0))        pygame.display.flip()# end main game loop# Run main if this is the primary program# Note use of 2 underscoresif __name__ == "__main__":    main()  # call main function here    

Use help("pygame") once again and look at the very end where it says DATA and you'll get a list of all the keyboard constants.
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok I wanted to give an example of what use the drawing functions can be even though I'm not planning on using them in my game I think:
""" lines.py     combine event handling and     drawing commands to build    a prototype drawing program """import pygamepygame.init()def main():    screen = pygame.display.set_mode((640, 480))    pygame.display.set_caption("Draw lines with the mouse")        background = pygame.Surface(screen.get_size())    background.fill((255, 255,255))        clock = pygame.time.Clock()    keepGoing = True    preview = False    lineStart = (0, 0)    lineEnd = (0, 0)        while(keepGoing):        clock.tick(30)                for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False            elif event.type == pygame.MOUSEBUTTONDOWN:                lineStart = pygame.mouse.get_pos()                preview = True            elif event.type == pygame.MOUSEBUTTONUP:                lineEnd = pygame.mouse.get_pos()                pygame.draw.line(background, (0, 0, 0), lineStart, lineEnd, 3)                preview = False            elif event.type == pygame.MOUSEMOTION:                lineEnd = pygame.mouse.get_pos()                                    screen.blit(background, (0, 0))        if preview:            pygame.draw.line(screen, (100, 100, 100), lineStart, lineEnd, 1)        pygame.display.flip()    if __name__ == "__main__":    main()

The only new thing is that if you hold the mouse down the line is temporarily drawn to the screen(giving you a cool preview effect) which will disappear as soon as you release the mouse.
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Ok I think I've covered enough preliminaries so that anyone that's been programming Python for any amount of time should be able to decipher version 1.0 of my Pirates game!
Here it is:
""" pirates.py    Pirates version 1.0    First complete arcade game    made with Python and Pygame    move ship with mouse    deliver piracy to islands,    avoid thunderstorms.    Each island you plunder adds to your score.    Each cloud you hit is a hurricane and causes you to lose a ship.        Jaime Moreno    4/25/07      """#I - Import and initialize still in global scope   import pygame, randompygame.init()#D - Display configurationresolution = (800,600)screen = pygame.display.set_mode(resolution)#E - Entities (now contained in their own classes now# overall IDEA/ALTER game framework still intact though# we do have 2 alter's due to adding intro screen and game stateclass Ship(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load("ship.gif")        self.image = self.image.convert()        self.rect = self.image.get_rect()                def update(self):        mousex, mousey = pygame.mouse.get_pos()        self.rect.center = (mousex, 430)                class Island(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load("island.gif")        self.image = self.image.convert()        self.rect = self.image.get_rect()        self.reset()                self.dy = 5 # sets islands to move down screen and note speed is same as background scrolling ocean        def update(self):        self.rect.centery += self.dy        if self.rect.top > screen.get_height(): # makes islands wrap around to top            self.reset()                def reset(self):        self.rect.top = 0        self.rect.centerx = random.randrange(0, screen.get_width()) # we don't want islands appearing at same spot all time      class Cloud(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load("Cloud.gif")        self.image = self.image.convert()        self.rect = self.image.get_rect()        self.reset()    def update(self):        self.rect.centerx += self.dx        self.rect.centery += self.dy        if self.rect.top > screen.get_height():            self.reset()        def reset(self):        self.rect.bottom = 0        self.rect.centerx = random.randrange(0, screen.get_width())        # set clouds to move in random directions at random speeds        self.dy = random.randrange(5, 10)        self.dx = random.randrange(-2, 2)    class Ocean(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load("ocean.gif")        self.rect = self.image.get_rect()        self.dy = 5        self.reset()            def update(self):        self.rect.bottom += self.dy        # scrolling trick        # fool the player's eyesight into thinking the ocean background is infinite        if self.rect.bottom >= 1440:            self.reset()         def reset(self):        self.rect.top = -960class Scoreboard(pygame.sprite.Sprite):    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.lives = 5        self.score = 0        self.font = pygame.font.SysFont("None", 50)            def update(self):        self.text = "ships: %d, score: %d" % (self.lives, self.score)        yellow = (255, 255, 0)        self.image = self.font.render(self.text, 1, yellow)        self.rect = self.image.get_rect()    def game():    pygame.display.set_caption("Pirates v 1.0 by Jaime!")    background = pygame.Surface(screen.get_size())    background.fill((0, 0, 0))    screen.blit(background, (0, 0))    ship = Ship()        island = Island()    #can add more or less clouds here to make game harder or easier    cloud1 = Cloud()    cloud2 = Cloud()    cloud3 = Cloud()    ocean = Ocean()    scoreboard = Scoreboard()    friendSprites = pygame.sprite.Group(ocean, island, ship)    cloudSprites = pygame.sprite.Group(cloud1, cloud2, cloud3)    scoreSprite = pygame.sprite.Group(scoreboard)    clock = pygame.time.Clock()    #A - Action (broken into ALTER steps)    #A - Assign values to key variables    keepGoing = True    #L - Set up main loop    while keepGoing:        #T - Timer to set frame rate        clock.tick(30)        pygame.mouse.set_visible(False)        #E - Event handling        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False                #check collisions                if ship.rect.colliderect(island.rect):                        island.reset()            scoreboard.score += 100        hitClouds = pygame.sprite.spritecollide(ship, cloudSprites, False)        if hitClouds:                       scoreboard.lives -= 1            if scoreboard.lives <= 0:                keepGoing = False            for theCloud in hitClouds:                theCloud.reset()                friendSprites.update()        cloudSprites.update()        scoreSprite.update()                friendSprites.draw(screen)        cloudSprites.draw(screen)        scoreSprite.draw(screen)        #R - Refresh display        pygame.display.flip()            #return mouse cursor    pygame.mouse.set_visible(True)     return scoreboard.score    def instructions(score):    pygame.display.set_caption("Pirates v 1.0 by Jaime!")    ship = Ship()    ocean = Ocean()        allSprites = pygame.sprite.Group(ocean, ship)    insFont = pygame.font.SysFont(None, 50)    insLabels = []    instructions = (    "Pirates.     Last score: %d" % score ,    "Instructions:  You are a Pirate,",    "delivering terror to the islands.",    "",    "Sail over an island to plunder it,",    "but be careful not to sail too close",        "to the clouds. Your ship will fall ",    "apart if it is hit by lightning too",    "many times. Steer with the mouse.",    "",    "good luck!",    "",    "click to start, escape to quit..."    )        for line in instructions:        yellow = (255, 255, 0)        tempLabel = insFont.render(line, 1, yellow)        insLabels.append(tempLabel)    #A - Action (broken into ALTER steps)    #A - Assign values to key variables    keepGoing = True    clock = pygame.time.Clock()    pygame.mouse.set_visible(False)    #L - Set up main loop    while keepGoing:        #T - Timer to set frame rate        clock.tick(30)        #E - Event handling        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False                donePlaying = True            if event.type == pygame.MOUSEBUTTONDOWN:                keepGoing = False                donePlaying = False            elif event.type == pygame.KEYDOWN:                if event.key == pygame.K_ESCAPE:                    keepGoing = False                    donePlaying = True                 allSprites.update()        allSprites.draw(screen)        for i in range(len(insLabels)):            screen.blit(insLabels, (50, 30*i))        #R - Refresh display        pygame.display.flip()                pygame.mouse.set_visible(True)    return donePlaying        def main():    donePlaying = False    score = 0    while not donePlaying:        donePlaying = instructions(score)        if not donePlaying:            score = game()if __name__ == "__main__":    main()

And here's the screen shot of the introduction screen
Image Hosted by ImageShack.us

Notice how I added classes for all the main game entities like ship,ocean,island,cloud etc.
Each of them have a constructor, and update and reset method.
The only thing that I didn't really cover is using pygame.font but it's shouldn't be too hard to figure out.
The only tricky stuff really is creating the artwork for the game and to make the illusion of a scrolling background you need to make a background image that is way longer than it is wide(800x1800 for ocean.gif) so the player won't notice you are just recycling the same image over and over. Also make sure to modify the wrap code for the background image appropriately.
I know this was short on explanation but after taking a couple of days off I really wanted to get my Pirate version 1 at least up and running!






[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Looking back at my last post I just realized I totally forgot to talk about one of the most important things you will need to learn to make games no matter what language you use-collision detection!
Unlike alot of other languages where you have to write your own collision detection routines pygames makes it as easy as using the colliderect() method of a Rect object. If two rects are overlapping, the method returns true hence a collision. The following code shows how to use it:
""" spriteSprite.py     demonstrates a simple sprite - sprite    collision using rect's collision method    use mouse to move circle around and test for collisions"""    import pygame, randompygame.init()class Square(pygame.sprite.Sprite):    """ makes a box with a random starting         position and the given color.          To make a red square, use        redSquare = Square((255, 0, 0))                requires screen be predefined and import random """                   def __init__(self, color, screen):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.Surface((50, 50))        self.image.fill(color)        self.rect = self.image.get_rect()        self.rect.centerx = random.randrange(0, screen.get_width())        self.rect.centery = random.randrange(0, screen.get_height())    class Circle(pygame.sprite.Sprite):    """ makes a blue circle that         follows the mouse. """            def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.Surface((50, 50))        self.image.fill((255, 255, 255))        pygame.draw.circle(self.image, (0, 0, 255), (25, 25), 25, 0)        self.rect = self.image.get_rect()            def update(self):        self.rect.center = pygame.mouse.get_pos()class TransCircle(Circle):    """ extended collisionObjects circle with colorkey    transparency. """    def __init__(self):        Circle.__init__(self)        self.image.set_colorkey((255,255,255))        class Label(pygame.sprite.Sprite):    """ Label Class (simplest version)         Attributes:            font: any pygame font object            text: text to display            center: desired position of label center (x, y)    """    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.font = pygame.font.SysFont("None", 30)        self.text = ""        self.center = (320, 240)                    def update(self):        self.image = self.font.render(self.text, 1, (0, 0, 0))        self.rect = self.image.get_rect()        self.rect.center = self.centerdef main():    screen = pygame.display.set_mode((640, 480))    pygame.display.set_caption("sprite - to - sprite collision")        background = pygame.Surface(screen.get_size())    background.fill((255, 255, 255))    screen.blit(background, (0, 0))        lblOutput = Label()    lblOutput.center = (100, 50)    lblOutput.text = "Hi"        circle = Circle()    square = Square((0, 255, 0), screen)        allSprites = pygame.sprite.Group(square, circle, lblOutput)    keepGoing = True    clock = pygame.time.Clock()    pygame.mouse.set_visible(False)    while keepGoing:        clock.tick(30)        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False        # Use special colliderect() method of Rect object to test for collision        if circle.rect.colliderect(square.rect):            lblOutput.text = "Collision"        else:            lblOutput.text = "No collision"                    allSprites.clear(screen, background)        allSprites.update()        allSprites.draw(screen)                pygame.display.flip()    pygame.mouse.set_visible(True)if __name__ == "__main__":    main()

Ok now what if you have alot of objects to check for collisions? Using the above example it's still pretty simple but you'll end up with alot of repeated code and gets pretty old and tiring.
In this case pygame comes to the rescue once again with the pygame.sprite.spritecollide() function. It looks for all possible collisions between a sprite and all other sprites in a group so to use it you need to put your game objects into sprite groups as the following program shows:
""" spriteGroup.py     shows how to check for a    collision between a sprite and     a group    Movable circle coming in really handy now    to test for collisions    Also using sprite.spritecollide() instead of rect.colliderect()    This one uses TransCircle instead of Circle for transparent collisions!    Jaime Moreno    4/7/07    """    import pygame, randompygame.init()class Square(pygame.sprite.Sprite):    """ makes a box with a random starting         position and the given color.          To make a red square, use        redSquare = Square((255, 0, 0))                requires screen be predefined and import random """                   def __init__(self, color, screen):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.Surface((50, 50))        self.image.fill(color)        self.rect = self.image.get_rect()        self.rect.centerx = random.randrange(0, screen.get_width())        self.rect.centery = random.randrange(0, screen.get_height())    class Circle(pygame.sprite.Sprite):    """ makes a blue circle that         follows the mouse. """            def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.Surface((50, 50))        self.image.fill((255, 255, 255))        pygame.draw.circle(self.image, (0, 0, 255), (25, 25), 25, 0)        self.rect = self.image.get_rect()            def update(self):        self.rect.center = pygame.mouse.get_pos()class TransCircle(Circle):    """ extended collisionObjects circle with colorkey    transparency. """    def __init__(self):        Circle.__init__(self)        self.image.set_colorkey((255,255,255))        class Label(pygame.sprite.Sprite):    """ Label Class (simplest version)         Attributes:            font: any pygame font object            text: text to display            center: desired position of label center (x, y)    """    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.font = pygame.font.SysFont("None", 30)        self.text = ""        self.center = (320, 240)                    def update(self):        self.image = self.font.render(self.text, 1, (0, 0, 0))        self.rect = self.image.get_rect()        self.rect.center = self.centerdef main():    screen = pygame.display.set_mode((640, 480))    pygame.display.set_caption("colliding with a group")        background = pygame.Surface(screen.get_size())    background.fill((255, 255, 255))    screen.blit(background, (0, 0))        lblOutput = Label()    lblOutput.text = "Hi"    lblOutput.center = (100, 50)        circle = Circle()    # make 10 red squares at random locations    squares = []    for i in range(10):        square = Square((255, 0, 0), screen)        squares.append(square) # add square to list            basicSprites = pygame.sprite.Group(circle, lblOutput)    squareGroup = pygame.sprite.Group(squares)        keepGoing = True    clock = pygame.time.Clock()    while keepGoing:        clock.tick(30)        for event in pygame.event.get():            if event.type == pygame.QUIT:                keepGoing = False                    if pygame.sprite.spritecollide(circle, squareGroup, False): # set to True to have object die            lblOutput.text = "Collision"        else:            lblOutput.text = "No collision"                    squareGroup.clear(screen, background)        basicSprites.clear(screen, background)                squareGroup.update()        basicSprites.update()                squareGroup.draw(screen)        basicSprites.draw(screen)            pygame.display.flip()        if __name__ == "__main__":    main()

Finally some things to remember about collisions using pygame:
all sprites are rectangular
pygame uses bounding-box collision detection
what this all means is that sometimes you will register a collision even though you can see on the screen that the objects are not actually touching(but their bounding boxes are!).
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe

This topic is closed to new replies.

Advertisement