Learn the last project of Python: Airplane war games (pure code)

Keywords: Python pip Mobile Windows

Learn the last project of Python: Airplane war games (pure code)

In ancient times, those who made great achievements must not only have extraordinary talents, but also perseverance. ——Su Shi

Sweet first

This time, pygame module in Python is used to complete a small game of aircraft war; the basic idea is to control the left and right mobile shooting spacecraft of the aircraft through the direction key.

Finished product effect

This post is the complete code of this little game, with complete comments. Another post has a complete process. Portal

Article catalog

Install pygame

To complete this project, you must install the third-party library of pygame. The installation process is as follows

  1. The pip tool that first checks whether the system is installed through the command-line tool

    python -m pip --version
    

    Xiaotian is a Windows system, here only provides the detection method of windows system

  2. Install pip tool if not installed, skip this step

    python get-pip.py
    

    Return to the first step for re inspection after installation

  3. Install pygame

    python -m pip install pygame --user
    

    Or install the third library through pycharm, as follows

  4. Import a third-party library through the import keyword

    import pygame
    

Small aircraft

The file name is plane.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/4
"""


class GameStats:
    """Track game statistics"""

    def __init__(self, setting):

        self.setting = setting
        self.reset_stats()
        # Game is inactive by default
        self.game_active = False

        # Highest score
        self.high_score = 0

    def reset_stats(self):
        # Initialize statistics that may change during the game run
        self.planes_left = self.setting.plane_limit
        # Statistical score
        self.score = 0

ZiDan

The file name is bullet.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/3
"""
import pygame
from pygame.sprite import Sprite


class Bullet(Sprite):  # inherit pygame.sprite Sprite class in
    """Bullet management"""

    def __init__(self, setting, screen, plane):
        super().__init__()
        self.screen = screen
        # Create a rectangle representing the bullet at (0,0)
        # pygame.Rect
        # pygame object for storing rectangular coordinates
        self.rect = pygame.Rect(0,0, setting.bullet_width, setting.bullet_height)
        # Set the location of the display
        self.rect.centerx = plane.rect.centerx
        self.rect.top = plane.rect.top
        # Make the position of the bullet overlap with that of the small plane. When the bullet flies out, it looks like it is shot out of the small plane

        # Convert bullet coordinates to floating-point numbers
        self.y = float(self.rect.y)

        # The color of the bullet
        self.color = setting.bullet_color
        # Bullet speed
        self.speed = setting.bullet_speed

    def update(self):
        # Move the bullet up
        self.y -= self.speed
        # Update according to the value of self.y self.rect.y
        self.rect.y = self.y

    def draw_bullet(self):
        """Draw bullets"""
        # pygame.draw.rect () draw a rectangular shape
        pygame.draw.rect(self.screen, self.color, self.rect)

Enemy human (spacecraft)

The file name is spaceship.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/4
"""
import pygame
from pygame.sprite import Sprite


class Spaceship(Sprite):
    '''Class for spacecraft'''

    def __init__(self, setting, screen):
        super().__init__()
        self.screen = screen
        self.setting = setting

        # Add spaceship image
        self.img = pygame.image.load("./imgs/enemy.png")
        # Get rect property
        self.rect = self.img.get_rect()

        # Each ship was initially near the top left corner of the screen
        self.rect.x = self.rect.width  # The left margin of the spacecraft image is equal to the width of the image

        self.rect.y = self.rect.height  # The top margin of the airship book is equal to the height of the image


        self.rect.w = self.rect.width
        self.rect.h = int(self.rect.height / 2) # Set height to half

        self.x = float(self.rect.x)

    def blitme(self):
        # Drawing spacecraft images
        self.screen.blit(self.img, self.rect)

    def check_edges(self):
        '''If a ship is on the edge of the screen, go back true'''
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right:
            return True
        elif self.rect.left <= 0:
            return True

    def update(self):
        """Mobile spacecraft"""
        self.x += (self.setting.spaceship_speed * self.setting.fleet_direction)
        self.rect.x = self.x

Button class

The file name is button.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/5
"""
import pygame.font


