飞机大战游戏---Pygame
一、基础知识
pygame安装
pygame
就是一个Python模块,专为店子游戏设计
安装pygame(Windows):
pip install pygame
验证安装
python -m pygame.examples.aliens
会出现一个游戏界面,则表示安装成功。
pygame快速入门
1、使用pygame创建图形窗口
1.1游戏的初始化和退出
要使用pygame提供的所有功能之前,需要调用init方法
在游戏结束前需要调用quit方法
方法 | 说明 |
---|---|
pygame.init() | 导入并初始化所有pygame模块,使用其他模块之前,必须先调用init方法 |
pygame.quit() | 卸载所有pygame模块,在游戏结束之前调用! |
1.2理解游戏中的坐标
坐标系:
原点在左上角(0,0)
x轴水平方向向右,逐渐增加
y轴垂直方向向下,逐渐增加
在游戏中,所有可见的元素都是以矩形区域来描述位置的:
要描述一个矩形区域有四个要素:(x,y)(width,height)
pygame
专门提供了一个类pygame.Rect
用于描述矩形区域
Rect(x, y , width , height ) --->Rect
提示:
pygame.Rect
是一个比较特殊的类,内部只是封装了一些数字计算
不执行pygame.init()
方法同样能够直接使用
例子:
import pygame
first_rect = pygame.Rect(100,500,120,125)
print(' 第一个矩形区域的原点为: %d %d' %(first_rect.x , first_rect.y))
print(' 第一个矩形区域的尺寸为:%d %d' %(first_rect.width , first_rect.height))
print('尺寸:',first_rect.size)
1.3创建游戏主窗口
pygame专
门提供了一个模块pygame.display
用于创建、管理游戏窗口
方法 | 说明 |
---|---|
pygame.display.set_mode() | 初始化游戏显示窗口 |
pygame.display.update() | 刷新屏幕内容显示 |
set_mode
方法:
set_mode(resolution=(0,0),flags=0) -->Surface
- 作用 —创建游戏显示窗口
- 参数:
resolution
指定屏幕的宽和高,默认创建的窗口大小和屏幕大小一致
flags
参数指定屏幕的附加选项,例如是否全屏等等,默认不需要传递
depth
参数表示颜色的位数,默认自动匹配 - 注意:必须使用变量记录set_mode方法的返回结果。因为:后续所有的图像绘制都基于这个返回结果
#创建游戏主窗口
screen = pygame.display.set_mode((480,700))
1.4简单的游戏循环
- 为了做到游戏程序启动后,不会立即退出,通常会在游戏程序中添加一个游戏循环
- 游戏循环就是一个无限循环
- 在创建游戏串口代码下方,增加一个无限循环(使用 while true)
- 注意:游戏窗口不需要重复创建
2、理解图像并实现图像绘制
- 在游戏中,能够看到的游戏元素大多都是图像
- 图像文件初始是保存在磁盘上的,如果需要使用,第一步就需要被加载到内存中。
- 要在屏幕上看到某一个图像的内容,需要按照三个步骤:
- 1、使用
pygame.image.load()
加载图像的数据 - 2、使用游戏屏幕对象,调用
blit
方法,将图像绘制到指定位置 - 3、调用
pygame.display.update()
方法更新整个屏幕的显示
提示:要想在屏幕上看到绘制的结果,就一定要调用pygame.display.update()方法
例子:
# 绘制背景图像
# 加载图像数据
bg=pygame.image.load("./images/background.png")
hero=pygame.image.load("./images/me1.png")
# blit绘制图像
screen.blit(bg,(0,0))
screen.blit(hero,(200,500))
# update更新屏幕显示
pygame.display.update()
理解update()方法的作用
- 使用display.set_mode()创建的screen对象是一个内存中的屏幕数据对象
- screen.blit方法可以在画布上绘制很多图像
- display.update()会将画布的最终结果绘制在屏幕上,这样可以提高屏幕绘制效率,增加游戏的流畅度。
3、理解游戏循环和游戏时钟
3.1游戏中动画实现原理
- 通过在电脑上每秒绘制60次,就能够到大非常连续高品质的动画效果。每次绘制的结果被成为帧Frame
3.2游戏循环
游戏的两个组成部分:
游戏循环的开始就意味着游戏的正式开始
游戏循环的作用:
1、保证游戏不会直接退出
2、变化图像位置—动画效果
每个1/60 秒移动一下所有图像的位置
调用pygame.display.update()
更新屏幕显示
3、检测用户交互 —按键、鼠标等
3.3游戏时钟
- pygame专门提供了一个类
pygame.time.Clock
可以非常方便的设置屏幕绘制速度—刷新帧率。 - 要使用时钟对象需要两步:
- 1)在游戏初始化创建一个时钟对象
- 2)在游戏循环中让时钟对象调用tick(帧率)方法
tick
方法会根据上次被调用的时间,自动设置游戏循环中的延时
# 创建时钟对象
clock = pygame.time.Clock()
# tick参数可以指定循环体内部循环的频率
clock.tick(60) #在循环体内部使用
3.4简单动画实现
需求:
1、在游戏初始化定义一个pygame.Rect的变量记录英雄的初始位置
2、在游戏循环中每次让英雄的y-1 ----向上移动
3、当y<=0时,将英雄丕东到屏幕的底部
提示:
每一次调用update()方法之前,需要把所有的游戏图像都重新绘制一边
而且应该最先重新绘制背景图像
3.5在游戏循环中监听事件
事件event
就是启动游戏后,用户针对游戏所做的操作
例如:点击关闭按钮,点击鼠标,按下键盘…
监听在游戏循环中,判断用户具体操作
只有捕获到用户具体的操作,才能针对性的做出响应
pygame中通过pygame.event.get()可以获得用户当前所做动作的事件列表。
用户可以同一时间做很多事情
提示:这段代码非常固定,几乎所有的pygame游戏都大同小异。
例子:
for event in pygame.event.get():#判断用户是否点击了关闭按钮if event.type == pygame.QUIT:print("退出游戏...")pygame.quit()#直接退出系统exit()
理解精灵和精灵组
在之前写的案列中,图像加载、位置变化、绘制图像都需要程序员编写代码分别处理。
为了简化开发步骤,pygame提供了两个类
- pygame.sprite.Sprite —存储图像数据image和位置rect对象
- pygame.sprite.Group
精灵(需要派生子类 |
---|
image 记录图像数据 rect 记录在屏幕上的位置 |
update(*args):更新精灵位置 kill():从所有组中删除 |
精灵组 |
---|
init(self , *精灵): add(*sprites):向组中添加精灵 update(*args):让组中所有精灵调用update方法 sprites():返回所有精灵列表 draw(Surface):将组中所有精灵的image,绘制到Surface的rect位置 |
4.1创建游戏精灵:
新建一个plane_sprites.py文件
定义GameSprite类继承自pygame.sprite.Sprite
注意:
- 如果一个类的父类不是object
- 在重写初始化方法时,一定要先super()一下父类的__init__方法
- 保证父类中实现的__init__代码能够被正常执行
属性: - image精灵图像,使用image_name加载
- rect精灵大小,默认使用图像大小
- speed精灵移动速度,默认为1
方法:
update每次更新屏幕时在游戏循环内调用
让精灵的self.rect.x+=self.speed
提示:
image的get_rect()方法,可以返回pygame.Rect(0,0,图像宽,图像高)的对象
实现代码:
class GameSprite(pygame.sprite.Sprite):"""飞机大战游戏的精灵"""def __init__(self,image_name,speed=1):#调用父类的初始化方法super().__init__()#定义对象属性:#这里的image_name是图片的存放路径self.image = pygame.image.load(image_name)self.rect = self.image.get_rect()self.speed = speed#定义更新def update(self):#在屏幕的垂直方向上移动self.rect.y += self.speed
4.2使用游戏精灵和精灵组创建敌机
步骤
1、使用from导入plane_sprites模块
- from导入的模块可以直接使用
- import 导入的模块需要通过模块名来使用
2、在游戏初始化创建精灵对象和精灵组对象
3、在游戏循环中让精灵组分别调用update()和draw(screen)方法
职责 - 精灵
- 封装图像image、位置rect和速度speed
- 提供update()方法,根据游戏需求,更新位置rect
- 精灵组
- 包含多个精灵对象
- update方法,让精灵组中的所有精灵调用update方法更新位置
- draw(screen)方法,在screen上绘制精灵组中的所有精灵
代码
#创建敌机的精灵
enemy = GameSprite("./images/enmey1.png")
#创建敌机的精灵组
enemy_group = pygame.sprite.Group(enemy)#游戏循环
while True:#tick参数可以指定循环体内部循环的频率,记得import time模块clock.tick(60)# 捕获事件for event in pygame.event.get():# 判断事件类型是否是退出事件if event.type == pygame.QUIT:print('游戏退出...')# quit卸载所有模块pygame.quit()# exit() 直接终止当前正在执行的程序exit()#让精灵组调用两个方法#update --让组中的所有精灵更新位置enemy_group.update()#draw --在screen上绘制所有的精灵enemy_group.draw(screen)#screen是最开始创建的游戏窗口#screen = pygame.display.set_mode((480,700))
游戏框架搭建
目标—使用面向对象设计飞机大战游戏类
目标:
- 明确主程序职责
- 实现主程序类
- 准备游戏精灵组
01.明确主程序职责
一个游戏程序的职责可以分为两个部分:
- 游戏初始化
- 游戏循环
根据明确的职责,设计PlaneGame类如下:
|PlaneGame|
|:–|
|screen |
PlaneGame |
---|
screen clock 精灵或精灵组… |
__init__(self) :__create_sprites(self): start_game(self): |
提示:根据职责封装私有方法,可以避免某一个方法的代码写得太过冗长,如果某一个方法编写的太长,及不好阅读,也不好维护
方法 | 职责 |
---|---|
__event_handler(self)
|
事件监听 |
__check_collide(self)
|
碰撞检测—子弹销毁敌机、敌机撞毁英雄 |
__update_sprites(self)
|
精灵组更新和绘制 |
__game_over()
|
游戏结束 |
02.明确文件职责
plane_main
:
1、封装主游戏类
2、创建游戏对象
3、启动游戏plane_sprites
:
1、封装游戏中所有需要使用的精灵子类
2、提供游戏的相关工具
代码实现- 新建plane_main.py文件,并设置为可执行
- 编写基础代码
import pygame
from plane_sprites import *class PlaneGame(object):"""飞机大战主游戏"""def __init__(self)print("游戏初始化")def start_game(self):print("游戏开始")#游戏循环体while True:passif __name__=='__main__':#创建游戏对象game = PlaneGame()#启动游戏game.start_game()
在游戏初始化中需要设置游戏窗口、创建游戏时钟、创建精灵、精灵组。
在PlaneGame类中的__init__函数中进行这些操作:
def __init__(self):print("游戏初始化")#1.设置游戏窗口self.screen = pygame.display.set_mode(SCREEN_RECT.size)#SCREEN_RECT是定义在plane_sprites.py中的屏幕大小的常量。#通过设置次常量,当我们需要修改屏幕大小时,直接在plane_spriyes.py文件定义常量的位置修改即可,不需要在主函数中一个一个的去找和去修改值。#提示:python中并没有真正意义的常量,只是通过命名的约定---所有字母都是大写的就是常量,开发时不要轻易修改。#2.创建游戏时钟self.clock = pygame.time.Clock()#3.调用私有方法,创建精灵和精灵组self.__create_sprites()#私有方法,创建精灵和精灵组
def __create_sprites(self):pass
在游戏循环中需要:设置刷新帧率、事件监听、碰撞检测、更新/绘制精灵组,更新屏幕显示。
代码如下:
def start_game(self):print("游戏开始")#游戏循环while True:#1.设置刷新帧率self.clock.tick(FRAME_PRE_SEC) #这里的FRAME_PRE_SEC同上屏幕大小#2.事件监听:self.__event_handle()#3.碰撞检测:self.__check_collide()#4.更新/绘制精灵self.__update_sprites()#5.更新显示pygame.display.update()#以下是游戏循环中函数的定义
#暂时只定义,不实现,稍后一个一个实现
def __event_handle(self):#使用pygame.event.get()获得操作事件#使用for循环遍历获得的操作事件for event in pygame.event.get():#判断是否退出游戏if event.type == pygame.QUIT:#定义的静态私有方法,不需要创建对象,直接就可以使用PlaneGame.__game_over()elif:passdef __check_collide(self):passdef __update_sprites(self):pass#定义退出游戏的静态私有方法
@staticmethod
def __game_over():print("游戏结束")pygame.quit()exit()
03.设计背景类
背景交替滚动的思路
游戏启动后,背景图像会连续不断地向下方移动
在视觉上产生飞机不断向上飞行的错觉:
游戏背景不断变化
游戏的主角位置保持不变
解决方法:
1.创建两张背景图像精灵
第1张完全和屏幕重合
第2张在屏幕的正上方
2.两张图像一起向下方运动
self.rect.y +=self.speed
3.当任意背景精灵的 rect.y >= 屏幕的高度,说明移动到屏幕下方
4.将移动到屏幕下方的这张图像设置到屏幕的正上方
rect.y = -rect.height
设计一个背景类Background,继承于GameSprite类,并且有自己的方法。
初始化方法
直接指定背景图片
is_alt
判断是否是另一张图像False表示第一张图像,需要与屏幕重合
True表示另一张图像,在屏幕的正上方。
update()方法
判断是否移动出屏幕,如果是,将图像设置到屏幕的正上方,从而实现交替滚动。
提示:
继承如果父类提供的方法,不能满足子类的需求:
派生一个子类
在子类中针对特有的需求,重写父类方法,并且进行扩展
实现代码
plane_sprites.py
import pygame#定义屏幕大小的常量
SCREEN_RECT = pygame.Rect(0,0,480,700)
#定义屏幕刷新率
FRAME_PRE_SEC = 60class GameSprite(pygame.sprite.Sprite):"""飞机大战游戏精灵"""def __init__(self,image_name,speed=1):#调用父类的初始化方法super().__init__()#定义对象属性:#这里的image_name是图片的存放路径self.image = pygame.image.load(image_name)self.rect = self.image.get_rect()self.speed = speed#定义更新def update(self):#在屏幕的垂直方向上移动self.rect.y += self.speed#背景图片类
class Background(GameSprite):"""游戏背景精灵"""def __init__(self,is_alt=Flase):#1.调用父类方法实现精灵的创建super().__init__("./images/background.png")#2.判断是否是交替图像,如果是,需要设置初始位置if is_alt:self.rect.y = self.rect.heightdef update(self):#调用父类的方法实现super().update()#判断背景是否溢出屏幕,如果移出屏幕,将图像设置到屏幕的上方if self.rect.y>=SCREEN_RECT.height:self.rect.y = -self.rect.height
在plane_main.py中显示背景精灵
1、在__create_sprites
方法中创建精灵和精灵组
2、在__update_sprites
方法中,让精灵组调用update()
和draw()
方法
#plane_main.py模块
class PlaneGame(object):"""飞机大战主游戏"""def __create_sprites(self):bg1 = Background()bf2 = Background(True)self.back_group = pygame.sprite.Group(bg1,bg2)def __update_sprites(self):self.back_group.update()self.back_group.draw(self.screen)
04敌机出场
01使用定时器添加敌机
1、游戏启动后,每隔1s会出现一架敌机
2、每架敌机向屏幕下方飞行,飞行速度各不相同
3、每架敌机出现的水平位置也不尽相同
4、当敌机从屏幕下方飞出,不会再飞回到屏幕中
1.1定时器
- 在pygame中可以使用pygame.time.set_time()来添加定时器
- 所谓定时器,就是每隔一段事件,去指定一些动作
set_timer(eventid,milliseconds) --->None
- set_timer可以创建一个事件
- 可以在游戏循环的事件监听方法中捕获到该事件
- 第1个参数事件代号需要基于常量pygame.USEREVENT来指定
USEREVENT是一个整数,再增加的事件可以使用USEREVENT+1指定,一次类推… - 第二个参数是事件触发间隔的毫秒值
定时器事件的监听
- 通过pygame.event.get()可以获取当前时刻所有的事件列表
- 遍历列表并且判断event.type是否等于eventid,如果相等,表示定时器事件发生。
1.2定义并监听创建敌机事件
pygame的定时器使用套路非常固定:
1、定义定时器常量—eventid
2、在初始化方法中,调用set_timer方法设置定时器事件
3、在游戏循环中,监听定时器事件
1)定义事件
在plane_sprites.py的顶部定义事件常量
#敌机出现
CREATE_ENEMY_EVENT = pygame.USEREVENT
2)在初始化方法中,调用set_timer方法设置定时器事件
#plane_main.py文件
class PlaneGame(object):def __ini__(self):#前面不再赘述#4.设置定时器事件 --创建敌机,每1s出现pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)
3)在游戏循环中,监听定时器事件
def __event_handler(self):for event in pygame.event.get():if event.type == pygame.QUIT():PlaneGame.__game_over()elif event.type == CREATE_ENEMY_EVENT:#创建敌机精灵enemy = Enemy()#将敌机精灵添加到敌机精灵组self.enemy_group.add(enemy)
02设计Enemy类
- 初始化方法
指定敌机图片
随机敌机的初始位置和初始速度 - 重写update()方法
判断是否飞出屏幕,如果是,从精灵组删除
代码
class Enemy(GameSprite):"""敌机精灵"""def __init__(self):#1.调用父类方法实现精灵的创建,同时指定敌机图片super().__init__("./images/enemy1.png")#2.指定敌机的初始随机速度1~3self.spedd = random.randint(1,3)#3.指定敌机的初始随机位置#self.rect.y = -self.rect.heightself.rect.bottom = 0self.rect.x = random.randint(0,SCREEN_RECT.width-self.rect.width)def update(self):#1.调用父类方法,保持垂直方向的飞行super().update()#2.判断是否飞出屏幕,如果是,需要从精灵组删除敌机if self.rect.y >= SCREEN_RECT.height:self.kill()def __del__(self):print("敌机挂了 %s"%self.rect)
创建好敌机类后,在plane_main.py文件中创建精灵并加入到精灵组。创建精灵在监听定时器事件中已完成
加入精灵组
def __create_sprites(self):self.enemy_group = pygame.sprite.Gruop()
飞机大战游戏---Pygame相关推荐
- python飞机大战功能模块图_基于Python的飞机大战游戏设计
第 2 3 卷 第 1 期 2019年 3 月 扬 州 职 业 大 学 学 报 Journal of Yangzhou Polytechnic College Vol .23 No . 1 Mar . ...
- 基于pygame实现的飞机大战游戏
目录 1.引言 1.1 背景 1.2 意义 1.3 功能 2.系统结构 2.1 整体框架 2.2 精灵与精灵组 2.3 功能介绍 2.3.1 玩家飞机 2.3.2 敌机类型和关卡设定 2.3.3 敌机 ...
- Python实验,用pygame做飞机大战游戏设计
飞机大战游戏设计 摘 要:根据课程要求,以及面向对象程序设计的编程思想,在Windows操作系统环境下,运用PyCharm编译程序,以Python语言为开发语言,最终实现飞机大战游戏相应的游戏操作功能 ...
- python飞机大战功能模块图_python pygame实现飞机大战游戏
1.引言 1.1 项目背景 python是一种跨平台的计算机程序设计语言.是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.最初被设计用于编写自动化脚本(Shell),随着版本的不断更新 ...
- Python+pygame飞机大战游戏
转载自IIronMan 的博客 Python:飞机大战游戏1:前期准备 Python:飞机大战游戏2:pygame 快速入门 Python:飞机大战游戏3:框架搭建 Python:飞机大战游戏4:背景 ...
- pygame实现飞机大战游戏
标题:pygame实现飞机大战游戏 源码链接:我的github地址 一.具体演示 1.怪兽分为小怪,和大怪:大怪可以发射子弹 2.英雄飞机共有10个生命值 3.英雄飞机可以上下左右移动 4.显示了英雄 ...
- 基于Pygame开发的最完美的飞机大战游戏
基于Pygame开发的最完美的飞机大战游戏 后期会给大家上源码,以及完整的实现思路.
- 体感游戏 | 手势识别玩飞机大战游戏(一) 用pygame实现飞机大战小游戏
Color Space OpenCV与AI深度学习 后面将分四篇文章来介绍实现手势识别控制飞机大战游戏的功能,它们分别是: 使用Pygame实现简易飞机大战小游戏 使用Python+OpenCV实现简 ...
- python写飞机大战游戏_python实现飞机大战游戏
飞机大战(Python)代码分为两个python文件,工具类和主类,需要安装pygame模块,能完美运行(网上好多不完整的,调试得心累.实现出来,成就感还是满满的),如图所示: 完整代码如下: 1.工 ...
最新文章
- pku 3411 Paid Roads DFS+灵活技巧卡节点访问次数
- 数据库选项--ALTER DATABASE WITH 选项
- 脑电信号特征提取算法c语言_应用深度学习EEGNet来处理脑电信号
- 转:两种转换mysql数据编码的方法-latin1转utf8
- scipy.optimize.curve_fit-曲线拟合
- 一道非常棘手的 Java 面试题:i++ 是线程安全的吗
- javascript学习系列(21):数组中的reduceRight法
- 常系数线性微分方程的直接解法-利用特征方程
- PTA c语言 选择法排序过程
- SQL服务器名称更改
- java getpathinfo_request.getServletPath()和request.getPathInfo()用法
- 单位启用人脸识别考勤
- 第一家店开始要做品牌吗?
- 玩转接口测试,那些必备的技能
- javax.servlet.http.HttpServletResponse.setContentLengthLong(J)V,maven项目报错!!无法访问webapp下的文件,完美解决方案
- 黑苹果登录apple id_充分利用Apple登录功能
- 【Python】个人所得税
- win下连编socket时[Linker error] undefined reference to XXX
- 天空为什么刚才灰得就像哭过呢??
- python 无限循环小数_有关无限循环小数的一处漏洞