Pygame模块下载及导入创建
在电脑中用pip install pygame命令安装pygame模块并导入pycharm中
先创建一个飞机大战项目文件,所有代码都写在这个文件里,创建好后将游戏的图片文件拷贝到项目文件下
pip install pygame
创建游戏窗口
创建窗口
在上面创建的飞机大战文件中创建py文件,在里面写以下所有代码。
首先导入pygame包,利用import pygame命令实现导入;再创建游戏窗口设置元组set_mode,在元组中设置其宽高。
# 创建游戏窗口
pygame.display.set_mode((480,650)) # 元组中480表示宽度, 650表示高度
pygame.quit() # 卸载模块,释放资源【】
使游戏循环
通过语句While True实现游戏循环,位置写在pygame.quit()上方
# 游戏循环
修改游戏名称和图标
主要修改游戏的名称和图标,使其变成飞机大战游戏专有
Set_caption修改游戏名称,image.load导入图片set.icon修改图标为导入的图片
# 修改游戏名称
pygame.display.set_caption("飞机大战")
icon = pygame.image.load("img/icon72x72.png")
绘制游戏背景和英雄机精灵
绘制游戏背景
首先image.load加载图片,screen.blit将背景图片加载到窗口中,并将其设置到原点位置(0,0)
#加载背景图片
bg_img = pygame.image.load("img/background.png")
#将背景图片加载到窗口中,(0,0)表示背景图片放到原点位置
绘制英雄机
image.load加载图片,用.....if...else....绘制英雄精灵图片将英雄飞机绘制到游戏窗口上,要设计heroIndexShif = 0 作为切换图片索引,rect定义英雄机。
其中,飞机位置的确认是这样的,窗口的大小都是 480*650,飞机大小是100*124,由于飞机初始化的时候在窗口的正下方,所以英雄机的坐标为(190,526)
heroIndexShif = 0 #作为切换图片索引
hero_rect = pygame.rect.Rect(190,526,66,80) # 定义英雄机rect
screen.blit(hero_img1,(hero_rect.x,hero_rect.y))
screen.blit(hero_img2,(hero_rect.x,hero_rect.y))
设置游戏时钟
主要是为了设置游戏的刷新次数,创建游戏时钟,在游戏循环中设置时钟为每秒钟刷新60次
# 创建游戏时钟
更改英雄机坐标位置
主要是为了英雄精灵实现上下自动移动。首先rect.y修改英雄飞机的y轴值,让飞机从底部飞进
# 修改英雄飞机的y轴值
事件监听和控制英雄机移动
游戏事件监听
通过事件监听来接收鼠标和键盘对英雄机的控制,一定要增添事件监听,否则游戏将不能实现正常关闭。
- 首先获取所有事件
event_list = pygame.event.get()
- 获取窗口退出事件
for event in event_list:
if event.type == pygame.QUIT:# 加上这个模块就不卡了
终止Python程序, exit(0)表示正常退出 exit(1)表示异常退出。
控制英雄机移动
通过if elif实现对英雄机的上下左右移动控制,一定要计算好英雄机移动数值,要设置定义按键动作重复执行。
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:# 向左移动
heroPlaneX = heroPlaneX - 5 if heroPlaneX >= 5 else 0
elif event.key == pygame.K_RIGHT:# 向右移动
heroPlaneX = heroPlaneX +5 if heroPlaneX <= 375 else 380
elif event.key == pygame.K_DOWN: # 向下移动
heroPlaneY = heroPlaneY + 5 if heroPlaneY <= 521 else 526
elif event.key == pygame.K_UP: # 向上移动
heroPlaneY = heroPlaneY -5 if heroPlaneY >= 5 else 0
pygame.key.set_repeat(20,30)
在使按键动作重复执行时,set_repeat(20,30)中20,30都是毫秒级的,20代表按下键盘20 ms后反应,30代表当在30 ms内还没有抬起键盘,就会再给一个20 ms按键反应。
绘制敌机和控制敌机移动
绘制敌机精灵
加载敌机精灵图片到游戏中,定义敌机精灵的rect以及xy坐标,绘制出的敌机精灵要和英雄机大小相似,且要使敌机精灵在游戏显示窗口上方位置。
# 加载敌机图片
enemy_img = pygame.image.load("img/enemy1.png")
enemy_rect = pygame.rect.Rect(206,0,69,89) # x= 480//2-69//2
screen.blit(enemy_img,(enemyPlaneX,enemyPlaneY))
控制敌机移动
通过if elif实现对敌机的上下左右移动控制,一定要计算好英雄机移动数值,要在游戏循环代码外进行设置。
if direct == "左":
绘制敌机子弹和英雄机子弹
绘制英雄机与敌机子弹时我们采取类方法来进行定义,draw用来画子弹,然后定义xy坐标和窗口对象,elif设置英雄机控制发射子弹,实例化子弹对象并将子弹添加到列表中。要画出每一个子弹,在画敌机子弹时要产生随机性。实例化每一个子弹并让子弹到最下面的时候消失。
class HeroBullet():
def __init__(self, x, y, screen):
self.pic = pygame.image.load("img/bullet.png")
self.screen.blit(self.pic, (self.x, self.y))
def __init__(self, x, y, screen):
self.pic = pygame.image.load("img/bullet1.png")
self.screen.blit(self.pic, (self.x, self.y))
画出英雄机子弹
elif event.key == pygame.K_SPACE: # 英雄机控制发射子弹
hero_bullet = HeroBullet(heroPlaneX + 50 - 11, heroPlaneY - 22, screen) # 把子弹添加到列表里
HeroBiulist.append(hero_bullet)
HeroBiulist.remove(bullet) if bullet.y < 0 else ""
画出敌机子弹
# 产生随机数
enemy_bullet = EnemyBullet(enemyPlaneX+69//2-9//2,enemyPlaneY+89,screen)
EnemyBiulist.append(enemy_bullet)
EnemyBiulist.remove(bullet) if bullet.y >650-89 -21//2 else ""
绘制敌机爆炸和英雄机爆炸
绘制敌机爆炸
绘制爆炸及碰撞检测,设置爆炸条件和图片索引,控制敌机爆炸条件,检测敌机和子弹的矩形是否相交,绘制敌机爆炸图片, 当敌机爆炸图片的下表和图片总数相同时,说明爆炸图片已经绘制结束。在这里要用到colliderect()函数,语法为rect1.colliderect(rect2)。
is_bomb = False # 爆炸条件
定义子弹的rect,检测敌机和子弹的矩形是否相交,并绘制敌机爆炸图片放入游戏,用if else做循环检测是否为真,从而执行爆炸命令。
hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y,10,10)
flag = pygame.Rect.colliderect(enemy_rect,hero_bullet_rect)# 检测敌机和子弹的矩形是否相交
enemy_bomb_list = ["img/enemy1_down1.png", "img/enemy1_down2.png", "img/enemy1_down3.png", "img/enemy1_down4.png"]
screen.blit(enemy_img, (enemyPlaneX, enemyPlaneY))
if enemy_bomb_index == len(enemy_bomb_list):# 当敌机爆炸图片的下表和图片总数相同时,说明爆炸图片已经绘制结束
enemy_bomb_img = pygame.image.load(enemy_bomb_list[enemy_bomb_index])# 加载敌机爆炸图片
screen.blit(enemy_bomb_img, (enemyPlaneX, enemyPlaneY))# 绘制敌机爆炸图片
绘制英雄机爆炸
设置英雄机爆炸条件及图片索引,定义子弹将英雄飞机绘制到窗口上,当爆炸图片加载结束后,加载并绘制英雄飞机爆炸的图片。我们只需要循环遍历每一颗已经发射的子弹,子弹和每一个敌人飞机的矩形是否相交,如果相交,说明子弹击中了敌机,我们对应做行为就可以了。
hero_is_bomb = False # 英雄机爆炸条件
hero_bomb_index = 0 # 英雄机爆炸图片索引
enemy_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 9, 21) # 定义敌机子弹rect
flag = enemy_bullet_rect.colliderect(hero_rect) # 英雄机爆炸的条件
EnemyBiulist.remove(bullet)# 当战机爆炸的时候,移除子弹
screen.blit(hero_img1, (heroPlaneX, heroPlaneY))
screen.blit(hero_img2, (heroPlaneX, heroPlaneY))
if hero_bomb_index == len(hero_bomb_list):# 当爆炸图片加载结束后
hero_bomb_img = pygame.image.load(hero_bomb_list[hero_bomb_index])
screen.blit(hero_bomb_img,(heroPlaneX,heroPlaneY))
飞机大战游戏项目完整代码
import random
import pygame
import time
pygame.init()
#创建窗口
screen=pygame.display.set_mode((480,650))#480为宽,500为高
#修改游戏名称
pygame.display.set_caption('飞机大战')
#修改游戏图标
icon = pygame.image.load("img/icon.png")
pygame.display.set_icon(icon)
# 加载背景
bg_img = pygame.image.load('img/background.png')
#加载精灵图片
hero_img1 = pygame.image.load("img/me1.png")
hero_img2 = pygame.image.load("img/me2.png")
#加载战机战损
hero_bomb_imgs=["img/me_destroy_1.png",
"img/me_destroy_2.png", "img/me_destroy_3.png", "img/me_destroy_4.png"]
#作为切换的索引值
shitindex=0
#定义英雄机位置
hero_rect=pygame.rect.Rect(190,525,100,124)
#设置精灵XY轴
hero_PlaneX=hero_rect.x
hero_PlaneY=hero_rect.y
#加载敌机图片
enemy_img=pygame.image.load('img/enemy2.png')
enemy_img2=pygame.image.load("img/enemy2_hit.png")
#加载敌机战损
enemy_bomb_imgs=["img/enemy2_down1.png",
"img/enemy2_down2.png", "img/enemy2_down3.png", "img/enemy2_down4.png"]
#定义敌机位置
enemy_rect=pygame.rect.Rect(158,0,69,99) #(480-69)/2
enemyPlaneX=enemy_rect.x
enemyPlaneY=enemy_rect.y
#设置灵敏度
pygame.key.set_repeat(20,30)
#定义时钟
clock=pygame.time.Clock()
#定义图片切换索引
hero_imgindex=0
#定义敌机初始移动方向
direct='left'
#定义英雄机子弹 子弹类
class HeroBullet:
def __init__(self,x,y,screen):
self.x=x
self.y=y
self.screen=screen
self.pic=pygame.image.load('img/bullet1.png')
#画子弹
def draw(self):
self.screen.blit(self.pic,(self.x,self.y))
self.move()
#子弹移动方法
def move(self):
self.y-=5
#英雄机子弹列表
hero_Bulletlist=[]
#定义敌机子弹
class EnemyBullet:
def __init__(self, x, y, screen):
self.x = x
self.y = y
self.screen = screen
self.pic = pygame.image.load('img/bullet2.png')
# 画子弹
def draw(self):
self.screen.blit(self.pic, (self.x, self.y))
self.move()
# 子弹移动方法
def move(self):
self.y+=5
#敌机子弹列表
enemy_list=[]
#英雄机爆炸
hero_bomb=False
#英雄机爆炸索引
hero_bomb_index=
#敌机爆炸条件
enemy_bomb=False
#敌机爆炸索引
enemy_bomb_index=0
#游戏循环
while True:
clock.tick(60)#60表示每秒刷新60
# 图片背景
screen.blit(bg_img, (0, 0))
# 修改飞机y值,实现自动飞行
hero_PlaneY -=1
# 飞机从底部飞出
if hero_PlaneY<0:
hero_PlaneY=650
#绘制敌机
screen.blit(enemy_img,(enemyPlaneX,enemyPlaneY))
# 控制敌机移动
if direct =='left':
enemyPlaneX-=5
if enemyPlaneX<=0:
direct='right'
elif direct=='right':
enemyPlaneX=enemyPlaneX + 5
if enemyPlaneX >=480-165:
direct='left'
x=random.randint(1,100)
if x==5 or x==78 :
#绘制敌机子弹
enemybullet=EnemyBullet(enemyPlaneX+69/2-5/2,enemyPlaneY+99,screen)
enemy_list.append(enemybullet)
for bullet2 in enemy_list:
bullet2.draw()
enemy_bullet_rect = pygame.rect.Rect(bullet2.x, bullet2.y, 5, 11)
flag2 = enemy_bullet_rect.colliderect(hero_rect)
if flag2:
print("战机爆炸")
hero_bomb = True
enemy_list.remove(bullet2)
if hero_bomb == False:
# 英雄机绘制到窗口
if shitindex == 0:
screen.blit(hero_img1, (hero_PlaneX, hero_PlaneY))
shitindex = 1
else:
screen.blit(hero_img2, (hero_PlaneX, hero_PlaneY))
shitindex = 0
else:
if hero_bomb_index == len(hero_bomb_imgs):
time.sleep(0.3)
exit()
hero_bomb_img = pygame.image.load(hero_bomb_imgs[hero_bomb_index])
screen.blit(hero_bomb_img, (hero_PlaneX, hero_PlaneY)) # 绘制爆炸图片
hero_bomb_index += 1
time.sleep(0.09)
# 对事件进行监听 获取所有事件
event_list = pygame.event.get()
#捕捉窗口退出事件
for event in event_list:
if event.type == pygame.QUIT: # 加上这个模块就不卡了
print("游戏结束了.......")
pygame.quit() # 卸载模块
exit(0) # 终止Python程序, exit(0)表示正常退出 exit(1)表示异常退出
# 控制英雄精灵移动
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
hero_PlaneX = hero_PlaneX - 5 if hero_PlaneX >= 5 else 0
elif event.key == pygame.K_RIGHT:
hero_PlaneX = hero_PlaneX + 5 if hero_PlaneX <= 375 else 380
elif event.key == pygame.K_DOWN:
hero_PlaneY = hero_PlaneY + 5 if hero_PlaneY <= 521 else 526
elif event.key == pygame.K_UP:
hero_PlaneY = hero_PlaneY - 5 if hero_PlaneY >= 5 else 0
elif event.key == pygame.K_SPACE:
#调用子弹的方法属性
hero_bullet=HeroBullet(hero_PlaneX+50,hero_PlaneY-11,screen)
#把子弹放入列表中 子弹是多个 我们将多个实例化的子弹放表中
hero_Bulletlist.append(hero_bullet)
for bullet in hero_Bulletlist:
bullet.draw()
#让子弹到最上面的时候消失
hero_Bulletlist.remove(bullet) if bullet.y < 0 else ''
# 定义英雄子弹rect
hero_bullet_rect = pygame.rect.Rect(bullet.x, bullet.y, 5, 11)
# 碰撞检测
flag = hero_bullet_rect.colliderect(enemy_rect)
if flag:
print("敌机爆炸")
enemy_bomb = True
hero_Bulletlist.remove(bullet)
if enemy_bomb == False:
#切换图片, # 绘制敌机图片
if enemy_bomb_index == 0:
screen.blit(enemy_img, (enemyPlaneX, enemyPlaneY))
enemy_bomb_index = 1
else:
screen.blit(enemy_img2, (enemyPlaneX, enemyPlaneY))
enemy_bomb_index = 0
else:
if enemy_bomb_index == len(enemy_bomb_imgs):
# 当敌机爆炸索引与图片总数相同时,退出游戏
time.sleep(0.2)
exit(0)
enemy_bomb_img = pygame.image.load(enemy_bomb_imgs[enemy_bomb_index])
screen.blit(enemy_bomb_img, (enemyPlaneX, enemyPlaneY)) # 绘制爆炸图片
enemy_bomb_index += 1
time.sleep(0.2)
# 图片更新
pygame.display.update()
# pygame.quit()