There are many kinds of aircraft wars, but those are not familiar enough. Today, let's have a wechat aircraft war of the same type.
1, Software and modules used
1. Software
Python
pycharm
2. Module
pygame
sys
os
random
Import module
import pygame import sys import os import random
Path address of material file
source_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'material_images')
Initialize pygame
pygame.init() pygame.display.init() pygame.font.init()
Simple encapsulation of upper, lower, left and right variables
class Direction(): UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4
Mixin class that displays aircraft self destruction animation, which can be used for self destruction animation display of aircraft and enemy aircraft
class DestroyAnimationMixin(): def show_destroy_animation(self, time_passed, destroy_time=200): ''' Show self destruct animation Animation is actually a few pictures that switch quickly. Our eyes can't recognize it, so we think it is dynamic, that is, animation :param time_passed: Time since the last image was drawn, in ms :param destroy_time: Total display time of self destruction animation, unit ms '''
Because we have four self destruct pictures, which need to be displayed in turn. First, the effect of animation
self.destroy_image_position refers to the self destruction picture in the chapter, starting from scratch
If it is greater than or equal to 4, the self destruction animation display is completed. Set the self.destroyed variable to True for easy calling elsewhere
if self.destroy_image_position >= 4: self.destroyed = True return
Load self destruct pictures in turn
if self.time_passed >= destroy_time / 4: self.image = pygame.image.load(os.path.join(source_dir, self.destroy_images[self.destroy_image_position])).convert_alpha() self.destroy_image_position += 1 self.time_passed = 0 else: self.time_passed += time_passed
The enemy aircraft class inherits DestroyAnimationMixin to facilitate the use of functions that display self destruction animation
class Enemy(DestroyAnimationMixin): def __init__(self, image_path=os.path.join(source_dir, 'enemy1.png'), speed=2000, background_size=(480, 700)): ''' :param image_path: Enemy picture address :param speed: Time required for enemy aircraft to move the whole window, unit ms,That is, speed :param background_size: Size of the game window ''' self.image = pygame.image.load(image_path).convert_alpha() self.speed = background_size[1] / speed self.background_size = background_size self.position = [random.randint(0, background_size[0]-self.image.get_size()[0]), -self.image.get_size()[1]] # Start self destruction self.start_destroy = False # Self destruction complete self.destroyed = False # Self destruct picture path self.destroy_images = ['enemy1_down1.png', 'enemy1_down2.png', 'enemy1_down3.png', 'enemy1_down3.png'] # Time since the last image was drawn self.time_passed = 0 # Self destruction picture in self.destroy_ Location of images self.destroy_image_position = 0 def update(self, time_passed): ''' Update the enemy's position :param time_passed: Time since the last image was drawn :return: ''' # If the enemy plane runs out of the game window, set self.position[1] = -100 to facilitate use in other locations if self.position[1] >= self.background_size[1]: self.position[1] = -100 return # If you start self destruction, call the self destruction function to display the animation. If not, change the position if self.start_destroy: self.show_destroy_animation(time_passed) else: self.position[1] += self.speed * time_passed
Aircraft bullets
class Bullet(): def __init__(self, image_path=os.path.join(source_dir,'bullet.png'), background_size=(480, 700), plan=None, speed=1000): ''' :param image_path: Picture address of bullet :param background_size: Game window size :param plan: Aircraft object :param speed: Missle Velocity ''' self.image = pygame.image.load(image_path).convert_alpha() self.background_size = background_size self.speed = background_size[1] / speed # Did the bullet hit the enemy plane self.destroyed = False self.position = self._get_position(plan) def _get_position(self, plan): ''' according to plan Get the location of the bullet :param plan: Aircraft object ''' bullet_size = self.image.get_size() plan_width = plan.image_size[0] x = (plan_width-bullet_size[0]) / 2 return [plan.position[0] + x, plan.position[1]] def update(self, time_passed): ''' Change bullet position :param time_passed: Time since the last image was drawn ''' # If the bullet exceeds the screen or hits the enemy plane, set self.position[1] to - 100 and remove it when planning.draw if self.position[1] + self.image.get_size()[1] <= 0 or self.destroyed: self.position[1] = -100 return # Distance changed = time * rate self.position[1] -= time_passed * self.speed
The aircraft class inherits DestroyAnimationMixin, which is convenient to use the function of displaying self destruction animation
Aircraft picture address
class Plan(DestroyAnimationMixin): def __init__(self, image_path=os.path.join(source_dir,'plan.png'), background_size=(480, 700)): ''' :param image_path: :param background_size: Game window size ''' self.background_size = background_size self.image = pygame.image.load(image_path).convert_alpha() self.image_size = self.image.get_size() self.position = [(background_size[0]-self.image_size[0]) / 2, 500] # Distance per movement of the aircraft self.every_time_move_distance = 0.5 # Aircraft bullets self.bullets = [] # destroy association attributes # Start self destruction self.start_destroy = False # End of self destruction self.destroyed = False # Self destruct picture self.destroy_images = ['me_destroy_1.png', 'me_destroy_2.png', 'me_destroy_3.png', 'me_destroy_4.png'] # Self destruct picture location self.destroy_image_position = 0 # Time since the last image was drawn self.time_passed = 0
Update aircraft position
def update(self, direction): ''' :param direction: Aircraft movement direction ''' if direction == 1: if self.position[1] <= 0: return self.position[1] -= self.every_time_move_distance elif direction == 2: if self.position[1] + self.image_size[1] >= self.background_size[1]: return self.position[1] += self.every_time_move_distance elif direction == 3: if self.position[0] <= 0: return self.position[0] -= self.every_time_move_distance else: if self.position[0] + self.image_size[0] >= self.background_size[0]: return self.position[0] += self.every_time_move_distance
The plane fired bullets
def shut(self, image_path=os.path.join(source_dir,'bullet.png')): ''' :param image_path: Bullet picture ''' bullet = Bullet(image_path, plan=self) self.bullets.append(bullet)
Draw all the bullets in the plane
def draw_bullets(self, time_passed, screen): ''' :param time_passed: Time since the last image was drawn :param screen: To which window ''' # Clean up the missing bullets for bullet in self.bullets: if bullet.position[1] == -100: self.bullets.remove(bullet) # Update the position of each bullet for bullet in self.bullets: bullet.update(time_passed) # Draw each bullet for bullet in self.bullets: screen.blit(bullet.image, bullet.position)
param background_image_path: the path address of the background picture
param size: the size of the game window
param title: the title of the game window
param font_name: specify font
param font_size: Specifies the font size
param speed: the time taken by the background image to scroll the whole window once, in ms
class Game(): def __init__(self, background_image_path, size=(480, 700), title='Aircraft war', font_name='Fangzheng shutI', font_size=30, speed=2000): self.size = size self.screen = pygame.display.set_mode(size) self.title = title self.background_image_path = background_image_path self.background = pygame.image.load(self.background_image_path).convert() # Set the font object to get the font in the system self.font = pygame.font.SysFont(font_name, font_size) # Get the Clock object, which we can use to get the time since the last image was drawn self.clock = pygame.time.Clock() # Initial position of background image self.height = 0 # Using the height of the window in the scrolling time, you can get the scrolling distance per ms self.every_ms_move_distance = self.size[1] / speed # 2 seconds # fraction self.score = 0 # Store all enemy aircraft self.enemies = []
The score is displayed. It is 10px above the top of the window, centered left and right.
def show_score(self): # Enable zigzag mode font color background color score = self.font.render(f'score : {self.score} ', True, (0,0,0), (255,255,255)) score_position_x = (self.size[0]-score.get_size()[0]) / 2 score_position_y = 10 self.screen.blit(score, (score_position_x, score_position_y))
Controls the frame of the drawing
def set_time_passed(self): # Control the frame drawn, the larger the faster # self.clock.tick(1000) # Get the time from the last drawn image to the present, ms self.time_passed = self.clock.tick()
Draw the background picture and scroll down to create the feeling of the plane flying up all the time
def draw_background(self): # Distance per move = distance per ms * time from last time to present (ms) move_distance = self.every_ms_move_distance * self.time_passed self.height += move_distance # If the height of the window is exceeded, reset the height to zero if self.height >= self.size[1]: self.height = 0 # The two background images are displayed together to create an uninterrupted rolling effect of the background image self.screen.blit(self.background, (0, -self.size[1] + self.height)) self.screen.blit(self.background, (0, self.height))
Create enemy aircraft
def create_enemy(self, image_path=os.path.join(source_dir,'enemy1.png'), enemy_number=5): ''' :param image_path: Picture address of enemy aircraft :param enemy_number: How many enemy planes are on the screen at most ''' if len(self.enemies) >= enemy_number: return enemy = Enemy(image_path=image_path) self.enemies.append(enemy)
Draw the enemy plane on the screen and clean up the enemy plane running out of the window.
def draw_enemies(self, time_passed, screen): ''' :param time_passed: The time elapsed since the last guide was drawn :param screen: Drawn window object ''' # Clear enemy planes out of range for enemy in self.enemies: # When the enemy plane runs out of range, it sets enemy.position[1] to - 100, so we judge here that enemy.position[1]==-100 is the enemy plane running out of range # enemy.destroyed is True, which means that the enemy plane is hit by bullets and needs to clean up this enemy if enemy.position[1] == -100 or enemy.destroyed: self.enemies.remove(enemy) # Update enemy position for enemy in self.enemies: # Call the update method of each enemy aircraft to change the position of the enemy aircraft enemy.update(time_passed) # Draw enemy aircraft for enemy in self.enemies: # Draw the enemy plane according to its position screen.blit(enemy.image, enemy.position)
Detect whether the bullet hit the enemy plane
def bullet_and_enemy_crash_detection(self, bullets): ''' :param bullets: All the bullets in the plane ''' for bullet in bullets: # Traverse every bullet for enemy in self.enemies: # Traverse each enemy aircraft to determine whether it has been hit if bullet.position[0] >= enemy.position[0] and bullet.position[0] <= enemy.position[0]+enemy.image.get_size()[0]: if bullet.position[1] >= enemy.position[1] and bullet.position[1] <= enemy.position[1] + enemy.image.get_size()[1]: # If hit, the enemy plane begins to destroy itself enemy.start_destroy = True # The bullet destroyed itself and disappeared bullet.destroyed = True # Score plus one self.score += 1
Detect whether the enemy aircraft collided with the aircraft
def plan_and_enemy_crash_detection(self, plan, allow_crash_size=None): ''' :param plan: Aircraft object :param allow_crash_size: The allowable size of aircraft collision is only valid on the left and right ''' # If this parameter is not passed in, it is assigned as 10% of the aircraft width if allow_crash_size is None: allow_crash_size = 0.1 * plan.image_size[0] for enemy in self.enemies: # Traverse each enemy aircraft to detect whether it collides if enemy.position[0]+enemy.image.get_size()[0] - allow_crash_size >= plan.position[0] and enemy.position[0] <= plan.position[0]+plan.image.get_size()[0] - allow_crash_size: if enemy.position[1] + enemy.image.get_size()[1] >= plan.position[1] and enemy.position[1] <= plan.position[1] + plan.image.get_size()[1]: # A collision was detected and the plane began to self destruct plan.start_destroy = True
Drawing aircraft
def draw_plan(self, plan, time_passed): ''' :param plan: Aircraft object :param time_passed: Time since last drawing :return: ''' # If the aircraft starts to self destruct, call the self destruct function to display the self destruct animation if plan.start_destroy: plan.show_destroy_animation(time_passed, destroy_time=1000) self.screen.blit(plan.image, plan.position)
game over
def game_over(self): while True: # Draw background map self.set_time_passed() self.draw_background() text = self.font.render(f'Game over, score : {self.score} ', True, (0, 0, 0), (255, 255, 255)) text_position_x = (self.size[0] - text.get_size()[0]) / 2 text_position_y = (self.size[1] - text.get_size()[1]) / 2 self.screen.blit(text, (text_position_x, text_position_y)) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() pygame.display.update()
Game entry function, start function
def run(self): ''' :return: ''' # Set the size of the game window pygame.display.set_caption(self.title) # Initialize an aircraft object plan = Plan() while True: # If the plane self destructs and the game is over, call game_over function if plan.destroyed: self.game_over() break # Detect listening events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() # If the user's spacebar pops up, it means that the user has pressed the spacebar and fired a bullet elif event.type == pygame.KEYUP: if event.key == pygame.K_SPACE: # Call the plan.shut function plan.shut() # Detect up, down, left and right moving cases # w. A, s, D and up, down, left and right buttons are OK # Then execute the plan.update function to change the position of the aircraft key_pressed = pygame.key.get_pressed() if key_pressed[pygame.K_w] or key_pressed[pygame.K_UP]: plan.update(direction=Direction.UP) elif key_pressed[pygame.K_s] or key_pressed[pygame.K_DOWN]: plan.update(direction=Direction.DOWN) elif key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]: plan.update(direction=Direction.LEFT) elif key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]: plan.update(direction=Direction.RIGHT) # Collision detection between bullets and enemy aircraft self.bullet_and_enemy_crash_detection(plan.bullets) # Collision detection between aircraft and enemy aircraft self.plan_and_enemy_crash_detection(plan) # Set property time_ The value of passed, the time from the last time, is convenient for later use self.set_time_passed() # Draw background picture self.draw_background() # Show score self.show_score() # Generate enemy aircraft self.create_enemy() # Draw enemy aircraft self.draw_enemies(time_passed=self.time_passed, screen=self.screen) # Drawing aircraft self.draw_plan(plan=plan, time_passed=self.time_passed) # Draw bullets plan.draw_bullets(time_passed=self.time_passed, screen=self.screen) # Show our images pygame.display.update()
Background picture address
if __name__ == '__main__': # Background picture address background_image_path = os.path.join(source_dir, 'background.png') game = Game(background_image_path=background_image_path)
Add game.run() to start the game
Brother Meng, have you abandoned your studies?
python welfare tutorial (including the complete source code of this article, the materials to be used in this article, e-books, other video tutorials and answers)
Collection method:
1. Like + comment (check "forward at the same time")
2. Pay attention to Xiaobian. And reply to the keyword [aircraft war] by private letter
(be sure to send a private message ~ click my avatar to see the private message button)