class Button:
    def __init__(self, setting, screen, msg):
        """Initialize button properties"""
        self.screen = screen
        self.screen_rect = screen.get_rect()

        # Set the size of the button
        self.width = 180
        self.height = 50
        # Set button color
        self.button_color = (0, 255, 0)
        # Set the color of the text
        self.text_color = (200, 200, 200)
        # Set font size
        self.font = pygame.font.SysFont("SimHei", 50)  # Font is bold and size is 48 pixels

        # Create rect object for button
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        # Center button
        self.rect.center = self.screen_rect.center

        # The label of the button needs to be created only once
        self.prep_msg(msg)

    def prep_msg(self, msg):
        # msg render as image
        """
        font.render The method is to msg Text to image in
        * parameter True Is anti aliasing on
        * self.text_color Is the color of the text
        * self.button_color Is the background color
        """
        self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
        # Center it on the button
        self.msg_image_rect = self.msg_image.get_rect()
        self.msg_image_rect.center = self.rect.center

    def draw_button(self):
        # Draw button
        self.screen.fill(self.button_color, self.rect)  # Fill text with a color
        self.screen.blit(self.msg_image, self.msg_image_rect)  # Draw text

Record game information

File name is game_stats.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/4
"""


class GameStats:
    """Track game statistics"""

    def __init__(self, setting):

        self.setting = setting
        self.reset_stats()
        # Game is inactive by default
        self.game_active = False

        # Highest score
        self.high_score = 0

    def reset_stats(self):
        # Initialize statistics that may change during the game run
        self.planes_left = self.setting.plane_limit
        # Statistical score
        self.score = 0

Record classification

The file name is scoreboard.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/5
"""
import pygame.font
from pygame.sprite import Group
from plane import Plane


class Scoreboard:
    """Category displaying score information"""

    def __init__(self, setting, screen, stats):
        """Attribute involved in initialization score"""
        self.screen = screen
        self.screen_rect = screen.get_rect()
        self.stats = stats
        self.setting = setting

        # Display font settings for score
        # Set the color of the text
        self.text_color = (250, 250, 250)
        # Set font size
        self.font = pygame.font.SysFont("SimHei", 40)  # Font is bold and size is 40 pixels

        # Initialize score image
        self.prep_score()
        # Initialize highest score image
        self.prep_high_score()

    def prep_score(self):
        """Convert score to image"""
        score_str = str(self.stats.score)
        self.score_image = self.font.render(score_str, True, self.text_color)

        # Put the score in the top right corner of the screen
        self.score_rect = self.score_image.get_rect()
        self.score_rect.right = self.screen_rect.right - 20  # 20 pixels to the right
        self.score_rect.top = 20  # 20 pixels from top

    def prep_high_score(self):
        """Convert score to image"""
        high_score_str = str(self.stats.high_score)
        self.high_score_image = self.font.render(high_score_str, True, self.text_color)

        # Put the score in the middle of the top of the screen
        self.high_score_rect = self.high_score_image.get_rect()
        self.high_score_rect.centerx = self.screen_rect.centerx
        self.high_score_rect.top = 10

    def show_score(self):
        """Show score on screen"""
        self.screen.blit(self.score_image, self.score_rect)
        # Show highest score
        self.screen.blit(self.high_score_image, self.high_score_rect)

Game settings class

The file name is settings.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/3
"""
import pygame
import random


class Settings:
    """Store all settings for aircraft battle"""

    def __init__(self):
        # screen setting
        self.screen_width = 1000
        self.screen_height = 600
        self.bg_img = pygame.image.load("./imgs/bg_img.png")

        #Small aircraft setup
        # Life limitation of small aircraft
        self.plane_limit = 3

        # Bullet setting
        self.bullet_width = 3  # The width of the bullet
        self.bullet_height = 15  # The height of the bullet
        self.bullet_color = 190, 190, 190  # The color of the bullet
        # Limit the number of bullets
        self.bullet_allowed = 5

        # Speed of descent
        self.fleet_drop_speed = 10

        # How to speed up the game
        self.speedup_scale = 1.2

        # Speed up points
        self.score_scale = 1.5

        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        #Small aircraft setup
        # The speed of a small plane
        self.plane_speed = 2.5

        # Bullet setting
        self.bullet_speed = 3  # speed

        # The speed of the ship's movement
        self.spaceship_speed = 2

        # Flag bit, 1 for right - 1 for left
        self.fleet_direction = 1  # Default move right


        self.spaceship_points = 15

    def increase_speed(self):
        """Improve game rhythm"""
        self.plane_speed *= self.speedup_scale
        self.bullet_speed *= self.speedup_scale
        self.spaceship_speed *= self.speedup_scale

        # Increase the ship's score
        self.spaceship_points = int(self.spaceship_points * self.score_scale)

All functions of the game

File name is game_func.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/3
"""
import sys
from bullet import Bullet
from spaceship import Spaceship
import pygame
from time import sleep


def check_keydown_events(event, plane, setting, screen, bullets):
    # Capture user press
    if event.key == pygame.K_RIGHT:
        # Flag bit is True when the user presses the key
        plane.mv_right = True
    elif event.key == pygame.K_LEFT:
        plane.mv_left = True
    elif event.key == pygame.K_SPACE:
        if len(bullets) <= setting.bullet_allowed:
            # Create a bullet and add it to the group bullets
            new_bullet = Bullet(setting, screen, plane)
            bullets.add(new_bullet)


def check_keyup_events(event, plane):
    # Capture user release
    if event.key == pygame.K_RIGHT:
        # When the user releases the key, it is false
        plane.mv_right = False
    elif event.key == pygame.K_LEFT:
        plane.mv_left = False


def check_events(plane, setting, screen, bullets, stats, play_button, spaceships, score_board):
    # In order to prevent the game window from closing immediately, add a game loop (infinite loop),
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  # QUIT user requests program shutdown
            sys.exit()

        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, plane, setting, screen, bullets)

        elif event.type == pygame.KEYUP:
            check_keyup_events(event, plane)

        elif event.type == pygame.MOUSEBUTTONDOWN:  # Detect MOUSEBUTTONDOWN event
            mouse_x, mouse_y = pygame.mouse.get_pos()  # Returns a tuple containing the coordinates of the mouse click
            check_play_button(plane, setting, screen, bullets, stats, play_button, mouse_x, mouse_y, spaceships, score_board)


def check_play_button(plane, setting, screen, bullets, stats, play_button, mouse_x, mouse_y, spaceships, score_board):
    # Start the game when the player has a single play button
    # Collidedpoint detects whether the click position is within the rect of the button
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    if button_clicked and not stats.game_active:  # When stats.game_ If the value of active is False, negation will be executed
        # Reset all images scored
        score_board.prep_score()
        score_board.prep_high_score()
        # Reset game settings
        setting.initialize_dynamic_settings()
        # hide cursor
        pygame.mouse.set_visible(False)
        # Game state
        stats.game_active = True
        # Reset game statistics
        stats.reset_stats()

        # Clear ship list and bullet list
        spaceships.empty()
        bullets.empty()

        # Center the plane
        plane.center_plane()


def update_screen(screen, bg_img, plane, bullets, spaceships, stats, play_button, score_board):
    # Update image of screen
    # Each cycle redraws the screen
    screen.blit(bg_img, [0, 0])  # Drawing an image
    # Draw bullets
    for bullet in bullets.sprites():
        bullet.draw_bullet()  # Draw bullets
    # Drawing an airplane
    plane.blitme()
    for spaceship in spaceships.sprites():
        spaceship.blitme()

    # Show score
    score_board.show_score()

    # If the game is inactive, draw the Play button
    if not stats.game_active:
        play_button.draw_button()


    # Update the full display Surface to the screen
    pygame.display.flip()


