第095讲: Pygame:飞机大战6 | 学习记录(小甲鱼零基础入门学习Python)
时间:2019-04-18
本文章向大家介绍第095讲: Pygame:飞机大战6 | 学习记录(小甲鱼零基础入门学习Python),主要包括第095讲: Pygame:飞机大战6 | 学习记录(小甲鱼零基础入门学习Python)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
接下来我们要做的,就是实现我们的补给了,游戏每30秒就随机下放一个补给包,可能是超级子弹或者全屏炸弹。
补给包有自己的图片,也有自己的运行轨迹(由上而下)
因此,我们可以新建两个类来实现
"""\/\/\/\/\/\/\/\/------补给类------\/\/\/\/\/\/\/\/"""
class Bullet_Supply(pygame.sprite.spritecollide):
def __init__(self,bg_size) :
pygame.sprite.Sprite.__init__(self)
self.image = pygame.load( r"D:\Code\Python\Pygame\pygame11:飞机大战\images\bullet_supply.png").convert_alpha() #补给子弹图
self.rect = self.image.get_rect()
self.width , self.height = bg_size[0] ,bg_size[1]
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100 #随机生成补给的位置
self.speed = 5 #补给下落的速度
self.active = False #补给是否激活
self.mask = pygame.mask.from_surface(self.image)
def move (self) : #运动函数
if self.rect.top < self.height :
self.rec.top += self.speed
else :
self.active = False
def reset(self): #重置函数
self.active = True
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100
class Bomb_Supply(pygame.sprite.spritecollide):
def __init__(self,bg_size) :
pygame.sprite.Sprite.__init__(self)
self.image = pygame.load( r"D:\Code\Python\Pygame\pygame11:飞机大战\images\bomb_supply.png").convert_alpha() #全屏炸弹补给图
self.rect = self.image.get_rect()
self.width , self.height = bg_size[0] ,bg_size[1]
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100 #随机生成补给的位置
self.speed = 5 #补给下落的速度
self.active = False #补给是否激活
self.mask = pygame.mask.from_surface(self.image)
def move (self) : #运动函数
if self.rect.top < self.height :
self.rec.top += self.speed
else :
self.active = False
def reset(self): #重置函数
self.active = True
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100
接下来我们在 main 模块中实现这个补给包:
实例化补给包并这只补给包发放定时器,定时器每30秒触发一次。
#补给包
bullet_supply = Bullet_Supply(bg_size)
bomb_supply = Bomb_Supply(bg_size)
supply_timer = USEREVENT
pygame.time.set_timer(supply_timer,30000) #设定自定义事件每隔30s返回一个用户自定义事件属性
elif event.type == supply_timer : #响应补给包事件
supply_sound.play() #播放补给的声音
if choice([True,False]) : #随机生成子弹补给或者炸药补给
bullet_supply.reset()
else :
bomb_supply.reset()
#绘制全屏炸弹补给并检测是否发生碰撞
if bomb_supply.active : #如果炸弹补给是激活的
bomb_supply.move() #补给移动
supply_sound.play() #播放炸弹补给出现音乐
screen.blit(bomb_supply.image,bomb_supply.rect) #绘制补给图片
if pygame.sprite.collide_mask(bomb_supply,myself): #检测补给和我放飞机是否发送碰撞
bomb_supply.active = False #如果发生碰撞,那么补给变为未激活状态
get_bomb_sound.play()#播放得到补给的音效
if bomb_num < 3: #如果炸弹数小于3
bomb_num += 1 #炸弹数+1
接下来有个细节问题,就是游戏运行起来之后,当我们按暂停时,背景音乐还存在,而且还会听到补给发放的声音,因为补给发放是在事件触发那里写的,而暂停管的是下面的主逻辑部分,这就导致了一个问题,因为用户暂停,是希望游戏真正的安静下来。
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1 and paused_rect.collidepoint(event.pos): #如果检测到鼠标在暂停位置按下点击按钮
paused = not paused #puase标志键变为True
if paused_rect.collidepoint(event.pos): #让暂停图标在鼠标按下时立即改变
if paused:
paused_image = resume_pressed_image
else:
paused_image = pause_pressed_image
else:
if paused:
paused_image = resume_nor_image
else:
paused_image = pause_nor_image
screen.blit(paused_image,(width - paused_rect.width,5)) #绘制此时的暂停按钮
if paused : #如果暂停了
pygame.time.set_timer(supply_timer,0)
pygame.mixer.music.pause()
pygame.mixer.pause()
else :
pygame.time.set_timer(supply_timer,30000)
pygame.mixer.music.unpause()
pygame.mixer.unpause()
接下来我们来讲讲超级子弹,当我们接收到超级子弹补给的时候,子弹由原来的单发变成了双发,子弹的速度相对也会提高一些。
我们先在 bullet 模块中添加一个 Bullet2 类
class Bullet2(pygame.sprite.Sprite):
def __init__(self,bullet2_image,position):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(bullet2_image).convert_alpha()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.speed = 14
self.active = False
self.mask = pygame.mask.from_surface(self.image)
def move(self):
self.rect.top -= self.speed
if self.rect.top < 0:
self.active = False
def reset(self, position):
self.rect.left, self.rect.top = position
self.active = True
超级子弹的使用时长为18秒,过了这个时间,就自动变为普通子弹。
因此我们需要一个超级子弹的定时器,另外,我们还需要一个变量来表示子弹的类型。
#超级子弹定时器
double_bullet_timer = USEREVENT + 1
# 标志是否使用超级子弹
is_double_bullet = False
然后生成超级子弹
# 生成超级子弹
bullet2 = []
bullet2_index = 0
BULLET2_NUM = 8
for i in range(BULLET2_NUM//2):
bullet2.append(bullet.Bullet2((me.rect.centerx-33, me.rect.centery)))
bullet2.append(bullet.Bullet2((me.rect.centerx+30, me.rect.centery)))
然后响应事件
elif event.type == DOUBLE_BULLET_TIME: #响应超级子弹事件
is_double_bullet = False
pygame.time.set_timer(DOUBLE_BULLET_TIME, 0)
if bullet_supply.active:
bullet_supply.move()
screen.blit(bullet_supply.image, bullet_supply.rect)
if pygame.sprite.collide_mask(bullet_supply, me):
get_bullet_sound.play()
#发射超级子弹18秒
is_double_bullet = True
pygame.time.set_timer(DOUBLE_BULLET_TIME, 18 * 1000)
bullet_supply.active = False
然后修改发射子弹部分
#检测子弹是否击中敌机
for b in bullets: #对于列表中的的所有子弹
if b.active : #如果子弹有效
b.move() #子弹移动
screen.blit(b.image,b.rect) #把子弹绘制在背景上
enemies_hit = pygame.sprite.spritecollide(b,enemies,False,collided=pygame.sprite.collide_mask) #将所有与子弹发生碰撞的敌方飞机都加入到组中
if enemies_hit : #如果有敌机与子弹相碰
b.active = False #将碰撞后在子弹设置为未激活,使其消失,不再继续存在在画面中
for e in enemies_hit : #对于所有相撞的敌机
if (e in middleenemies) or (e in bigenemies) : #如果敌机是中型飞机或者大型飞机
e.hit = True #将敌机的撞击属性设置为已碰撞
e.energy -= 1 #生命值-1
if e.energy == 0 : #如果生命值变为0
e.active = False #将敌机的生命属性设置为死亡
e.hit = False #重新降低及的撞击属性变为未撞击
else : #小型敌机
e.active = False #将他们的状态设置为死亡
本节课位置的所有代码
from pygame.locals import *
from random import *
import traceback
import tkinter as tk
import pygame
import math
import sys
"""\/\/\/\/\/\/\/\/------我的飞机类------\/\/\/\/\/\/\/\/"""
class MyPlane (pygame.sprite.Sprite): #定义我的飞机类,继承动画精灵类(因为之后要进行碰撞检测)
def __init__(self,bg_size,me1_image,me2_image) :
pygame.sprite.Sprite.__init__(self)
self.me1_image = me1_image
self.me2_image = me2_image
self.image1 = pygame.image.load(me1_image).convert_alpha() #第一张飞机图片
self.image2 = pygame.image.load(me2_image).convert_alpha() #第二张飞机图片 两张图片是为了做出飞机喷气的效果
#添加坠机图片
self.destroy_images = []
self.me_destory_1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\me_destroy_1.png").convert_alpha() #自身飞机炸毁第1张图片
self.me_destory_2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\me_destroy_2.png").convert_alpha() #自身飞机炸毁第2张图片
self.me_destory_3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\me_destroy_3.png").convert_alpha() #自身飞机炸毁第3张图片
self.me_destory_4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\me_destroy_4.png" ).convert_alpha() #自身飞机炸毁第4张图片
self.destroy_images.extend([self.me_destory_1_image,self.me_destory_2_image,self.me_destory_3_image,self.me_destory_4_image])
self.rect = self.image1.get_rect() #获得飞机图片的尺寸
self.width , self.height = bg_size[0] , bg_size[1] #设置飞机允许活动地点
self.rect.left , self.rect.top = [ (self.width - self.rect.width) // 2 , \
(self.height - self.rect.height - 60) ] #设置我方飞机出现的位置
self.mask = pygame.mask.from_surface(self.image1) #给类添加上mask属性,之后可以按照完美碰撞
self.speed = 10 #设置飞机出现的速度
self.active = True#设置飞机是否生存的状态
def moveup(self): #飞机向上飞的函数
if self.rect.top > 0: #如果我方飞机没有飞出 上方边界
self.rect.top -= 10 #那么我方飞机朝上飞10个像素
else : #飞出 上方边界
self.rect.top = 0 #锁定在0的位置,不再发生变化
def movedown(self): #飞机向下飞的函数
if self.rect.bottom < (self.height - 60) : #如果我方飞机没有飞出 上方边界
self.rect.bottom += 10 #那么我方飞机朝下飞10个像素
else : #飞出 下方边界
self.rect.bottom = (self.height - 60) #锁定在底边界上方60的位置,不再发生变化
def moveleft(self): #飞机向左飞的函数
if self.rect.left > 0 : #如果我方飞机没有飞出 左方边界
self.rect.left -= 10 #那么我方飞机朝下左10个像素
else : #飞出 左方边界
self.rect.left = 0 #锁定在左边界的位置,不再发生变化
def moveright(self): #飞机向下飞的函数
if self.rect.right < self.width : #如果我方飞机没有飞出 上方边界
self.rect.right += 10 #那么我方飞机朝下飞10个像素
else : #飞出 下方边界
self.rect.right = self.width #锁定在底边界的位置,不再发生变化
"""\/\/\/\/\/\/\/\/------敌机类------\/\/\/\/\/\/\/\/"""
"""本来这里其实可以使用类的继承,然后三种敌机分别继承这个敌机类生成新的敌机,但是在这里、
没有这样做的必要,因为三个类的差别并不是很大,所以不用那么繁杂"""
class SmallEnemy(pygame.sprite.Sprite): #定义我的低敌机类,继承自动画精灵
def __init__(self,bg_size,enemy1_image):
pygame.sprite.Sprite.__init__(self)
self.enemy1_image = enemy1_image
self.enemy1 = pygame.image.load(enemy1_image).convert_alpha() #载入低级敌机照片
#添加坠机图片
self.destroy_images = []
self.enemy1_down1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy1_down1.png").convert_alpha() #低级敌机撞到爆炸第1张图片
self.enemy1_down2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy1_down2.png").convert_alpha() #低级敌机撞到爆炸第2张图片
self.enemy1_down3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy1_down3.png").convert_alpha() #低级敌机撞到爆炸第3张图片
self.enemy1_down4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy1_down4.png").convert_alpha() #低级敌机撞到爆炸第4张图片
self.destroy_images.extend([self.enemy1_down1_image,self.enemy1_down2_image,self.enemy1_down3_image,self.enemy1_down4_image])
self.width ,self.height = bg_size[0] , bg_size[1] #获取生成低级敌机的活动范围
self.rect = self.enemy1.get_rect() #获得低级敌机的尺寸
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
self.mask = pygame.mask.from_surface(self.enemy1) #给类添加上mask属性,之后可以按照完美碰撞
self.speed = 3 #设置小敌机移动的速度
self.active = True #设置飞机是否生存的状态
def move(self) : #小敌机的移动函数
if self.rect.top < self.height : #如果小飞机的底超出窗口的下边框
self.rect.top += self.speed #小飞机向下移动他的速度
else : #如果小飞机已经超出窗口的下边界框
self.reset() #重置小飞机
def reset(self) : #重置小飞机函数
self.active = True#设置飞机是否生存的状态
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
class MiddleEnemy(pygame.sprite.Sprite): #定义我的中敌机类,继承自动画精灵
energy = 8
def __init__(self,bg_size,enemy2_image):
pygame.sprite.Sprite.__init__(self)
self.enemy2_image = enemy2_image
self.enemy2 = pygame.image.load(enemy2_image).convert_alpha() #载入中级敌机照片
#添加坠机图片
self.destroy_images = []
self.enemy2_down1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy2_down1.png").convert_alpha() #中级敌机撞到爆炸第1张图片
self.enemy2_down2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy2_down2.png").convert_alpha() #中级敌机撞到爆炸第2张图片
self.enemy2_down3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy2_down3.png").convert_alpha() #中级敌机撞到爆炸第3张图片
self.enemy2_down4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大战\images\enemy2_down4.png").convert_alpha() #中级敌机撞到爆炸第4张图片
self.enemy2_hit_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飞机大
- Web开发常见的几个漏洞解决方法
- .Net多线程编程—同步机制
- .Net多线程编程—Parallel LINQ、线程池
- 没有自己的服务器如何学习生物数据分析(下篇)
- .Net多线程编程—并发集合
- .Net多线程编程—任务Task
- 学会WCF之试错法——安全配置报错分析
- 生物信息学技能面试题(第5题)-根据GTF画基因的多个转录本结构
- 学会WCF之试错法——超时
- 学会WCF之试错法——客户端调用基础
- 【直播】我的基因组58:用R包SNPRelate来对我的基因型跟hapmap计划数据比较
- 生物信息学技能面试题(第4题)-多个同样的行列式文件合并起来
- PHP 底层的运行机制与原理
- asp.net web api 版本控制
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android学习笔记,不断更新
- cJSON,c语言的JSON库!
- 自己动手实现4大免费聊天机器人:小冰、图灵、腾讯、青云客
- Android Spinner下拉框的基本使用
- hadoop本地运行的两个案例。官方Grep案例、官方WordCount案例。
- 腾讯智能闲聊机器人详细开发教程
- 用PyTorch实现MNIST手写数字识别(非常详细)
- 手把手教你从零开始用Java写爬虫
- STM32 cjson的GBK/UTF-8/UNICODE转换、显示中文、GBK字库
- 都说Linux很重要,你会几个Linux命令?来看看这道面试题目。
- 使用VisualGDB将Keil项目导入VisualStudio
- 小白学图像 | Group Normalization详解+PyTorch代码
- 使用VisualGDB开发Keil MDK-ARM项目
- 保姆级教程:还愁不会搭建伪分布式吗?(其实很简单)
- 如何使用OpenCV RTMP直播推流