实战项目:飞机大战
项目目标:
实现基本的飞机大战python
项目描述:
运行程序,英雄飞机出如今屏幕底边的中央区域,飞机中央每隔一秒会自动发射一枚子弹。随着游戏的开始,敌机会在屏幕上方随机不定时的出如今屏幕内向下飞行。英雄飞机须要经过移位躲避敌机或用子弹消灭敌机,避免碰撞致使游戏结束。编程
项目实现环境:
编辑器:vscode编辑器微信
操纵系统:win10dom
编辑语言:python3.7编辑器
项目中所使用的库或模块:
pygame:第三方模块,用于编写游戏ide
random:python自带的模块,在指定的数字范围内随机产生相应结果动画
项目需求:
绘制游戏背景图并实现背景图滚动ui
绘制敌机并实现出现的时间随机spa
绘制英雄飞机,并实现上下左右移动.net
实现英雄飞机自动发射子弹
实现英雄飞机与敌机、子弹与敌机的碰撞检测
项目准备:建立文件
建立专门调用功能实现飞机大战的主文件main.py
建立为飞机大战提供功能的类文件tools.py,包含的内容有:
精灵类
背景类
敌机类
子弹类
英雄飞机类
代码编写
如何建立屏幕
# 导入第三方模块
import pygame
# 导入pygame库中的全部模块并进行初始化
pygame.init()
# 建立屏幕,设置屏幕大小(应根据背景图大小设置)
surface = pygame.display.set_mode((480,580))
# 卸载全部模块,退出程序
pygame.quit()
以上代码必须写入,不然没法正常运行
如何导入图片,建立图片对象
image = pygame.image.load('图片的地址')
如何将图片绘制到屏幕上
surface.blit(image,(0,0))
第一个参数为图片对象
第二个参数为绘制的初始位置
如何更新屏幕
pygame.display.update()
每次绘制完全部图片后必定要更新屏幕
如何建立精灵组
group = pygame.sprite.Group(精灵1对象,精灵2对象)
精灵组的三个方法
# 同时调用精灵组中全部精灵的update方法
group.update()
# 同时绘制精灵组中全部精灵的位置,须要传入屏幕对象
group.draw(屏幕对象)
# 向精灵组中添加精灵的方法
group.add(精灵)
如何碰撞检测
# 精灵组与精灵组之间的碰撞检测,好比子弹与敌机之间
pygame.sprite.groupcollide('精灵组1','精灵组2',True,True)
# 精灵与精灵组之间的碰撞检测,好比敌机与英雄飞机
pygame.sprite.spritecollide('精灵','精灵组',True)
其中,True表明碰撞的精灵或精灵组内的精灵会消失
编写tools.py文件代码
常量部分
# 480\580是图片的宽高
SCREEN = pygame.Rect(0,0,480,580)
# 建立敌机事件
CREAT_EVENT = pygame.USEREVENT
# 发射子弹事件
FIRE_BULLET = pygame.USEREVENT+1
pygame.Rect能够用来描述矩形区域,从左到右的参数分别表明 x、y、矩形区域的宽、矩形区域的高
pygame.USEREVENT表明定时事件的编号,经过后面+一、+二、+3.....的方式添加多个事件
编写精灵类
# 精灵类
class SpriteParent(pygame.sprite.Sprite):
def __init__(self,imgae,speed=1)
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.speed = speed
def update(self):
self.rect.y += self.speed
该类继承了精灵类,须要包含两种方法:初始化方法和update()方法。
在初始化方法中要添加三个属性,分别是:加载的图片对象、图片的矩形区域,图片的移动速度。其中图片的矩形区域能够使用图片对象的 get_rect() 来获取,速度自定义设置,这里设置成 每次移动1像素。
这里要注意的是,咱们是扩展父类的初始化方法,而不是重写父类的初始化方法
update()方法的做用是更新图片的位置
self.rect.y 表明矩形区域在y轴的位置
编写背景类
class BackGround(SpriteParent):
def __init__(self,is_alt=False):
super().__init__('./images/background.png')
# 若是is_alt为True,则设置图片的初始位置为图片高度的负值
if is_alt:
self.rect.y = -self.rect.height
def update(self):
# 继承父类的update方法,使图片每次向下移动1像素
super().update()
# 当图片顶部的位置等于屏幕的高度时,将该图片返回到屏幕上方,与上方图片进行衔接
if self.rect.y >= SCREEN.height:
self.rect.y = -self.rect.height
要实现背景图片循环上下交替滚动,因此须要实例化两个背景图片对象,其中一个对象的初始位置位于y轴的负方向,且y为背景图片的高度的负值
编写敌机类
import random
class Enemy(SpriteParent):
def __init__(self):
super().__init__('./images/enemy.png')
max_x = SCREEN.width - self.rect.width
# 设置敌机在x轴随机出现的范围
self.rect.x = random.randint(0,max_x)
# 固定敌机在y轴出现的位置
self.rect.y = -self.rect.height
def update(self):
super().update()
# 若是敌机飞出屏幕,则杀死该敌机对象,而后会自动调用__del__方法将其从内存中删除
if self.rect.y >= SCREEN.height:
self.kill()
def __del__(self):
print("敌机已经从内存中销毁..")
编写子弹类
class Bullet(SpriteParent):
def __init__(self):
super().__init__('./images/bullet.png')
def update(self):
self.rect.y -= self.speed
if self.rect.y <= -self.rect.height:
self.kill()
def __del__(self):
print("子弹已经从内存中销毁...")
编写英雄飞机类
class Hero(SpriteParent):
def __init__(self):
super().__init__('./images/hero1.png')
# centerx表明矩形区域在x轴的中心位置
# 这里设置英雄飞机的初始位置为屏幕底端位于x轴的中间
self.rect.centerx = SCREEN.rect.centerx
self.rect.y = SCREEN.rect.height - self.rect.height
self.bullet_group = pygame.sprite.Goup()
def update(self):
# 获取从键盘上按下的值
key_down = pygame.key.get_pressed()
# 判断按下的值,向对应的方向移动
# 内部是设置英雄飞机上下左右移动的边界
if key_down[pygame.K_DOWN]:
if self.rect.bottom >= SCREEN.height:
self.rect.bottom = SCREEN.height
self.rect.y += 2
elif key_down[pygame.K_UP]:
if self.rect.y <= 0:
self.rect.y = 0
self.rect.y -= 2
elif key_down[pygame.K_LEFT]:
if self.rect.x <= 0:
self.rect.x = 0
self.rect.x -= 2
elif key_down[pygame.K_RIGHT]:
if self.rect.right >= SCREEN.width:
self.rect.right = SCREEN.width
self.rect.x += 2
def fire(self):
bullet = Bullet()
# 设置子弹出现的初始位置
bullet.rect.centerx = self.rect.centerx
bullet.rect.y = self.rect.y-20
# 向子弹精灵组中添加子弹精灵
self.bullet_group.add(bullet)
编写main.py文件
from tools import *
import pygame
class PlaneGame(object):
def __init__(self):
pygame.init()
self.surface = pygame.display.set_mode(0,0,SCREEN.size)
# 设置游戏时钟对象
self.clock = pygame.time.Clock()
self.__create_sprite()
# 设置定时建立敌机和发射子弹的定时器,1000表明1s
# 第一个参数为事件编号,第二个参数是定时的时间
pygame.time.set_timer(CREAT_EVENT,1000)
pygame.time.set_timer(FIRE_BULLET,1000)
def __create_sprite(self):
bg1 = Background()
bg2 = Backgroud(True)
self.bg_group = pygame.sprite.Group(bg1,bg2)
self.enemy_group = pygame.sprite.Group()
self.hero = Hero()
self.hero_group = pygame.sprite.Group(self.hero)
def startGame(self):
# 循环表明游戏开始
while True:
# 设置屏幕刷新频率为每秒更新60次,这种频率足以使动画流畅运行
self.clock.tick(60)
self.__event_handler()
self.__check_collide()
self.__update_sprites()
# 每次绘制完就要更新一次
pygame.display.update()
def __event_handler(self):
# 获取屏幕事件
for event in pygame.event.get():
# 若是点击屏幕的退出按钮,则结束游戏
if event.type == pygame.QUIT:
PlaneGame.gemeover()
# 定时建立敌机
elif event.type == CREAT_EVENT:
enemy = Enemy()
self.enemy_group.add(enemy)
# 定时发射子弹,实现自动射击的效果
elif event.type == FIRE_BULLET:
self.hero.fire()
def __check_collide(self):
'''碰撞检测'''
pygame.sprite.groupcollide(self.enemy_group,self.hero.bullet_group,True,True)
# 精灵与精灵组内的精灵产生碰撞,会返回与精灵碰撞的精灵对象
enemies = pygame.sprite.spritecollide(self.hero,self.enemy_group,True)
# 若是enemies有值,说明敌机与英雄飞机产生碰撞,那么杀死英雄飞机,游戏结束
if enemies:
self.hero.kill()
PlaneGame.gemeover()
def __update_sprites(self):
# 更新和绘制精灵组中全部精灵的位置
self.bg_group.update()
self.bg_group.draw(self.surface)
self.enemy_group.update()
self.enemy_group.draw(self.surface)
self.hero_group.update()
self.hero_group.draw(self.surface)
self.hero.bullet_group.update()
self.hero.bullet_group.draw(self.surface)
# 静态方法,由于该方法内不须要传入任何属性或类对象
@ staticmethod
def gameOver():
print("游戏结束...")
pygame.quit()
exit()
# 主程序的入口
if __name__ == "__main__":
pg = PlaneGame()
pg.startGame()
总结
虽然这是一个不完整的飞机大战,可是基本功能已经实现,对于刚入门的人(好比我)来讲,作完仍是会有点小小成就感的。游戏素材能够自行去网上下载,里面有些参数须要根据图片的大小来进行设置。
欢迎添加微信(sy520518)跟我联系
本文分享自微信公众号 - 佛系编程人(py520llj)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。