Python pyGame to achieve aircraft War-2

Python pyGame to realize aircraft War 1:https://blog.csdn.net/weixin_38778769/article/details/117329303

Continue the previous one. The previous one talked about adding game frames, game backgrounds, and the movement of players' planes

The purpose of this tutorial is to generate enemy aircraft, the movement of enemy aircraft, the destruction and rebirth of enemy aircraft and players after their collision
As follows:

First prepare the resources, which can also be downloaded from the network. Why do I use the tutorial resources directly here (it's really good-looking, and it's terrible to find it myself). I've put up the package of the whole project, including the source code and resources. I've basically added all the comments, which can be downloaded and viewed by myself: https://download.csdn.net/download/weixin_38778769/19126067 . Or directly download the picture below (to be used in this step) to undertake the resources of the previous one:

Then I won't say much. I'll go straight to the code. Basically, the comments that can be made on each line and the end of the method are written in detail. If there is something that is not described correctly, I can comment (I'm a chicken, please spray it gently)
enemy.py (enemy aircraft class, including the attributes, operation, reset, etc. of enemy aircraft)
The knowledge point is 1. " Initialization of base class“

import pygame
from random import *


# Small aircraft
# pygame.sprite.Sprite is a class used to implement sprites in Pygame. When using it, you don't need to instantiate it. You just need to inherit it and write your own class as needed. Therefore, it is very simple and practical
# All sprites are created from pyGame sprite. Inherited from Sprite
class SmallEnemy(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        # This involves the construction of "initialization of base class", which is well understood by Baidu.
        # Generally speaking, the SmallEnemy class inherits the parent class pyGame sprite. Sprite, child class and parent class__ init__ () this function. If the subclass does not implement this init() function,
        # Then, the initialization function of the parent class is called directly during initialization. If the child class implements this init() function, it will override the function of the parent class. Since it inherits the parent class, it is necessary to explicitly call the initialization function of the parent class in this function__ init__ ()
        pygame.sprite.Sprite.__init__(self)
        # Pictures of enemy aircraft
        self.image = pygame.image.load('images/enemy1.png').convert_alpha()
        # Picture of enemy aircraft destroyed
        self.destory_images = []
        self.destory_images.extend([
            pygame.image.load('images/enemy1_down1.png').convert_alpha(),
            pygame.image.load('images/enemy1_down2.png').convert_alpha(),
            pygame.image.load('images/enemy1_down3.png').convert_alpha(),
            pygame.image.load('images/enemy1_down4.png').convert_alpha()
        ])
        # Define screen width and height
        self.width = bg_size[0]
        self.height = bg_size[1]

        # get_rect() is a method for processing rectangular images. The return value contains the attributes of the rectangle. Here, the position of the enemy plane picture is returned, and the width and height attributes of the picture can be obtained
        self.rect = self.image.get_rect()

        # Randomly generate the position of the aircraft. randint(a,b) generates a < = n < = B, which is randomly generated under the screen width and minus 5 times the height
        self.rect.left = randint(0, self.width - self.rect.width)
        self.rect.top = randint(-5 * self.height, 0)

        # Small enemy aircraft speed
        self.speed = 2
        # Is the enemy plane alive
        self.active = True
        # Aircraft collision detection will ignore the white background in the picture
        self.mask = pygame.mask.from_surface(self.image)

    # The small enemy plane moved downward
    def samll_enemy_move(self):
        # For example, the plane can fly down randomly without waiting for the x-axis to move out of the screen
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.reset()

    # After the plane flies out of the screen, don't waste it, reset its position (or destroy it, you have to deal with it anyway, otherwise the memory will explode)
    def reset(self):
        # It's OK to write it here or not, because it's in a state of survival, so it's safer to write it
        self.active = True
        # Randomly reset the position of the aircraft, as generated above
        self.rect.left = randint(0, self.width - self.rect.width)
        self.rect.top = randint(-5 * self.height, 0)



The mian here is added on the basis of the previous one, that is, call the enemy aircraft class to generate a small enemy aircraft, and then the enemy aircraft moves. If it collides with the player's aircraft, both will be destroyed and the player's life will be reduced by one
main.py
Main knowledge points involved:
1.pygame. sprite. The Group () function can create a sprite Group for unified management and the corresponding methods of the Group
2.pygame.USEREVENT stands for event 1, pyGame time. set_ Timer: every once in a while (here is 3MS * 1000 = 3s), execute some actions, and then pass event type == invincible_ Event to capture the occurrence of the event
3. Collision detection, pyGame sprite. Sprite collapse (Sprite, sprite_group, bool): all sprites in a group will perform conflict detection on another single sprite one by one

import pygame
import sys
import traceback
from pygame.locals import *
from random import *
import myplane
import enemy

# initialization
pygame.init()
# Set window size
bg_size = width, height = 400, 700  # It's actually a tuple
screen = pygame.display.set_mode(bg_size)  # Setup window
pygame.display.set_caption("Aircraft war")  # Window title
# When loading the background picture, the display effect of ordinary images is the same whether there is convert or not, but using Convert can convert the format and improve the speed of blit
background = pygame.image.load("images/background.png").convert()

# Set the corresponding values of black, green, red and hundreds of colors, which will be used later
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)

# Generate enemy small aircraft
def add_small_enemy(small_enemies, enemiesGroup, num):
    for i in range(num):
        smallenemy = enemy.SmallEnemy(bg_size)
        # Sprite group to realize multiple images, which is very suitable for processing sprite list. There are methods of adding, removing, drawing, updating and so on
        # Group.sprites sprite group
        # Group.copy copy
        # Group.add add
        # Group.remove remove
        # Group.has determine the members of the wizard group
        # Group.update update
        # Group.draw bit block display
        # Group.clear - draw background
        # Group.empty empty
        # Adding this group of enemy aircraft to the attribute of small aircraft is equivalent to unified processing and unified assignment
        small_enemies.add(smallenemy)
        enemiesGroup.add(smallenemy)

def main():
    # Create a clock object (you can control the frequency of game cycles)
    clock = pygame.time.Clock()

    # Generate player aircraft
    me = myplane.MyPlane(bg_size)

    # Store all enemy aircraft. This aircraft group contains various attributes of small aircraft, medium aircraft and large aircraft, as long as it is used to deal with collision
    # When there are a large number of entities in the program, operating these entities will be quite troublesome
    # Use pyGame sprite. The group() function can create a wizard group for unified management. Here, an enemy group is created
    enemiesGroup = pygame.sprite.Group()

    # Generate local small aircraft, and the enemy small aircraft is also a group for unified processing
    small_enemies = pygame.sprite.Group()
    add_small_enemy(small_enemies, enemiesGroup, 15)

    # Players have three lives
    life_num = 3
    # Set the invincible time event, pyGame Userevent stands for event 1, pyGame Userevent + 1 represents event 2, and so on, which is equivalent to defining an event
    invincible_event = pygame.USEREVENT

    # The game is suspended. The default is non suspended
    paused = False

    # Control the player's aircraft picture switching to show the sudden effect
    switch_image = True
    # Handover Delay 
    delay = 100

    # Game score
    score = 0

    # The subscript of the picture of aircraft explosion is the subscript of the explosion picture of small enemy aircraft, medium enemy aircraft, large enemy aircraft and player aircraft in turn. Switch the subscript to change the explosion picture
    e1_destory_index = 0
    e2_destory_index = 0
    e3_destory_index = 0
    me_destory_index = 0

    running = True
    while running:
        # Get event
        for event in pygame.event.get():
            # The end event triggers the end operation
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            # When the collision was triggered, pyGame was written time. set_ timer(invincible_event, 3*1000)
            # It means that invincible will be executed in 3 seconds_ Event event, which captures invincible_ After the event event is executed, the timer will be canceled to prevent the loop from executing repeatedly and wait for the next trigger
            if event.type == invincible_event:
                # Disarm invincible state
                me.invincible = False
                pygame.time.set_timer(invincible_event, 0)


        # Detect the user's keyboard operation, up, down, left and right respectively
        key_pressed = pygame.key.get_pressed()
        if key_pressed[K_w] or key_pressed[K_UP]:
            me.moveUp()
        if key_pressed[K_s] or key_pressed[K_DOWN]:
            me.moveDown()
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            me.moveLeft()
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            me.moveRight()


        # Draw a background image on the screen and specify the location
        screen.blit(background, (0, 0))

        # Draw bullet supply, bomb supply and other elements
        # Not paused and life greater than 0
        if paused == False and life_num > 0:
            # Draw small enemy aircraft because the small aircraft group is defined above. The aircraft group add s the attributes of small aircraft (speed, position, etc.), and then the aircraft is generated on the map
            # If these aircraft belong to the category of small enemy aircraft, they will be handled together
            for ei in small_enemies:
                # The enemy plane was alive and undamaged
                if ei.active == True:
                    # Draw a small enemy plane and the enemy plane begins to move
                    screen.blit(ei.image, ei.rect)
                    ei.samll_enemy_move()
                # Small enemy aircraft are destroyed (destroyed by players or collided with players)
                else:
                    # Delay% 4 here means that the explosion picture is 4 frames (personal guess), which is understood as the explosion residence time, which can be set by yourself
                    if not (delay % 4):
                        # It is used to play the sound of explosion. Each enemy aircraft has only one time
                        if e1_destory_index == 0:
                            print("Play the explosion sound of enemy aircraft")
                        # Draw the picture of enemy aircraft impact and explosion
                        screen.blit(ei.destory_images[e1_destory_index], ei.rect)
                        # Switch the subscript of the explosion picture, so as to switch the explosion picture
                        e1_destory_index = (e1_destory_index + 1) % 4
                        # After a round of explosion, the enemy aircraft can be destroyed or reborn. We have to deal with them, otherwise they will explode and explode all the time
                        # Here choose to rebirth it
                        if e1_destory_index == 0:
                            ei.reset()
                            score += 1000
                            print("score:", score)

            # Do collision detection, pyGame sprite. Sprite collapse (Sprite, sprite_group, bool): all sprites in a group will perform conflict detection on another single sprite one by one, and the conflicting sprites will be returned as a list.
            # The first parameter is a single Sprite, the second parameter is a sprite group, and the third parameter is a bool value. Finally, this parameter plays a great role. When True, all conflicting sprites in the group will be deleted. When False, conflicting sprites will not be deleted
            # The fourth parameter is pixel mask detection between two sprites
            enemy_collide = pygame.sprite.spritecollide(me, enemiesGroup, False, pygame.sprite.collide_mask)
            # Collision processing, if the collision occurs in the invincible state
            if enemy_collide and not me.invincible:
                # Player aircraft trigger destroy status
                me.active = False
                # enemy_ Collapse is a list that stores all enemy aircraft that collide with the player's aircraft, and then sets the status of the collided enemy aircraft to destroy status
                for ei in enemy_collide:
                    ei.active = False

            # Draw the player's plane if it is active
            if me.active:
                # Draw the player's plane on the screen, switch_image is whether to switch pictures
                if switch_image:
                    screen.blit(me.image1, me.rect)
                # Switch the flight picture
                else:
                    screen.blit(me.image2, me.rect)
            # It means that the aircraft was collided and the explosion was activated
            else:
                if not (delay % 4):
                    # It is used to play the sound of explosion. Each enemy aircraft has only one time
                    if me_destory_index == 0:
                        print("Player plane explosion sound")
                    # Draw player impact explosion screen
                    screen.blit(me.destory_image[me_destory_index], me.rect)
                    # Switch the subscript of the explosion picture, so as to switch the explosion picture
                    me_destory_index = (me_destory_index + 1) % 4
                    # After the explosion, the plane was reborn
                    if me_destory_index == 0:
                        # Life is reduced by one. If you see 0, you will automatically skip the previous cycle
                        life_num -= 1
                        # reset state 
                        me.reset()
                        # Invincible time is set to 3 seconds. After 3 seconds, the invincible time event, pyGame, will be triggered time. set_ Timer: every once in a while (here is 3MS * 1000 = 3s) to perform some actions
                        pygame.time.set_timer(invincible_event, 3 * 1000)


            delay -= 1
            if delay == 0:
                delay = 100
            # Switch the flight picture style every 5 frames
            if delay % 5 == 0:
                switch_image = not switch_image


        # Update the whole Surface object to be displayed to the screen, and display the contents in memory to the screen
        pygame.display.flip()
        # Specify the cycle frequency through the clock object, and cycle 60 times per second
        # The frame rate is the rate at which the program draws graphics on the screen per second
        clock.tick(60)

if __name__ == "__main__":
    try:
        main()
    # Normal service exit
    except SystemExit:
        print("The game exits normally!")
        # pass ignores the error and continues to run. In fact, it exits here
        pass
    # Other exceptions occurred in the service
    except:
        # Print the error directly
        traceback.print_exc()
        pygame.quit()

Myplane from the previous one Py, there are no additional things added here, and they are also pasted here:

import pygame

# Player aircraft, pygame Sprite module contains a class named Sprite, which is a wizard of pygame itself.
class MyPlane(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        # convert_alpha() changes the pixel format of the image, including the alpha of each pixel, which is equivalent to that the picture background becomes transparent
        self.image1 = pygame.image.load('images/me1.png').convert_alpha()
        self.image2 = pygame.image.load('images/me2.png').convert_alpha()
        # Pictures of aircraft destruction are saved in digital form
        self.destory_image = []
        self.destory_image.extend([
            pygame.image.load('images/me_destroy_1.png').convert_alpha(),
            pygame.image.load('images/me_destroy_2.png').convert_alpha(),
            pygame.image.load('images/me_destroy_3.png').convert_alpha(),
            pygame.image.load('images/me_destroy_4.png').convert_alpha()
        ])
        # Define screen width and height
        self.width = bg_size[0]
        self.height = bg_size[1]

        # get_rect() is a method for processing rectangular images. The return value contains the attributes of the rectangle. Here, the position of aircraft picture 1 is returned to obtain the width and height attributes of the picture
        self.rect = self.image1.get_rect()

        # The initialization position of the aircraft, / / is the division, the position is centered and the height is 60 from the bottom of the screen
        self.rect.left = (self.width - self.rect.width)//2
        self.rect.top = self.height - self.rect.height - 60

        # Set the speed of the aircraft
        self.myPlaneSpeed = 10
        self.active = True

        # Set whether the aircraft is invincible (invincible within 3 seconds of rebirth)
        self.invincible = False

        # Aircraft collision detection will ignore the white background in the picture and return a Mask from the specified Surface object
        # For fast and perfect collision detection, Mask can judge accurately to 1 pixel level.
        # The transparent part of the Surface object is set to 1 and the opaque part is set to 0.
        self.mask = pygame.mask.from_surface(self.image1)

    # Player plane moves up
    def moveUp(self):
        # The description has not been fixed, that is, it has not reached the boundary on the game interface
        if self.rect.top > 0:
            self.rect.top -= self.myPlaneSpeed
        # Indicates that the movement has reached the upper boundary
        else:
            self.rect.top = 0

    # Player plane moves down
    def moveDown(self):
        # A height of 60 needs to be marked at the bottom to display other data (number of bombs, number of lives, etc.)
        if self.rect.bottom < self.height - 60:
            # self.rect.bottom refers to the lower boundary of the aircraft picture
            self.rect.bottom += self.myPlaneSpeed
        else:
            self.rect.bottom = self.height - 60

    # Player plane moves left
    def moveLeft(self):
        if self.rect.left > 0:
            self.rect.left -= self.myPlaneSpeed
        else:
            self.rect.left = 0

    # The player's plane moves to the right
    def moveRight(self):
        if self.rect.right < self.width:
            self.rect.right += self.myPlaneSpeed
        else:
            self.rect.right = self.width

    # Player plane rebirth
    def reset(self):
        self.active = True
        # Be invincible when reborn
        self.invincible = True
        # The initialization position of the reborn aircraft, / / is the division, the position is centered and the height is 60 from the bottom of the screen
        self.rect.left = (self.width - self.rect.width) // 2
        self.rect.top = self.height - self.rect.height - 60

Keywords: Python Game Development

Added by motofzr1000 on Tue, 08 Feb 2022 12:17:38 +0200