= Intro = Pygame is a library for making arcade style sprite games It features very easy blitting and colision detection I have some sample code to help with understanding pygame here: https://code.edge.launchpad.net/~rick-rickspencer3/pygame-template/trunk note that this is a bit old, and I need to reformat it and such however, it will eventually be a quickly template, hopefully in time for lucid if you want to grab that it might help you follow the class a bit, but it is not required it comes with some basic game play that you can study and modify essentially, it is kind of like asteroids you control the black triangle in the middle, and there are two enemies Of course you will want some docs Pygame has good docs here: http://www.pygame.org/docs/ = Setting up a game = first thing you need to do is set up a game surface initialize pygame libraries pygame.font.init() pygame.mixer.init() then create a screen the screen will be the surface on which your sprites will be drawn, essentially where your game will occur screen = pygame.display.set_mode((800, 480)) also, create a couple of variable you will need later like a background image background = pygame.image.load(path_to_background) and a clock clock = pygame.time.Clock() pygame games use a good old fashioned input loop essentially, you tell your app to keep looping and whenever it goes through the loop do a few things respond to user input update data for any sprites on the screen this includes seeing if any sprites have collided tell the app to update itself let's look at setting up a game loop while 1: clock.tick(15) if ControllerTick() == 0: return if not game.paused: ViewTick() if CheckCollisions() == 0: return you can see this code in the crashteroids file at line 169 so first, the loop just runs and runs until etiher ControllerTick or CheckCollisions returns 0 the first line in the loop basically says to have 15 frames per second this is not like a sleep function where the argument says how long to sleep make sure that you pick a number that is low enough that a lower powered computer can keep up, if you care about that kind of thing The next line calls ControllerTick This function checks for user input, which I will explain in a moment, and the updates all the game data Then assuming that the game is not paused, it will go ahead and update the view and do collision detection The reason that controllertick is always called is because this function controlls pausing and unpausing of the game we'll look at each of these functions in more detail now But first, questions? = using input = pygame basically queues up input events you can then loop through them and respond to each event at line 93, you can see how the loop is set up for event in pygame.event.get(): if event.type == pygame.QUIT: return 0 pygame.QUIT is called when the window closes or such of course you could also do something smart and save game state or such but this code returns 0, which causes the main event loop to quit now, let's say what I want to do is make the ship go forward when the user presses the j key first I ask what kind of event it was if event.type == pygame.KEYDOWN: and then if it was a key event, what key was pressed if event.key == pygame.K_l: #do something you can see the whole tree of if, else statements starting at line 89 there are also events for the mouse and joysticks even so it's easy to create games that aren't only using the keyboard if you want so that's how to handle input let's look at sprites, but first, any questions? = managing a sprite = A sprite is basically an image in an arcade game pygame handles blitting for you, which is quite nice I'll discuss blitting in a bit If you wrote games long ago, you may remember rendering a sprite strip to an offscreen graphics world and then selecting bits of that strip and copying them to the onscreen graphics world pygame does not reqiure that at all it is much more fun and easy you just subclass the Sprite class the key thing a sprite has is an Pygame.Image member, called image I usually like to keep the original image around, as if you keep rotating the image and such, it will get more and more distorted over time so I set the image object like this self.masterImage = pygame.image.load(path_to_image_file) self.image = self.masterImage a sprite also has a "virtual" function, called update update is supposed to be called to tell a sprite to update it's data for a tick you set things like the sprite's x, y coordinates in this function, and such all your sprites should use this because you can then add a sprite to a RenderUpdates sprite group and then call update for that group, which will call update for each sprite you create a sprite group like this: enemies = pygame.sprite.RenderUpdates() and then you can add an sprite to that group enemies.add(create_enemy()) you can also empty a sprite group enemies.empty() useful when you are resetting a level or something as we'll see later, sprite groups also help lots with collision detection back to sprites though so you have an image on a sprite you also need to define an x and y for your sprite I in my sprite subclass, I might set x and y randomly like this: self.x = random.randint(0,300) self.y = random.randint(0,140) but then on each call to update(), just change the x and/or y if the sprite is moving sprites also have a "kill()" member function calling kill causes the sprite to be removed from the playing surface questions before we talk about updating the display? = updating the display so now you have your event loop running, your game surface set up, and some sprites created now we need to actually draw the sprites for sprites that are not in a sprite group, we need to blit them fortunately this does not involve the crazy gworld hackery of days of hold pygame gives us a blit method blitting is essentially the act of repainting parts of the screen that have changed without blitting, the whole screen repaints and appears to flash so to blit the blackgroud, we'll use the screen to blit remember when we created teh screen object? now it's time to use it screen.blit(background, [0,0]) blitting the background like this basically repaints the whole background image over everything if you are tuning for a very slow platform, or a game with lots and lots of sprites, you can't do it this way or you get flashing in those cases you need to track the parts of the background exposed by moving sprites this is a bit of work, but probably will not be necessary for you to do to blit an individual sprite, you have to tell the screen the image to use and the rect, or xy coords and dimensions, for hte sprite to blit So if we have a sprite object called "g", we blit it like this: screen.blit(g.image, g.rect) sprites in a sprite group are a bit easier to blit you can tell the sprite group to blit them all: enemies.draw(screen) this blits all the enemies for you question before we discuss collision detection? = collision detection = so let's say when an enemy rams our guy, we want both to be killed but how to tell when an ememy hits? detecting overlapping sprites is called "collision detection" and is handled quite well by PyGame this saves you tons of work you can detect if two sprites have collided using pygame.sprite.spritecollide (), collideany, or groupcollide so let's see if our guy, called g, has collided with an enemy e = pygame.sprite.spritecollideany(g, enemies) call this each tick if the guy has not collided with any enemies, e will be None but when e is not None, that means boom let's say your guys shoots bullets those bullets will most likely be managed in a sprite group so we should also see if any enemies were killed by bullets hits_dict = pygame.sprite.groupcollide(bullets, enemies, False, False) here you get back a dictionary the keys are sprites from the first sprite group and the values are keys from the second sprite group so then we can just go through and kill each bullet and enemy for the collision: for b in hits_dict: for e in hits_dict[b]: e.kill() b.kill() ok, next and last section is on playing sounds any questions first? = playing sounds = we use the Pygame.mixer module to manage sounds we need to initialize it before we use it: pygame.mixer.init() now I'll load an explosion sound to play when my guy explodes: self.explosionSound = pygame.mixer.Sound(path_to_sound_file) let's assume this sound is a bit loud, we can adjust the volume as we like: self.explosionSound.set_volume(.2) then we can play the sound: self.explosionSound.play() we can stop it too if it's going too long: self.explosionSound.stop() the mixer module is quite rich there are channels, fades, and all kinds of stuff ok, any last questions?