您的位置:首页 > 编程语言 > Python开发

Python实现飞机大战-第二部分(附源码、素材、超详细教程)

2020-07-14 21:22 246 查看

飞机大战第二部分

  • 3.敌方飞机
  • 4.射杀敌机
  • 5.游戏结束
  • 1.前言

    第二部分:飞机射击、子弹、和敌方飞机。

    第一部分的实现过程点击下方链接
    Python实现飞机大战-第一部分(附源码、素材、超详细教程)

    2.飞机射击

    实现飞机射击,首先需要有子弹,为了方便后期对子弹的长度、宽度、颜色和速度的改变,需要在settings.py内添加子弹这些信息。紧接着创建一个Bullet类,用来存放子弹的属性和方法。

    2.1.添加子弹的相关设置

    为了方便设置,在Settings类中添加子弹信息的相关设置,速度、长度、宽度、颜色。

    settings.py

    class Settings():
    '''游戏设置的类'''
    def __init__(self):
    --跳过其他代码--
    '''子弹设置'''
    # 子弹速度
    self.bullet_speed = 1.5
    # 子弹宽度
    self.bullet_width = 3
    # 子弹高度
    self.bullet_height = 10
    # 子弹颜色
    self.bullet_color = 0, 0, 255
    2.2.创建文件bullet.py
    import pygame
    from pygame.sprite import Sprite
    
    class Bullet(Sprite):
    '''控制子弹射击的类'''
    def __init__(self, player_settings, screen, player_plane):
    # super()函数,既可以继承父类的所有属性、方法,又可添加或重写父类的方法、属性。
    super().__init__()
    self.screen = screen
    # 创建矩形
    self.rect = pygame.Rect(0, 0, player_settings.bullet_width, player_settings.bullet_height)
    # 子弹的centerx = 飞机的centerx 目的是让子弹从飞机的top发出
    self.rect.centerx = player_plane.rect.centerx
    self.rect.top = player_plane.rect.top
    # 子弹图像的矩形方框的位置
    self.y = float(self.rect.y)
    # 子弹的速度
    self.bullet_speed = player_settings.bullet_speed
    # 子弹的颜色
    self.bullet_color = player_settings.bullet_color
    
    def update(self):
    '''子弹自动上移'''
    # 原理是让子弹的矩形图像的y左边每次刷新都减去子弹的速度
    self.y -= self.bullet_speed
    # 更新当前坐标
    self.rect.y = self.y
    def draw_bullet(self):
    '''绘制子弹'''
    pygame.draw.rect(self.screen, self.bullet_color, self.rect)
    2.3.修改game_functions.py

    用空格键控制飞机发射子弹,需要修改check_keyboard函数,和update_screen函数

    --省略部分代码--
    from bullet import Bullet
    
    def check_keyboard(players_plane, screen, player_settings, bullets):
    
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    sys.exit()
    # KEYDOWN检测键盘是否按下
    elif event.type == pygame.KEYDOWN:
    --省略部分代码--
    # 空格是否按下
    elif event.key == pygame.K_SPACE:
    print("空格键按下")
    new_bullet = Bullet(player_settings, screen, players_plane)
    bullets.add(new_bullet)
    --省略部分代码--
    def update_screen(player_settings,players_plane, screen, bullets):
    --省略部分代码--
    for bullet in bullets.sprites():
    bullet.draw_bullet()
    2.4.修改mian.py
    def start_game():
    --省略部分代码--
    # 用于存放子弹
    bullets = Group()
    while True:
    '''游戏主循环'''
    # 调用文件game_functions内的check_keyboard函数,是一个响应键鼠的函数
    game_functions.check_keyboard(players_plane, screen, player_settings, bullets)
    players_plane.change_position()
    bullets.update()
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings, players_plane, screen, bullets)
    2.5.射击效果

    2.6.关于子弹连发

    子弹连发的原理其实和飞机连续移动的原理相同。不过效果好像不是那么理想,看一下。

    简单解释一下,代码一共需要修改五个地方:

    1. 在Plane类中添加一个射击标志。
    class Plane():
    
    '''玩家的飞机的类'''
    def __init__(self, screen, player_settings):
    --省略部分代码--
    self.sign_launch = False
    1. 在game_functions.py中添加一个控制射击的方法launch_bullet()。
    def launch_bullet(players_plane, screen, player_settings, bullets):
    if  players_plane.sign_launch:
    new_bullet = Bullet(player_settings, screen, players_plane)
    bullets.add(new_bullet)
    1. 空格按下修改射击标志的布尔值为True。
    elif event.type == pygame.KEYDOWN:
    --省略部分代码--
    elif event.key == pygame.K_SPACE:
    print("空格键按下")
    players_plane.sign_launch = True
    1. 空格松开修改射击标志的布尔值为Flase。
    elif event.type == pygame.KEYUP:
    --省略部分代码--
    elif event.key == pygame.K_SPACE:
    print("空格键松开")
    players_plane.sign_launch = False
    1. 在main.py中调用控制射击的方法launch_bullet()
    while True:
    '''游戏主循环'''
    # 调用文件game_functions内的check_keyboard函数,是一个响应键鼠的函数
    game_functions.check_keyboard(players_plane, screen, player_settings, bullets)
    game_functions.launch_bullet(players_plane, screen, player_settings, bullets)
    players_plane.change_position()
    bullets.update()
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings, players_plane, screen, bullets)

    效果不是太好,小伙伴们有更好的方法,欢迎不吝赐教。

    2.6 删除已消失子弹

    创建的子弹被存放在Group()当中,当子弹到达屏幕的顶端,实际上子弹依旧存在于Group,只不过是超出屏幕范围无法绘制它们。为了避免计算做这些无用功,就需要把超出屏幕的子弹删除。

    2.6.1.创建函数delete_bullet()

    game_functions.py中新建一个删除子弹的函数

    def delete_bullet(bullets):
    '''删除超出屏幕的子弹'''
    bullets.update()
    
    for bullet in bullets.copy:
    if bullet.rect.bottom <= 0:
    bullets.remove(bullet)

    main.py
    调用函数delete_bullet()

    while True:
    '''游戏主循环'''
    # 调用文件game_functions内的check_keyboard函数,是一个响应键鼠的函数
    game_functions.check_keyboard(players_plane, screen, player_settings, bullets)
    #game_functions.launch_bullet(players_plane, screen, player_settings, bullets)
    players_plane.change_position()
    
    # 刷新子弹位置,子弹超出屏幕后将其删除。
    game_functions.delete_bullet(bullets)
    
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings, players_plane, screen, bullets)
    
    start_game()

    3.敌方飞机

    3.1.生成一个敌机

    同样新建一个enemy_plane.py的文件,用于存放敌方飞机的类。

    import pygame
    from pygame.sprite import Sprite
    
    class Enemy(Sprite):
    '''敌方飞机的类'''
    
    def __init__(self, screen, player_settings):
    
    super().__init__()
    self.screen = screen
    self.player_settings = player_settings
    
    # 获取敌方飞机图像、rect属性
    self.image = pygame.image.load('image/enemy1.png')
    self.rect = self.image.get_rect()
    # 敌方飞机的坐标
    self.rect.x = self.rect.width
    self.rect.y = self.rect.height
    
    # 储存敌方飞机水平方向准确位置
    self.x = float(self.rect.x)
    
    def blitme(self):
    '''绘制敌方飞机'''
    self.screen.blit(self.image, self.rect)

    然后实例化这个类,其中需要传递参数enemy_plane给update_screen()函数,后面绘制图像时需要用到。
    注意:实例化类的时候一定要按顺序传递参数。

    main.py

    def start_game():
    --省略部分代码--
    # 实例化敌方飞机,
    enemy_plane = Enemy(screen, player_settings)
    
    while True:
    --省略部分代码--
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings, players_plane, screen, bullets, enemy_plane)

    因为需要在屏幕上显示敌方飞机的图像,所以需要在game_functions.py中的update_screen()添加代码。

    game_functions.py

    def update_screen(player_settings,players_plane, screen, bullets, enemy_plane):
    '''更新窗口图像'''
    --省略部分代码--
    # 绘制玩家飞机
    players_plane.blitme()
    # 绘制敌方飞机
    enemy_plane.blitme()
    
    pygame.display.flip()

    那么如何生成一行敌机呢

    3.2.生成一行敌机

    每个敌机都是有宽度、高度的,那就可以计算出一行可以放下几个敌机。

    game_functions
    首先添加一个生成敌机机群的函数

    def create_enemys(player_settinngs, screen, enemys):
    '''创建敌方机群'''
    # 实例化敌机
    enemy = Enemy(screen, player_settinngs)
    # 计算一行可以容下几个敌机
    enemy_width = enemy.rect.width
    available_space_x = player_settinngs.screen_weight - 2 * enemy_width
    number_enemys_x = int(available_space_x / (2 * enemy_width))
    
    # 创建一行敌机
    for enemy_number in range(number_enemys_x):
    enemy = Enemy(screen, player_settinngs)
    enemy.x = enemy_width + 2 * enemy_width * enemy_number
    enemy.rect.x = enemy.x
    enemys.add(enemy)

    修改函数update_screen

    def update_screen(player_settings,players_plane, screen, bullets, enemys):
    --省略部分代码--
    # 绘制玩家飞机
    players_plane.blitme()
    # 绘制敌方飞机
    #enemy_plane.blitme()
    enemys.draw(screen)
    pygame.display.flip()

    main.py

    def start_game():
    --省略部分代码--
    # 实例化飞机类,对象为players_plane
    players_plane = Plane(screen, player_settings)
    # 存放子弹
    bullets = Group()
    # 实例化敌方飞机,
    enemy_plane = Enemy(screen, player_settings)
    # 存放敌机
    enemys = Group()
    # 创建敌机群
    game_functions.create_enemys(player_settings, screen, enemys)
    while True:
    --省略部分代码--
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings, players_plane, screen, bullets, enemys)
    3.3.重构create_enemys()函数

    为了是函数结构更清晰,这里对create_enemys()函数重构,分为三个函数,
    create_enemys:重复调用create_enemy,创建一行飞机。

    def create_enemys(player_settings, screen, enemys):
    '''创建敌方机群'''
    # 实例化敌机
    enemy = Enemy(screen, player_settings)
    number_enemys_x = get_number_enemys_x(player_settings, enemy.rect.width)
    # 创建一行敌机
    for enemy_number in range(number_enemys_x):
    create_enemy(player_settings, screen, enemys, enemy_number)

    create_enemy:创建一个飞机

    def create_enemy(player_settings, screen, enemys, enemy_number):
    '''创建一个敌机'''
    enemy = Enemy(screen, player_settings)
    enemy_width = enemy.rect.width
    enemy.x = enemy_width + 2 * enemy_width * enemy_number
    enemy.rect.x = enemy.x
    enemys.add(enemy)

    get_number_enemys_x:计算出一行容纳飞机个数

    def get_number_enemys_x(player_settings, enemy_width):
    '''计算出每行可生成几个敌机'''
    available_space_x = player_settings.screen_weight - 2 * enemy_width
    number_enemys_x = int(available_space_x / (2 * enemy_width))
    return number_enemys_x
    3.3.生成一屏幕敌机

    前面生成了一行飞机,原理相同,需要计算出屏幕垂直方向上可以放几行飞机。先创建一个计算垂直方向容纳飞机数的函数。
    game_functions

    def get_number_enemys_y(player_settings, players_plane_height, enemy_height):
    '''获取屏幕可生成多少行'''
    available_space_y = (player_settings.screen_height - (3 * enemy_height) - players_plane_height)
    number_y = int(available_space_y / (2 * enemy_height))
    return number_y
    
    def create_enemy(player_settings, screen, enemys, enemy_number, row_number):
    '''创建一个敌机'''
    enemy = Enemy(screen, player_settings)
    enemy_width = enemy.rect.width
    enemy.x = enemy_width + 2 * enemy_width * enemy_number
    enemy.rect.x = enemy.x
    enemy.rect.y = enemy.rect.height + 2* enemy.rect.height * row_number
    enemys.add(enemy)
    
    def create_enemys(player_settings, screen,  players_plane, enemys):
    '''创建敌方机群'''
    # 实例化敌机
    enemy = Enemy(screen, player_settings)
    number_enemys_x = get_number_enemys_x(player_settings, enemy.rect.width)
    number_rows = get_number_enemys_y(player_settings, players_plane.rect.height, enemy.rect.height)
    # 创建一pingmu敌机
    for row_number in range(number_rows):
    for enemy_number in range(number_enemys_x):
    create_enemy(player_settings, screen, enemys, enemy_number, row_number)

    main.py

    def start_game():
    --省略部分代码--
    game_functions.create_enemys(player_settings, screen, players_plane,enemys)

    运行代码:

    3.4.敌机移动

    main.py

    --省略部分代码--
    while True:
    '''游戏主循环'''
    # 调用文件game_functions内的check_keyboard函数,是一个响应键鼠的函数
    game_functions.check_keyboard(players_plane, screen, player_settings, bullets)
    #game_functions.launch_bullet(players_plane, screen, player_settings, bullets)
    players_plane.change_position()
    
    # 刷新子弹位置,子弹超出屏幕后将其删除。
    game_functions.delete_bullet(bullets)
    
    # 敌机移动
    game_functions.update_enemys(player_settings, enemys)
    
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings,players_plane, screen, bullets, enemys)

    enemy_plane.py

    --省略部分代码--
    def blitme(self):
    '''绘制敌方飞机'''
    self.screen.blit(self.image, self.rect)
    
    def change_position(self):
    '''敌机位置变化'''
    self.x += (self.player_settings.enemy_change_speed * self.player_settings.fleet_direction)
    self.rect.x = self.x
    
    def check_edges(self):
    '''触碰屏幕边缘'''
    screen_rect = self.screen.get_rect()
    if self.rect.right >= screen_rect.right:
    return True
    elif self.rect.left <= 0:
    return True

    game_functions

    --省略部分代码--
    def check_fleet_edges(player_settings, enemys):
    '''敌机触碰边缘响应'''
    for enemy in enemys.sprites():
    if enemy.check_edges():
    change_fleet_direction(player_settings, enemys)
    break
    def change_fleet_direction(player_settings, enemys):
    for enemy in enemys.sprites():
    enemy.rect.y += player_settings.fleet_drop_speed
    player_settings.fleet_direction *= -1
    def update_enemys(player_settings, enemys):
    '''更新敌机位置'''
    check_fleet_edges(player_settings, enemys)
    enemys.update()

    settings.py

    '''敌机设置'''
    # 敌机速度
    self.enemy_change_speed = 1
    self.fleet_drop_speed = 10
    # fleet_direction为1表示向右,为-1表示向左
    self.fleet_direction = 1

    4.射杀敌机

    main.py

    while True:
    '''游戏主循环'''
    # 调用文件game_functions内的check_keyboard函数,是一个响应键鼠的函数
    game_functions.check_keyboard(players_plane, screen, player_settings, bullets)
    #game_functions.launch_bullet(players_plane, screen, player_settings, bullets)
    players_plane.change_position()
    
    # 刷新子弹位置,子弹超出屏幕后将其删除。
    game_functions.delete_bullet(player_settings, screen, players_plane, enemys,bullets)
    
    # 敌机移动
    game_functions.update_enemys(player_settings, enemys)
    
    # 调用update_screen函数,更新窗口
    game_functions.update_screen(player_settings,players_plane, screen, bullets, enemys)

    game_functions

    def delete_bullet(player_settings, screen, players_plane, enemys, bullets):
    '''删除超出屏幕的子弹'''
    bullets.update()
    
    for bullet in bullets.copy():
    if bullet.rect.bottom <= 0:
    bullets.remove(bullet)
    # 子弹碰到敌人就消失
    collisions = pygame.sprite.groupcollide(bullets, enemys, True, True)
    if len(enemys) == 0:
    bullets.empty()
    create_enemys(player_settings, screen, players_plane, enemys)

    5.游戏结束

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: