Python小游戏飞机大战源码

Posted 黑马程序员官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python小游戏飞机大战源码相关的知识,希望对你有一定的参考价值。

1、pep8语法规范

  • 遵循语法规范,可以让我们的代码可读性更好,更容易融入新的开发环境。
  • 大多数语法规范可以使用alt + ctrl + L 进行格式化
  • 但是很多规范还是要靠自己调整

2、飞机大战学习的意义

  • 学习飞机大战不是为了让大家做游戏,而是巩固之前学习的知识,让大家了解框架或者三方模块的使用方式
  • 学习飞机大战要学会查询api文档,而不是将所有的函数或方法背下来
  • 使用第三方框架或者包,是为了调用其功能,不是为了解决技术难题,所以不必过度钻研底层代码

3、pygame包的安装

  • 第一种方式:File —> Setting—> Project:工程名—>Python interpret–> 到解释器模块列表下方的+点击—>查询要安装的模块—>点击底下的 Install Package
  • 第二种方式:点击pycharm底下的terminal 打开终端,使用pip list 查看解释器的模块列表,如果有pygame就证明已将安装成功了,如果没有,就输入pip install pygame 进行安装
    • 注意:如果警告pip不是最新版本,不用管他

4、添加python环境变量

不是内部或外部命令,也不是可运行的程序 或批处理文件。

  • 提示这个就是因为没有认真听讲或者不听话。(没有在安装解释器时勾选add to path)
  • 手动添加环境变量流程:
    • 在此电脑中右键点击属性
    • 在属性中选择高级系统设置
    • 点击环境变量按钮
    • 在系统环境变量中双击 Path
    • 找到你的解释器所在的文件夹:(可以使用全局搜索找到python.exe文件)
    • 点击新建,将路径添加到环境变量中
    • 然后找到python.exe所在路径下的Script目录,继续将路径添加到环境变量中
    • 测试 python 和pip 能否正常使用(如果是在终端中执行,需要将终端重启后环境变量才会生效)

5、飞机大战的实现流程

# 如果想要是实现飞机大战,需要分析飞机大战的实现流程恒
# 流程:
# 1.游戏需要有一个呈现数据的窗口,我们称之为窗体或者窗口,也就是显示飞机大战游戏的容器.
# 2.在窗口上添加图片,用于作为飞机大战的背景
# 3.在窗口中添加敌机,并且让敌机进行运动
# 4.在窗口中添加玩家飞机,并且让玩家飞机,根据鼠标的移动而移动位置
# 5.在窗口中添加子弹,并实现让子弹移动的功能
# 6.判断子弹和敌机的碰撞,如果碰撞,则敌机销毁
# 7.判断玩家飞机和敌机的碰撞,碰撞后退出游戏

6、创建飞机大战窗口

# 导入pygame模块
import pygame
import pygame.locals


# 创建窗口
# 怎么设计窗口的大小???  窗体大小,要与背景图片大小一致
# 背景图片的大小是512*768所以窗口大小,就定义为512*768就可以了
window = pygame.display.set_mode((512, 768))

# 为了让窗口不会立即关闭,而是等待我们的操作,需要循环刷新窗口
# 直接使用while True 死循环刷新窗口
while True:
    # 刷新窗口内容的命令
    pygame.display.update()
    # 再刷新窗口时,也要不断获取用户的操作信息,如果我们想要获取可以使用evnet
    # 获取所有的窗口事件(事件就是用户做出的操作)
    # 当前方法的返回值是一个列表,内部获取了所有的窗口事件(用户的点击,鼠标移动,关闭按钮的点击等)
    # 我们可以根据不同的事件做出不同的反馈例如QUIT 可以退出程序
    # print(pygame.event.get())
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')

7、飞机大战背景图片的添加

# 导入pygame模块
import pygame
import pygame.locals

# 创建窗口
window = pygame.display.set_mode((512, 768))

# TODO:加载背景图片
# 加载图片完成后,将图片保存到变量中
background_img = pygame.image.load('res/img_bg_level_2.jpg')
# TODO:将图片添加到窗口中
# window.blit(图片, (图片的x坐标, 图片的y坐标))
window.blit(background_img, (0, 0))

while True:
    # 刷新窗口内容的命令
    pygame.display.update()
    # 获取关闭窗口事件
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')

8、背景图片的移动

# 导入pygame模块
import pygame
import pygame.locals

# TODO: 可以创建全局变量,在循环中每次加载完图片后,将y值进行自增,则图片会不断向下移动
background_y = 0

# 创建窗口
window = pygame.display.set_mode((512, 768))

# 加载背景图片
# 加载图片完成后,将图片保存到变量中
background_img = pygame.image.load('res/img_bg_level_2.jpg')
# background_img1 = pygame.image.load('res/img_bg_level_1.jpg')
# 将图片添加到窗口中
# window.blit(图片, (图片的x坐标, 图片的y坐标))
window.blit(background_img, (0, 0))

while True:
    # TODO: 让背景图片进行移动
    # 如果我们想让背景图片移动,在每次刷新窗口之前,需要改变图片的位置
    # 改变图片的位置非常简单只需要修改图片的x,y坐标位置即可
    window.blit(background_img, (0, background_y))
    # TODO: 添加辅助背景
    # 如果想让图片进行无缝的滚动,需要再次添加一张图片,与现有图片首尾相接,当图片滚动到超出屏幕范围时,回到原始位置
    window.blit(background_img, (0, background_y - 768))
    # 怎样可以让图片随着循环不断向下移动??? 每次循环对于y左边进行自增
    # background_y += 1
    # 思考??这样移动出了屏幕是不是就看不见了???也就没有存在的价值了
    # 所以我们需要让背景图片反复移动,当图片完全移出窗体范围,则恢复到原始位置(0,0)
    if background_y >= 768:
        background_y = 0
    else:
        background_y += 1

    # 刷新窗口内容的命令
    pygame.display.update()
    # 获取关闭窗口事件
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')

9、将变量及函数抽取出来

# 导入pygame模块
import pygame
import pygame.locals

# TODO: 抽取常量和变量
# 思考: 变量是统一管理更为方便还是分散管理方便?? 统一管理
# 在代码中出现的数字有没有单位,比如  apples = 5 此时显示的是重量还是个数???  不清楚
# 为了增加代码的可读性,尽量减少程序中出现的魔法数字,可以将魔法数字提取出来作为常量出现.
# 在编程中,一般不可以被修改的变量叫做常量,Python中本身是没有常量的,所以我们使用标识符大写来备注常量
# 但是这个常量可以被修改,只是提醒协同人员或调用模块的人这个是一个常量而已
# 抽取常量
WINDOW_WIDTH = 512  # 窗口宽度
WINDOW_HEIGHT = 768  # 窗口高度

# 创建全局变量
background_x = 0
background_y = 0

# 创建窗口
# window = pygame.display.set_mode((512, 768))
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))

# # 加载背景图片
# background_img = pygame.image.load('res/img_bg_level_2.jpg')
# # 将图片添加到窗口中
# window.blit(background_img, (0, 0))

# TODO: 抽取函数
# 函数一般就是一个特定的功能,完整的功能保存到函数中进行调用即可

# 移动背景图片
def move_background():
    """可以滚动显示背景图片"""
    # 如果想要在函数体内部修改全局变量的值,需要声明全局变量才可以
    global background_y
    global background_x

    # 加载背景图片
    background_img = pygame.image.load('res/img_bg_level_2.jpg')

    # 让背景图片进行移动
    window.blit(background_img, (background_x, background_y))
    # 添加辅助背景
    window.blit(background_img, (background_x, background_y - WINDOW_HEIGHT))
    # 循环移动
    if background_y >= WINDOW_HEIGHT:
        background_y = 0
    else:
        background_y += 1

# 获取窗口事件
def get_window_event():
    """获取所有的窗口事件,并且进行处理"""
    # 获取关闭窗口事件
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')


