""" 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
Pygame easy as Py
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:
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
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]
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.
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))
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.
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.
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:
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
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
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:
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:
""" 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:
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:
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.
""" 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.
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:
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.
""" 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.
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:
And here's the screen shot of the introduction screen
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!
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
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!
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:
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:
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!).
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!).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement