Python实现飞机大战-第二部分(附源码、素材、超详细教程)
飞机大战第二部分
- 1.前言
- 2.飞机射击
- 2.1.添加子弹的相关设置
- 2.2.创建文件bullet.py
- 2.3.修改game_functions.py
- 2.4.修改mian.py
- 2.5.射击效果
- 2.6.关于子弹连发
- 2.6 删除已消失子弹
- 2.6.1.创建函数delete_bullet()
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.关于子弹连发
子弹连发的原理其实和飞机连续移动的原理相同。不过效果好像不是那么理想,看一下。
简单解释一下,代码一共需要修改五个地方:
- 在Plane类中添加一个射击标志。
class Plane(): '''玩家的飞机的类''' def __init__(self, screen, player_settings): --省略部分代码-- self.sign_launch = False
- 在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)
- 空格按下修改射击标志的布尔值为True。
elif event.type == pygame.KEYDOWN: --省略部分代码-- elif event.key == pygame.K_SPACE: print("空格键按下") players_plane.sign_launch = True
- 空格松开修改射击标志的布尔值为Flase。
elif event.type == pygame.KEYUP: --省略部分代码-- elif event.key == pygame.K_SPACE: print("空格键松开") players_plane.sign_launch = False
- 在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.游戏结束
- 循环神经网络教程-第二部分 用python numpy theano实现RNN
- 循环神经网络教程第二部分-用python,numpy,theano实现一个RNN
- 卷积神经网络(三):卷积神经网络CNN的简单实现(部分Python源码)
- iOS 实现快速切换主题详细教程(附上源码)
- 《Redis设计与实现》[第二部分]单机数据库的实现-C源码阅读(三)
- iOS开发--iOS 实现快速切换主题详细教程(附上源码)
- 循环神经网络教程 第四部分 用Python 和 Theano实现GRU/LSTM RNN
- jQueryEasyUI实现房贷计算器详细教程3--EasyUI部分
- jsp+ssm+mysql框架实现的手机WAP版外卖点餐订餐系统源码附带详细视频开发教程
- awk详细教程:第二部分
- iOS 实现快速切换主题详细教程(附上源码)
- 使用Python脚本在Linux下实现部分Bash Shell的教程
- Python绘图教程——Matplotlib文档(详细版)后半部分
- Python进阶(四十六)-Python3实现SMTP发送邮件详细教程
- 零基础使用python玩跳一跳详细使用教程(工具+源码)
- 循环神经网络教程第四部分-用Python和Theano实现GRU/LSTM循环神经网络
- 卷积神经网络(三):卷积神经网络CNN的简单实现(部分Python源码)
- python-82:交互部分模拟实现的源码
- Python 教程:: 11. 标准库简介 —— 第二部分
- 手把手教你做一个jsp+ssm+mysql实现的在线商城系统附带详细视频开发教程及完整源码