while True:
    # # 让背景图片进行移动
    # window.blit(background_img, (background_x, background_y))
    # # 添加辅助背景
    # window.blit(background_img, (background_x, background_y - WINDOW_HEIGHT))
    # # 循环移动
    # if background_y >= WINDOW_HEIGHT:
    #     background_y = 0
    # else:
    #     background_y += 1
    # TODO: 调用移动背景的方法
    move_background()

    # 刷新窗口内容的命令
    pygame.display.update()
    # 获取关闭窗口事件
    # for event in pygame.event.get():
    #     if event.type == pygame.locals.QUIT:
    #         exit('退出游戏')
    # TODO: 调用获取事件的方法
    get_window_event()

10、添加敌机

# 导入pygame模块
import random

import pygame
import pygame.locals

# 抽取常量
WINDOW_WIDTH = 512  # 窗口宽度
WINDOW_HEIGHT = 768  # 窗口高度

# TODO: 添加敌机的尺寸
ENEMY_WIDTH = 100  # 敌机宽度
ENEMY_HEIGHT = 68  # 敌机高度

# 创建全局变量
background_x = 0
background_y = 0

# TODO: 添加敌机坐标
enemy_x = random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH)  # 敌机的x坐标
enemy_y = -ENEMY_HEIGHT  # 敌机的y坐标

# TODO: 添加敌机速度
enemy_speed = random.randint(2, 4)  # 敌机的速度

# 创建窗口
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))


# 移动背景图片
def move_background():
    """可以滚动显示背景图片"""
    # 如果想要在函数体内部修改全局变量的值,需要声明全局变量才可以
    global background_y
    global background_x

    # 加载背景图片
    background_img = pygame.image.load('res/img_bg_level_2.jpg')
    # 让背景图片进行移动
    window.blit(background_img, (background_x, background_y))
    # 添加辅助背景
    window.blit(background_img, (background_x, background_y - WINDOW_HEIGHT))
    # 循环移动
    if background_y >= WINDOW_HEIGHT:
        background_y = 0
    else:
        background_y += 1


# TODO: 添加并移动敌机
def move_enemy():
    """添加敌机并且移动敌机的函数"""
    # 声明全局变量
    global enemy_x
    global enemy_y
    global enemy_speed
    # 加载敌机图片
    enemy_img = pygame.image.load('res/img-plane_1.png')
    # 在窗口上显示敌机
    window.blit(enemy_img, (enemy_x, enemy_y))
    # 移动敌机
    # 为了让敌机有一个俯冲的效果,所以让敌机移动速度大于背景图片的移动速度
    # enemy_y += 2
    # 当敌机移动到屏幕之外我们就不需要再去显示他了,为了让敌机变量复用
    # 当敌机超出屏幕范围时,将敌机恢复原位(如果我们想让敌机有一个进入到屏幕的效果,
    # 我们需要将敌机的初始位置设置到屏幕外边,此时初始位置左边y值应该为负的敌机的高度)
    if enemy_y >= WINDOW_HEIGHT:
        enemy_y = -ENEMY_HEIGHT
        # 每次进入屏幕时都会重置x的值
        enemy_x = random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH)
        # 每次重新进入屏幕时,重置速度值
        enemy_speed = random.randint(2, 4)
    else:
        enemy_y += enemy_speed
    # 思考如果每次敌机都从一个位置出现未免太过死板游戏过于简单,所以要将敌机出现的位置x坐标设置为随机值


# 获取窗口事件
def get_window_event():
    """获取所有的窗口事件,并且进行处理"""
    for event in pygame.event.get():
        # 获取关闭窗口事件
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')


if __name__ == '__main__':
    while True:
        # 调用移动背景的方法
        move_background()
        # TODO: 调用移动敌机的方法
        move_enemy()
        # 刷新窗口内容的命令
        pygame.display.update()
        # 调用获取事件的方法
        get_window_event()

11、添加多架敌机

# 导入pygame模块
import random

import pygame
import pygame.locals

# 抽取常量
WINDOW_WIDTH = 512  # 窗口宽度
WINDOW_HEIGHT = 768  # 窗口高度

ENEMY_WIDTH = 100  # 敌机宽度
ENEMY_HEIGHT = 68  # 敌机高度

# 创建全局变量
background_x = 0
background_y = 0

# TODO: 创建一个储存敌机数据的容器
# 如果添加添加多架敌机,每一架敌机都要保存几个数据??? 每一架敌机大小相同,所以需要保存三个数据x, y ,speed
# 多架敌机用什么数据类型进行保存更为合适???? 列表嵌套字典
# 示例['x':200, 'y':300, 'speed':3, 'x':300, 'y':500, 'speed': 4]
enemy_list = []
# enemy_x = random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH)  # 敌机的x坐标
# enemy_y = -ENEMY_HEIGHT  # 敌机的y坐标
#
# enemy_speed = random.randint(2, 4)  # 敌机的速度

# 创建窗口
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))


# TODO: 初始化敌机的函数
def init_enemy_list():
    global enemy_list
    # 循环多少次就有多少架敌机
    for i in range(5):
        enemy_list.append(
            'x': random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH),
             'y': -ENEMY_HEIGHT,
             'speed': random.randint(2, 4)
             
        )


# 移动背景图片
def move_background():
    """可以滚动显示背景图片"""
    # 如果想要在函数体内部修改全局变量的值,需要声明全局变量才可以
    global background_y
    global background_x

    # 加载背景图片
    background_img = pygame.image.load('res/img_bg_level_2.jpg')
    # 让背景图片进行移动
    window.blit(background_img, (background_x, background_y))
    # 添加辅助背景
    window.blit(background_img, (background_x, background_y - WINDOW_HEIGHT))
    # 循环移动
    if background_y >= WINDOW_HEIGHT:
        background_y = 0
    else:
        background_y += 1


# 添加并移动敌机
# TODO: 将每一架敌机数据组成的字典传递进来
# TODO: 将所有的敌机的x,y,speed 用字典中的数据进行替换
def move_enemy(enemy_dict):
    """添加敌机并且移动敌机的函数"""
    # 声明全局变量
    # global enemy_x
    # global enemy_y
    # global enemy_speed
    # 加载敌机图片
    # TODO: 随机加载飞机图片
    # 如果想要随机加载敌机图片,就对敌机的路径进行随机从plane1- plane7
    # 课下感兴趣的同学自己完成
    enemy_img = pygame.image.load('res/img-plane_1.png')
    # 在窗口上显示敌机
    window.blit(enemy_img, (enemy_dict['x'], enemy_dict['y']))
    # 移动敌机
    # 为了让敌机有一个俯冲的效果,所以让敌机移动速度大于背景图片的移动速度
    # enemy_y += 2
    # 当敌机移动到屏幕之外我们就不需要再去显示他了,为了让敌机变量复用
    # 当敌机超出屏幕范围时,将敌机恢复原位(如果我们想让敌机有一个进入到屏幕的效果,
    # 我们需要将敌机的初始位置设置到屏幕外边,此时初始位置左边y值应该为负的敌机的高度)
    if enemy_dict['y'] >= WINDOW_HEIGHT:
        enemy_dict['y'] = -ENEMY_HEIGHT
        # 每次进入屏幕时都会重置x的值
        enemy_dict['x'] = random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH)
        # 每次重新进入屏幕时,重置速度值
        enemy_dict['speed'] = random.randint(2, 4)
    else:
        enemy_dict['y'] += enemy_dict['speed']
    # 思考如果每次敌机都从一个位置出现未免太过死板游戏过于简单,所以要将敌机出现的位置x坐标设置为随机值


# 获取窗口事件
def get_window_event():
    """获取所有的窗口事件,并且进行处理"""
    for event in pygame.event.get():
        # 获取关闭窗口事件
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')


if __name__ == '__main__':
    # TODO: 调用函数初始化敌机数据
    init_enemy_list()
    while True:
        # 调用移动背景的方法
        move_background()
        # TODO: 如果想要添加多架敌机,要么在函数中进行循环,要么执行多次添加一架敌机的方法,我们选择后者
        for enemy in enemy_list:
            move_enemy(enemy)
        # 刷新窗口内容的命令
        pygame.display.update()
        # 调用获取事件的方法
        get_window_event()

12、随机设置敌机的颜色

# 导入pygame模块
import random

import pygame
import pygame.locals

# 抽取常量
WINDOW_WIDTH = 512  # 窗口宽度
WINDOW_HEIGHT = 768  # 窗口高度

ENEMY_WIDTH = 100  # 敌机宽度
ENEMY_HEIGHT = 68  # 敌机高度

# 创建全局变量
background_x = 0
background_y = 0

# 创建一个储存敌机数据的容器
enemy_list = []

# 创建窗口
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))


# 初始化敌机的函数
def init_enemy_list():
    # 循环多少次就有多少架敌机
    for i in range(5):
        enemy_list.append(
            'x': random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH),
             'y': -ENEMY_HEIGHT,
             'speed': random.randint(2, 4),
             # TODO: 让敌机保存自己的飞机颜色图片
             'img_path':f'res/img-plane_random.randint(1,7).png'
             
        )


# 移动背景图片
def move_background():
    """可以滚动显示背景图片"""
    # 如果想要在函数体内部修改全局变量的值,需要声明全局变量才可以
    global background_y
    global background_x

    # 加载背景图片
    background_img = pygame.image.load('res/img_bg_level_2.jpg')
    # 让背景图片进行移动
    window.blit(background_img, (background_x, background_y))
    # 添加辅助背景
    window.blit(background_img, (background_x, background_y - WINDOW_HEIGHT))
    # 循环移动
    if background_y >= WINDOW_HEIGHT:
        background_y = 0
    else:
        background_y += 1


# 添加并移动敌机
def move_enemy(enemy_dict):
    """添加敌机并且移动敌机的函数"""
    # 加载敌机图片
    # 动态随机添加敌机图片
    # 如果在此处我们进行图片随机,每一架飞机的图片都是一直在变化的,我们需要的结果
    # 是在敌机进入到窗口中,颜色就不再变化了,只有重新回到起点后,才会重置敌机颜色
    # TODO: 加载图片时,获取敌机字典中的图片路径进行加载
    enemy_img = pygame.image.load(enemy_dict['img_path'])
    # 在窗口上显示敌机
    window.blit(enemy_img, (enemy_dict['x'], enemy_dict['y']))
    # 移动敌机
    if enemy_dict['y'] >= WINDOW_HEIGHT:
        enemy_dict['y'] = -ENEMY_HEIGHT
        # 每次进入屏幕时都会重置x的值
        enemy_dict['x'] = random.randint(0, WINDOW_WIDTH - ENEMY_WIDTH)
        # 每次重新进入屏幕时,重置速度值
        enemy_dict['speed'] = random.randint(2, 4)
        # TODO: 每次回到起始位置时重置自己的图片路径
        enemy_dict['img_path'] = f'res/img-plane_random.randint(1,7).png'
    else:
        enemy_dict['y'] += enemy_dict['speed']
    # 思考如果每次敌机都从一个位置出现未免太过死板游戏过于简单,所以要将敌机出现的位置x坐标设置为随机值


# 获取窗口事件
def get_window_event():
    """获取所有的窗口事件,并且进行处理"""
    for event in pygame.event.get():
        # 获取关闭窗口事件
        if event.type == pygame.locals.QUIT:
            exit('退出游戏')


if __name__ == '__main__':
    # 调用函数初始化敌机数据
    init_enemy_list()
    while True:
        # 调用移动背景的方法
        move_background()
        # 如果想要添加多架敌机,要么在函数中进行循环,要么执行多次添加一架敌机的方法,我们选择后者
        for enemy in enemy_list:
            move_enemy(enemy)
        # 刷新窗口内容的命令
        pygame.display.update()
        # 调用获取事件的方法
        get_window_event()

以上是关于Python小游戏飞机大战源码的主要内容,如果未能解决你的问题,请参考以下文章

Python飞机大战项目终篇(一步一步实现---最全笔记)

javascript飞机大战-----001分析

Python笔记22——飞机大战(下)

Python版飞机大战

飞机大战

java开发飞机大战