def update_bullets(bullets, spaceships, setting, screen, plane, stats, score_board):
    # Call each bullet in the group bullet.update()
    bullets.update()
    # Delete bullets that have disappeared
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)


    collisions = pygame.sprite.groupcollide(bullets, spaceships, True, True)  # Two arguments true are used to delete them
    """The key in this dictionary is to hit the bullets of small and medium-sized ships, and the value is a list, which contains all the hit values"""

    if collisions:  # When there is a collision, there will be a return value, which will be True
        for spaceship in collisions.values():
            """Go through the dictionary and make sure that every alien's point counts"""
            stats.score += setting.spaceship_points * len(spaceship) # Bonus points in case of collision
            """Because the value of the bullet is a list, the length of the list is calculated to add points"""
            score_board.prep_score()  # And draw on the screen
        check_high_score(stats, score_board)

    if len(spaceships) == 0:
        bullets.empty()  # Delete all sprites (bullets) in the group
        # Speed up the game
        setting.increase_speed()
        create_fleet(setting, screen, spaceships, plane)  # Recall build spacecraft


def get_number_spaceship_x(setting, spaceship_width):
    # A function to calculate how many aliens each row can hold
    # Calculate the width that can accommodate multiple spacecraft
    available_space_x = setting.screen_width - (2 * spaceship_width)
    number_spaceship_x = int(available_space_x / (2 * spaceship_width))  # Convert it to an integer
    return number_spaceship_x


def get_number_rows(setting, plane_height, spaceship_height):
    # Calculate how many rows can be accommodated
    available_space_y = setting.screen_height - 7 * spaceship_height - plane_height
    number_rows = int(available_space_y / spaceship_height)
    return number_rows


def create_spaceship(setting, screen, spaceships, spaceship_number, number_rows):
    # Create a spaceship and join the current line
    spaceship = Spaceship(setting, screen)
    spaceship_width = spaceship.rect.width  # The width of the spacecraft
    spaceship.x = spaceship_width + 2 * spaceship_width * spaceship_number
    spaceship.rect.x = spaceship.x
    spaceship.rect.y = spaceship.rect.height + 2 * spaceship.rect.height * number_rows
    spaceships.add(spaceship)


def create_fleet(setting, screen, spaceships, plane):
    # Create a spaceship
    spaceship = Spaceship(setting, screen)
    number_spaceship_x = get_number_spaceship_x(setting, spaceship.rect.width)
    number_rows = get_number_rows(setting, plane.rect.height, spaceship.rect.height)

    for row_number in range(number_rows):
        for spaceship_number in range(number_spaceship_x):
            # if stats.game_active:  # Only for the truth can we create a spaceship
            create_spaceship(setting, screen, spaceships, spaceship_number, row_number)


def change_fleet_direction(setting, spaceships):
    """Move all ships down and change direction"""
    for spaceship in spaceships.sprites():
        spaceship.rect.y += setting.fleet_drop_speed
    setting.fleet_direction *= -1  # - 1 if 1, 1 if - 1


def check_fleet_edges(setting, spaceships):
    """Measures to be taken when a spaceship reaches the edge"""
    for spaceship in spaceships.sprites():
        if spaceship.check_edges():  # If it is true, the edge is reached, and change is executed_ fleet_ direction
            change_fleet_direction(setting, spaceships)
            break


