Python pyGame realizes the functions of aircraft war-5-screen rendering, drawing score, number of lives, number of super bombs and pause

Posted by oldmanice on Mon, 07 Feb 2022 12:00:04 +0100

Follow the previous 4 steps:
1. Add background and aircraft movement: https://blog.csdn.net/weixin_38778769/article/details/117329303
2. Add enemy aircraft and collision explosion: https://blog.csdn.net/weixin_38778769/article/details/117356538
3. Firing bullets and hitting enemy aircraft: https://blog.csdn.net/weixin_38778769/article/details/117410935
4. Obtain supplies, launch enhanced bullets and enlarge the clear screen: https://blog.csdn.net/weixin_38778769/article/details/117415884

The functions added this time are: screen rendering score, number of life, number of super bombs and pause function
The display is as shown in the figure:

Among the required resources, the text resources cannot be uploaded. There is no way. You can find it yourself or download the connection of the package above me (it seems to cost 6 points, which is a little shameless) 😂)

Then this time in the code module as long as it is still main Py changes. If someone looks at this step from the beginning, they will find a total of:
main.py: render various components, run logic, etc. in this step, the functions of rendering score, super bomb count, life count and pause are added
bullet.py: mainly the control of bullets, including various attributes of bullets and the reset of bullets
enemy.py: enemy aircraft class, including the attributes, operation, reset, etc. of enemy aircraft
myplane.py: it is mainly the control of the player's aircraft, including various attributes of the player's aircraft, the up, down, left and right movement of the aircraft, and the rebirth of the aircraft
supply.py: it mainly refers to the control of supply, including the movement and reset of supply. In fact, it is written in the same way

Knowledge points (I suggest you take a look at Baidu):
1. Draw fractional text, * * pyGame font. Font. render() 😗* Draw text on a new Surface object
pygame.font.Font.render(text, antialias, color, background=None)
a. text: text to display
b. antialias: when True, the text image is smoother, and when False, the text image is jagged
c. color: font color
d. background: background color (optional parameter). The default is small black screen

2.paused_rect.collidepoint(event.pos)
buttons – a tuple containing three numbers. The three values represent the left, middle and right keys respectively. 1 is pressed.
pos – is the location
rel – represents the current distance from the last time a mouse event was generated

