This series of blogs introduces the development of mini-games in the Python+pygame library. There is the wrong point of writing and hope you haihan.
Previous blog We learned about the Sprite module in Pygame and how to load the animation: http://www.cnblogs.com/msxh/p/5013555.html
This time we are going to study conflict detection techniques in pygame.
Pygame supports a very great number of conflict detection technologies, so let's take a one by one look at how they're used:
One, the clash between elves and elves detection
1. Rectangle detection between two sprites
We can use the Pygame.sprite.collide_rect () function for a one-to-one collision detection when there are only two sprites. This function needs to pass 2 parameters, and each parameter needs to inherit from Pygame.sprite.Sprite.
As an example:
Spirte_1 = MySprite ("sprite_1.png", 200,200,1= MySprite ("Sprite_ 2.png", 50,50,1= pygame.sprite.collide_rect (sprite_1,sprite_2)if Result: print"collision occurred"
Mysprite makes the class that we created in the last blog, he inherits from the sprite.
Hint: This function also has a very useful variant: Pygame.sprite.collide_rect_ratio (). This function requires an extra floating-point type parameter. This parameter is used to specify the percentage of the detection rectangle.
Sometimes we want the conflict detection to be more accurate, we can shrink the detection area, let the rectangle smaller, is controlled by this parameter. Here's how to use it:
result = Pygame.sprite.collide_rect_ratio (0.5) (sprite_1,sprite_2)
2. Circle detection between two sprites
Rectangle Collision Detection does not apply to all shapes of sprites, so there is also a circular collision detection in Pygame. Pygame.sprite.collide_circle (), this function is detected based on the radius value of each sprite.
You can specify the radius yourself, or let the function calculate its own radius.
result = pygame.sprite.collide_circle (sprite_1,sprite_2)if result: Print " collision occurred "
This function also has a variant: Pygame.sprite.collide_circle_ratio (). Function and usage are similar to the above Pygame.sprite.collide_rect_ratio ().
3. Pixel mask detection between two sprites
What if the rectangle detection and round detection are not sufficient for our needs? Don't worry, Pygame also provides us with a more accurate test: Pygame.sprite.collide_mask ().
This function receives two sprites as a parameter, and the return value is a bool variable.
if Pygame.sprite.collide_mask (sprite_1,sprite_2): Print ("collision occurred")
4. Rectangle collision Detection between sprites and groups
Pygame.sprite.spritecollide (Sprite,sprite_group,bool). When this function is called, all sprites in a group are automatically conflicting against another individual sprite, and the conflicting sprite is returned as a list.
The first parameter of this function is a single sprite, the second parameter is the sprite group, the third parameter is a bool value, and finally this parameter plays a very important role. When true, all conflicting sprites in the group are deleted, and false will not delete the conflicting sprite
List_collide = Pygame.sprite.spritecollide (Sprite,sprite_group,false);
In addition, this function has a variant: Pygame.sprite.spritecollideany (). This function returns a bool value when judging a conflict between a sprite group and a single sprite.
5. Rectangle collision Detection between sprite groups
Pygame.sprite.groupcollide (). Using this function to detect a conflict between two groups, he returns a dictionary. (Key-value pair)
Okay, there's probably a couple of common conflict detection functions we've done, let's do a little example to actually use the knowledge learned above.
Second, the conflict detection example---eat apple games
First Look at:
The game starts to randomly generate some apples on the screen, and the player controls the characters to eat the apples by the right and left arrow keys.
If you eat an apple, the energy bar will grow, until you finish eating all the apples and the game is over.
"Source code + footage"
Network disk: http://yunpan.cn/c3SttjmY2yYPk access password 4a7b
GitHub Address: Https://github.com/XINCGer/Eat-apple-Game
1. Modular Programming
This game uses the Mysprite class that we created on our last blog to make this class more reusable, and we make it into a module.
Just put the implementation code of the class into a separate py, and then introduce him when you use it. For example, we name this individual py: mylibrary.py
Import MyLibrary
This is the only thing we need to do when using the functions and classes in this module: Mylibrary.fun (). But it does not seem very convenient to say so, so we use the variant of import:
from Import *# Bring all the contents of the file into
2. Advanced Walking Animation
Through, we can see that the program used a high-level walking animation, the characters have a total of up and down about four direction of walking animation.
In fact, in this sprite sequence diagram there is a total of 8 direction of walking animation, for the sake of simplicity, we just use four of the direction,
By the number of rows can be convenient to distinguish, animation is left or right to go. Now it may be a little more difficult to understand, read the following code is better understood. We also added a velocity property to the Mysprite class so that the sprite can move in its direction.
classMySprite (pygame.sprite.Sprite):def __init__(self): Pygame.sprite.Sprite.__init__(self) self.master_image=None Self.frame=0 Self.old_frame=-1Self.frame_width= 1Self.frame_height= 1Self.first_frame=0 Self.last_frame=0 Self.columns= 1Self.last_time=0 self.direction=0#new Velocity attribute, he is a pointSelf.velocity = Point (0.0,0.0)
When you press the UP key, set the direction to 0 (up), press the Down key, set the direction to 4 (down), press the left key, set the direction to 6 (right), press the right key, and set the direction to 2 (rightwards)
ifKeys[k_escape]: sys.exit ()elifKEYS[K_UP]orKeys[k_w]: player.direction=0 player_moving=TrueelifKeys[k_right]orKeys[k_d]: player.direction= 2player_moving=TrueelifKeys[k_down]orkeys[k_s]: player.direction= 4player_moving=TrueelifKeys[k_left]orKeys[k_a]: player.direction= 6player_moving= True
This direction is what we said earlier to determine the range method used to animate frames. And there is a player_moving variable, when the key is pressed to set it to true, that is, press the button to have a walking animation, otherwise the character will be static.
3. Judging the clash of characters and apples
In order to achieve a more precise conflict, we used a combination of different conflicting functions.
First use Pygame.sprite.spritecollideany to determine whether the player and any Apple has a collision, if a collision, then use the pygame.sprite.collide_circle_ratio to narrow the detection range to do a test,
See exactly which Apple and character are in conflict, and then remove the resulting collision from the sprite group (remove).
# Detects if the player is in conflict with the food and eats the fruit Attacker = None = pygame.sprite.spritecollideany (player, Food_group) if attacker ! = None :if pygame.sprite.collide_circle_ratio (0.65) (player,attacker) :+ =2; Food_group.remove (attacker);
After eating the fruit, the energy value increases, and then we reflect to the user by drawing a rectangular energy bar.
All right, last up. All source code (not including MyLibrary module):
Importitertools, sys, time, random, math, Pygame fromPygame.localsImport* fromMyLibraryImport*defCalc_velocity (Direction, vel=1.0): Velocity=Point (0,0)ifDirection = = 0:#onVELOCITY.Y =-velelifDirection = = 2:#Rightvelocity.x =velelifDirection = = 4:#underVELOCITY.Y =velelifDirection = = 6:#leftvelocity.x =-velreturnvelocitypygame.init () screen= Pygame.display.set_mode ((800,600)) Pygame.display.set_caption ("Eat apples") Font= Pygame.font.Font (None, 36) Timer=Pygame.time.Clock ()#Create a sprite groupPlayer_group =pygame.sprite.Group () Food_group=Pygame.sprite.Group ()#Initialize the player sprite groupPlayer =MySprite () player.load ("farmer Walk.png", 96, 96, 8) Player.position= 80, 80player.direction= 4Player_group.add (player)#Initialize Food elf group forNinchRange (1,50): Food=MySprite (); Food.load ("Food_low.png", 35, 35, 1) Food.position= Random.randint (0,780), Random.randint (0,580) Food_group.add (food) game_over=falseplayer_moving=Falseplayer_health=0 whileTrue:timer.tick (30) Ticks=pygame.time.get_ticks () forEventinchpygame.event.get ():ifEvent.type = =QUIT:pygame.quit () sys.exit () keys=pygame.key.get_pressed ()ifKeys[k_escape]: sys.exit ()elifKEYS[K_UP]orKeys[k_w]: player.direction=0 player_moving=TrueelifKeys[k_right]orKeys[k_d]: player.direction= 2player_moving=TrueelifKeys[k_down]orkeys[k_s]: player.direction= 4player_moving=TrueelifKeys[k_left]orKeys[k_a]: player.direction= 6player_moving=TrueElse: player_moving=Falseif notGame_over:#use different animation frames depending on the direction of the rolePlayer.first_frame = Player.direction *player.columns Player.last_frame= Player.first_frame + player.columns-1ifPlayer.frame <Player.first_frame:player.frame=Player.first_frameif notplayer_moving:#Stop updating animation frames when the button stops (that is, when the character stops moving)Player.frame = Player.first_frame =Player.last_frameElse: Player.velocity= Calc_velocity (player.direction, 1.5) player.velocity.x*= 1.5player.velocity.y*= 1.5#Update player Sprite GroupPlayer_group.update (Ticks, 50) #Mobile Player ifPlayer_moving:player. X+=player.velocity.x player. Y+=player.velocity.yifPlayer. X < 0:player. X =0elifPlayer. X > 700:player. X = 700ifPlayer. Y < 0:player. Y =0elifPlayer. Y > 500:player. Y = 500#Detects if the player is in conflict with the food and eats the fruitAttacker =None Attacker=Pygame.sprite.spritecollideany (player, Food_group)ifAttacker! =None:ifPygame.sprite.collide_circle_ratio (0.65) (Player,attacker): Player_health+=2; Food_group.remove (attacker); ifPlayer_health > 100:player_health = 100#Update Food elf groupFood_group.update (Ticks, 50) ifLen (food_group) = =0:game_over=True#Clear ScreenScreen.fill ((50,50,100)) #Drawing Spritesfood_group.draw (screen) player_group.draw (screen)#draw the player's blood barPygame.draw.rect (screen, (50,150,50,180), rect (300,570,player_health*2,25)) Pygame.draw.rect (screen, (100,200,100,180), Rect (300,570,200,25), 2) ifgame_over:print_text (Font,300, 100,"G A M e O V e R") pygame.display.update ()
In the next blog we will learn about some of the data structures used in the game: data, lists, tuples, queues, stacks.
"Python Game Programming Tour" The seventh chapter---Conflict Detection technology in Pygame