def plane_hit(setting, spaceships, plane, stats, screen, bullets):
    """
    //After a spaceship hit the aircraft, the number has been reduced by 1, a batch of new flying creations have been created, and the aircraft has been restored to the original position of the screen
    //The sleep function of time module will also be introduced to achieve the effect of pause
    """
    if stats.planes_left > 0:
        stats.planes_left -= 1  # Place_ Left minus 1
        # print(stats.planes_left)

        # Clear the formation of the ship and the bullets
        spaceships.empty()
        bullets.empty()

        # Create new aircraft and spacecraft
        create_fleet(setting, screen, spaceships, plane)
        plane.center_plane()

        sleep(1)  # Pause for 1 second
    else:
        stats.game_active = False
        # Set cursor to display
        pygame.mouse.set_visible(True)

def check_spaceship_bottom(setting, spaceships, plane, stats, screen, bullets):
    # Check if any spacecraft touches the bottom
    screen_rect = screen.get_rect()
    for spaceship in spaceships.sprites():
        if spaceship.rect.bottom >= screen_rect.bottom:
            # Deal with it like a collision
            plane_hit(setting, spaceships, plane, stats, screen, bullets)


def update_spaceships(setting, spaceships, plane, stats, screen, bullets):
    # Update the position of the spacecraft
    spaceships.update()
    # At the time of detection, the spaceship is on the edge and updated in time
    check_fleet_edges(setting, spaceships)

    # Detect direct collision between spacecraft and aircraft
    '''
    pygame.sprite.spritecollideany method
    * It takes two parameters, a sprite and a group,
    * Detect whether the members in the group collide with each other, and stop traversing the group if collision is detected
    * Return if no collision occurs None
    '''
    game_over = pygame.sprite.spritecollideany(plane, spaceships)
    if game_over:
        plane_hit(setting, spaceships, plane, stats, screen, bullets)

    # Check if there is a spaceship landing
    check_spaceship_bottom(setting, spaceships, plane, stats, screen, bullets)


def check_high_score(stats, score_board):
    """Used to detect whether the highest score is generated"""
    if stats.score > stats.high_score:
        stats.high_score = stats.score  # If the score of is greater than the highest score, the value is assigned to the highest score
        score_board.prep_high_score()

The beginning of the game

File name is plane_war.py

"""
-*- coding:uft-8 -*-
author: Xiaotian
date:2020/6/3
"""
import pygame
from settings import Settings  # introduce settings.py
from plane import Plane
import game_func as fg
from pygame.sprite import Group
from game_stats import GameStats
from button import Button
from scoreboard import Scoreboard



def run_game():
    # Initialize game
    pygame.init()
    # Set screen resolution
    setting = Settings()
    screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))  # Size 1000px multiplied by 600px
    pygame.display.set_caption("Aircraft battle")  # title
    # Create play button
    play_button = Button(setting, screen, "Play")
    # Create an instance to store game statistics
    stats = GameStats(setting)
    # Create an instance of scoring
    score_board = Scoreboard(setting, screen, stats)
    # Create a small plane
    plane = Plane(screen, setting)
    # Create a group to store bullets
    bullets = Group()
    # Create a spaceship group
    spaceships = Group()

    # Start the main cycle of the game
    while True:
        # Do not close window
        fg.check_events(plane, setting, screen, bullets, stats, play_button, spaceships, score_board)
        if stats.game_active:  # Judge whether to create an image according to the game status
            # Call the method of small aircraft moving
            plane.update()
            # Update bullet position
            fg.update_bullets(bullets, spaceships, setting, screen, plane, stats, score_board)
            # Update ship position
            fg.update_spaceships(setting, spaceships, plane, stats, screen, bullets)
        # Drawing an image
        fg.update_screen(screen, setting.bg_img, plane, bullets, spaceships, stats, play_button, score_board)


run_game()

Sweet has something to say

Finally, this small project has been completed. It's very difficult to learn the pygame module used here at the same time. Anyway, it's finally out

Now take a few days off and start learning about reptiles

Motto: don't choose ease at the age of struggle!!

Posted by liamthebof on Fri, 05 Jun 2020 19:36:14 -0700