实现基本的飞机大战
运行程序,英雄飞机出现在屏幕底边的中央区域,飞机中央每隔一秒会自动发射一枚子弹。随着游戏的开始,敌机会在屏幕上方随机不定时的出现在屏幕内向下飞行。英雄飞机需要通过移位躲避敌机或用子弹消灭敌机,避免碰撞导致游戏结束。
# 导入第三方模块
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代表碰撞的精灵或精灵组内的精灵会消失
# 480\580是图片的宽高SCREEN = pygame.Rect(0,0,480,580)# 创建敌机事件
CREAT_EVENT = pygame.USEREVENT
# 发射子弹事件
FIRE_BULLET = pygame.USEREVENT+1
pygame.Rect可以用来描述矩形区域,从左到右的参数分别代表 x、y、矩形区域的宽、矩形区域的高
pygame.USEREVENT代表定时事件的编号,通过后面+1、+2、+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
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)
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()
虽然这是一个不完整的飞机大战,但是基本功能已经实现,对于刚入门的人(比如我)来说,做完还是会有点小小成就感的。游戏素材可以自行去网上下载,里面有些参数需要根据图片的大小来进行设置。