Put it directly on main py code, other codes are not put in this step, otherwise there will be a lot (it's hard to put. py files directly). If necessary, you can go to the previous steps to check, or download all the codes in that package.

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


# 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()

# The following colors are used: red, black and green
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)

    # Generate ordinary bullets. Here is the cycle of four bullets
    bullet1s = []
    # Mark which bullet happened
    bullet1s_index = 0
    # Number of bullets
    bullet1_num = 4
    for i in range(bullet1_num):
        # Send the position of the player's plane to the bullets
        bullet1s.append(bullet.Bullet1(me.rect.midtop))

    # Generate enhanced bullets. Here are eight bullet cycles, four on the left and four on the right
    bulletspro = []
    # Mark which bullet happened
    bulletspro_index = 0
    # Number of bullets
    bulletspro_num = 8
    # Press four bullets into the left and right, and / / 2 represents the division. In fact, it is the same with / 2
    for i in range(bulletspro_num // 2):
        # Here (me.rect.centerx - 33, me.rect.center) refers to the tuple position. Centerx represents the x-axis and center represents the y-axis
        bulletspro.append(bullet.Bullet2((me.rect.centerx - 33, me.rect.centery)))
        bulletspro.append(bullet.Bullet2((me.rect.centerx + 33, me.rect.centery)))

    # Initialize and strengthen bullet supply, super bomb supply
    bullet_supply = supply.Bullet_Supply(bg_size)
    bomb_supply = supply.Bomb_Supply(bg_size)
    # Set the invincible time event, pyGame Userevent stands for event 1, pyGame Userevent + 1 represents event 2, and so on. Here is equivalent to defining an event
    invincible_event = pygame.USEREVENT
    # Set supply time event
    bullet_time_supply = pygame.USEREVENT + 1
    # Set the enhanced bullet timer event, that is, the enhanced bullet buff duration event
    bulletpro_time = pygame.USEREVENT + 2
    # Set the timer to issue a supply every 8 seconds
    pygame.time.set_timer(bullet_time_supply, 8 * 1000)

    # Mark whether to use super bullet
    is_double_bullet = False

    # Players have three lives
    life_num = 3
    life_image = pygame.image.load('images/life.png').convert_alpha()
    life_rect = life_image.get_rect()
    # Number of super bombs players have
    bomb_num = 3
    # Draw super bomb
    bomb_image = pygame.image.load('images/bomb.png').convert_alpha()
    # Super bomb picture location
    bomb_rect = bomb_image.get_rect()
    # Number of bomb super fonts
    bomb_font = pygame.font.Font('font/font.ttf', 48)


    # The game is suspended. The default is non suspended
    paused = False
    # Pause picture
    pause_nor_image = pygame.image.load('images/pause_nor.png').convert_alpha()
    pause_pressed_image = pygame.image.load('images/pause_pressed.png').convert_alpha()
    # Continue picture
    resume_nor_image = pygame.image.load('images/resume_nor.png').convert_alpha()
    resume_pressed_image = pygame.image.load('images/resume_pressed.png').convert_alpha()
    # Set default picture
    paused_image = pause_nor_image
    # Pause button position
    paused_rect = pause_nor_image.get_rect()
    paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10


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

    # Game score
    score = 0
    # Set the player score Font style and create a Font object from a Font file
    score_font = pygame.font.Font('font/font.ttf', 36)

    # 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
            elif event.type == invincible_event:
                # Disarm invincible state
                me.invincible = False
                pygame.time.set_timer(invincible_event, 0)
            # Trigger supply event
            elif event.type == bullet_time_supply:
                # Make a random judgment. If it is True, issue enhanced bullet supply
                if choice([True, False]):
                    # Issue enhanced bullet supply
                    bullet_supply.reset()
                else:
                    # Distribute super bomb supplies
                    bomb_supply.reset()
            # Strengthen bullet buff to time event
            elif event.type == bulletpro_time:
                # Bullet switch to normal bullet
                is_double_bullet = False
                # The event stops the cycle and waits for the next trigger
                pygame.time.set_timer(bulletpro_time, 0)
            # Capture key operation
            elif event.type == KEYDOWN:
                # If the space is pressed, a big move will be triggered, and the super bomb will empty the aircraft in the screen
                if event.key == K_SPACE:
                    if bomb_num > 0:
                        bomb_num -= 1
                        # Judge whether all enemy planes present are in the game screen
                        for ei in enemiesGroup:
                            if ei.rect.bottom > 0:
                                ei.active = False
            # Mouse movement event
            elif event.type == MOUSEMOTION:
                # Move the mouse into the suspended rectangular box to detect whether the mouse is in the rectangle. If yes, return True; otherwise, return false; POS – is the mouse position
                if paused_rect.collidepoint(event.pos):
                    # If suspended
                    if paused:
                        paused_image = resume_pressed_image
                    else:
                        paused_image = pause_pressed_image
                else:
                    if paused:
                        paused_image = resume_nor_image
                    else:
                        paused_image = pause_nor_image
            # Click the pause button with the left mouse button
            elif event.type == MOUSEBUTTONDOWN:
                # If it is the left button and the mouse click position is in the pause box
                if event.button == 1 and paused_rect.collidepoint(event.pos):
                    # Switch pause state
                    paused = not paused
                # If you click the pause button, the game is suspended
                if paused:
                    # Draw pause button picture
                    paused_image = resume_pressed_image
                    # Pause supply timer
                    pygame.time.set_timer(bullet_time_supply, 0)
                # If you click the pause button, the game continues
                else:
                    # Draw continue button picture
                    paused_image = pause_pressed_image
                    # Resupply timer
                    pygame.time.set_timer(bullet_time_supply, 8 * 1000)


        # 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, enemy aircraft, player aircraft and other elements
        # Not paused and life greater than 0
        if paused == False and life_num > 0:
            # Draw bullet supply. If the bullet supply status is true, the bullet supply operation will be triggered
            if bullet_supply.active:
                # The bullet starts moving and renders the picture of bullet supply
                bullet_supply.move()
                screen.blit(bullet_supply.image, bullet_supply.rect)
                # If it collides with the player's aircraft during the falling process, it means that the player's aircraft has picked up bullet supplies
                # pygame.sprite.collide_mask: pixel mask detection between two sprites. It receives two sprites as parameters, and the return value is a bool variable
                if pygame.sprite.collide_mask(bullet_supply, me):
                    # Change the supply status of bullets, including hiding and can no longer be picked up
                    bullet_supply.active = False
                    # Aircraft bullets become reinforced bullets
                    is_double_bullet = True
                    # Set the enhanced bullet buff duration event, which lasts for 4s
                    pygame.time.set_timer(bulletpro_time, 4 * 1000)

            # Draw super bomb supply. If the super bomb status is true, the super bomb supply operation will be triggered
            if bomb_supply.active:
                # The super bomb supply starts moving and renders the supply picture
                bomb_supply.move()
                screen.blit(bomb_supply.image, bomb_supply.rect)
                # Player aircraft picked up supplies
                if pygame.sprite.collide_mask(bomb_supply, me):
                    # Change the supply status, including hiding and no longer picking
                    bomb_supply.active = False
                    # Judge the number of super bombs, which cannot be greater than 3
                    if bomb_num < 3:
                        bomb_num += 1



            # 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
                        # Its choice will be reborn here
                        if e1_destory_index == 0:
                            ei.reset()
                            score += 100

            # 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)

            # One bullet is fired every 10 units of time
            if not(delay % 10):
                # If it's an ordinary bullet
                if is_double_bullet == False:
                    bullets = bullet1s
                    # Locate bullet 0 first
                    bullets[bullet1s_index].reset(me.rect.midtop)
                    # Switch to the next bullet
                    bullet1s_index = (bullet1s_index + 1) % bullet1_num
                # If it's a super bullet
                else:
                    # Then the bullet is switched to reinforced bullet
                    bullets = bulletspro
                    # The logic of resetting the position of left and right strengthening bullets is actually the same as that of ordinary bullets, but the position has changed
                    bullets[bulletspro_index].reset((me.rect.centerx - 33, me.rect.centery))
                    bullets[bulletspro_index + 1].reset((me.rect.centerx + 33, me.rect.centery))
                    # Switch to the next group of bullets
                    bulletspro_index = (bulletspro_index + 2) % bulletspro_num


            # Draw bullets
            for bul in bullets:
                if bul.active:
                    # If the bullet is active, it can move and draw
                    bul.move()
                    screen.blit(bul.image, bul.rect)
                    # The collision between bullets and enemy aircraft and between bullets and enemy aircrew is actually a 1-to-1 collision under normal circumstances
                    enemy_hit = pygame.sprite.spritecollide(bul, enemiesGroup, False, pygame.sprite.collide_mask)
                    # If there are enemy planes hit by bullets
                    if enemy_hit:
                        # The bullet that hit the enemy aircraft is marked as inactive first. The next time it circulates to this bullet, it will actually reset and be displayed again
                        bul.active = False
                        for ei in enemy_hit:
                            ei.active = False

            # Draw fractional text, pyGame font. Font. Render (): draws text on a new Surface object
            # pygame.font.Font.render(text, antialias, color, background=None)
            # Text: text to display antialias: when True, the text image is smoother, and when False, the text image is jagged
            # Color: font color background: background color (optional parameter). The default is small black screen
            score_text = score_font.render('Score : %s' % str(score), True, WHITE)
            screen.blit(score_text, (10, 5))

            # Draw super bomb pictures and quantity display
            bomb_text = bomb_font.render('* %d' % bomb_num, True, WHITE)
            bomb_text_rect = bomb_text.get_rect()
            screen.blit(bomb_image, (10, height - 10 - bomb_rect.height))
            screen.blit(bomb_text, (bomb_rect.width + 20, height - 5 - bomb_text_rect.height))

            # Draw player's remaining life
            if life_num > 0:
                for i in range(life_num):
                    screen.blit(life_image, (width - 10 - (i+1)*life_rect.width, height - 10 - life_rect.height))


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

        # Draw pause button picture
        screen.blit(paused_image, paused_rect)
        # 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()

Topics: Python Game Development