#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 导入需要使用的模块
importpygame
frompygame.localsimport*
fromsysimportexit
importrandom
# 设置屏幕大小的变量
SCREEN_WIDTH=480
SCREEN_HEIGHT=800
importcodecs
# 子弹类
classBullet(pygame.sprite.Sprite):
def__init__(self,bullet_img,init_pos):
# 实现父类的初始化方法
pygame.sprite.Sprite.__init__(self)
self.image=bullet_img
self.rect=self.image.get_rect()
self.rect.midbottom=init_pos
self.speed=10
defmove(self):
self.rect.top-=self.speed
# 玩家飞机类
classPlayer(pygame.sprite.Sprite):
def__init__(self,plane_img,player_rect,init_pos):
pygame.sprite.Sprite.__init__(self)
self.image=[]
foriinrange(len(player_rect)):
self.image.append(plane_img.subsurface(player_rect[i]).convert_alpha())
self.rect=player_rect[0]
self.rect.topleft=init_pos
self.speed=8
self.bullets=pygame.sprite.Group()#玩家飞机发射子弹的集合
self.img_index=0
self.is_hit=False
# 发射子弹
defshoot(self,bullet_img):
bullet=Bullet(bullet_img,self.rect.midtop)
self.bullets.add(bullet)# 将子弹放入玩家飞机的子弹集合
# 向上移动
defmoveUp(self):
ifself.rect.top<=0:
self.rect.top=0
else:
self.rect.top-=self.speed
# 向下移动
defmoveDown(self):
ifself.rect.top>=SCREEN_HEIGHT-self.rect.height:
self.rect.top=SCREEN_HEIGHT-self.rect.height
else:
self.rect.top+=self.speed
# 向左移动
defmoveLeft(self):
ifself.rect.left<=0:
self.rect.left=0
else:
self.rect.left-=self.speed
# 向右移动
defmoveRight(self):
ifself.rect.left>=SCREEN_WIDTH-self.rect.width:
self.rect.left=SCREEN_WIDTH-self.rect.width
else:
self.rect.left+=self.speed
# 敌机类
classEnemy(pygame.sprite.Sprite):
# 飞机的图片 敌机坠毁的图片 敌机的位置
def__init__(self,enemy_img,enemy_down_imgs,init_pos):
pygame.sprite.Sprite.__init__(self)
self.image=enemy_img
self.rect=self.image.get_rect()
self.rect.topleft=init_pos
self.down_imgs=enemy_down_imgs
self.speed=2
self.down_index=0
# 移动
defmove(self):
self.rect.top+=self.speed
# 对文件的操作
# 写入文本
# 要写入的内容,写入方式,写入文件所在的位置
defwrite_txt(contert,strim,path):
f=codecs.open(path,strim,'utf8')
f.write(str(contert))
f.close()
# 读取文本
defread_txt(path):
withopen(path,'r',encoding='utf8')asf:
lines=f.readlines()
returnlines
# 初始化pygame
pygame.init()
# 设置游戏界面的大小,背景图片,标题
# 界面startGame(
screen=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
# 标题
pygame.display.set_caption('飞机大战')
# 图标
ic_launcher=pygame.image.load('resources/image/ic_launcher.png').convert_alpha()
pygame.display.set_icon(ic_launcher)
# 背景图
background=pygame.image.load('resources/image/background.png').convert()
# 游戏结束
game_over=pygame.image.load('resources/image/gameover.png')
# 飞机及子弹的图片
plane_img=pygame.image.load('resources/image/shoot.png')
defstartGame():
# 1.设置玩家飞机不同状态的图片列表,多张图片展示为动画效果
player_rect=[]
# 玩家飞机的图片
player_rect.append(pygame.Rect(0,99,102,126))
player_rect.append(pygame.Rect(165,360,102,126))
# 玩家飞机爆炸的图片
player_rect.append(pygame.Rect(165,234,102,126))
player_rect.append(pygame.Rect(330,634,102,126))
player_rect.append(pygame.Rect(330,498,102,126))
player_rect.append(pygame.Rect(432,624,102,126))
player_pos=[200,600]
# 生成玩家飞机类
player=Player(plane_img,player_rect,player_pos)
# 加入子弹的图片
bullet_rect=pygame.Rect(69,77,10,21)
bullet_img=plane_img.subsurface(bullet_rect)
# 加入敌机图片
enemy1_rect=pygame.Rect(534,612,57,43)#没有爆炸前的图片
enemy1_img=plane_img.subsurface(enemy1_rect)
enemy1_down_imgs=[]#飞机销毁后的图片
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(267,347,57,43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(873,679,57,43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(267,296,57,43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(930,697,57,43)))
# 存储敌机的集合
enmies1=pygame.sprite.Group()
# 存储被击毁的敌机的集合
enemies_down=pygame.sprite.Group()
# 初始子弹射击频率
shoot_frequency=0
# 初始化敌机生成频率
enemy_frequency=0
# 玩家飞机被击中后的效果处理
player_down_index=16
# 设置游戏的帧数
clock=pygame.time.Clock()
# 初始化成绩
score=0
# 判断循环结束的参数
running=True
whilerunning:
foreventinpygame.event.get():
ifevent.type==pygame.QUIT:
exit()
screen.fill(0)
screen.blit(background,(0,0))
clock.tick(60)
# 生成子弹 判断玩家有没有被击中
ifnotplayer.is_hit:
ifshoot_frequency%15==0:
player.shoot(bullet_img)
shoot_frequency+=1
ifshoot_frequency>=15:
shoot_frequency=0
forbulletinplayer.bullets:
bullet.move()
ifbullet.rect.bottom<0:
player.bullets.remove(bullet)
# 显示子弹
player.bullets.draw(screen)
# 生成敌机,..需要控制频率
ifenemy_frequency%50==0:
#生成随机的位置
enemy1_pos=[random.randint(0,SCREEN_WIDTH-enemy1_rect.width),0]
# 初始化敌机
enemy1=Enemy(enemy1_img,enemy1_down_imgs,enemy1_pos)
# 存储到集合中
enmies1.add(enemy1)
enemy_frequency+=1
# 敌机生成到 100 则重新循环
ifenemy_frequency>=100:
enemy_frequency=0
# 敌机的移动
forenemyinenmies1:
enemy.move()
# 敌机与玩家碰撞效果处理
ifpygame.sprite.collide_circle(enemy,player):# pygame判定是否相撞的方法
enemies_down.add(enemy)# 将敌机加入到坠毁的集合中
enmies1.remove(enemy)# 从敌机集合中移除
player.is_hit=True
break
# 移动出屏幕的敌机
ifenemy.rect.top<0:
enmies1.remove(enemy)
# 与子弹碰撞
enemies1_down=pygame.sprite.groupcollide(enmies1,player.bullets,1,1)
forenemy_downinenemies1_down:
enemies_down.add(enemy_down)
# 绘制玩家飞机
ifnotplayer.is_hit:
screen.blit(player.image[player.img_index],player.rect)
# 实现飞机动效
player.img_index=shoot_frequency// 8
else:
# 玩家飞机被击毁后的动画效果
player.img_index=player_down_index// 8
screen.blit(player.image[player.img_index],player.rect)
player_down_index+=1
ifplayer_down_index>47:
running=False
# 敌机被击中的效果
forenemy_downinenemies_down:
ifenemy_down.down_index==0:
pass
ifenemy_down.down_index>7:
enemies_down.remove(enemy_down)
score+=100
continue
# 绘制碰撞动画
screen.blit(enemy_down.down_imgs[enemy_down.down_index// 2],enemy_down.rect)
enemy_down.down_index+=1
# 显示敌机
enmies1.draw(screen)
# 绘制当前得分
score_font=pygame.font.Font(None,36)
score_text=score_font.render(str(score),True,(128,128,128))
text_rect=score_text.get_rect()
text_rect.topleft=[10,10]
screen.blit(score_text,text_rect)
# 获取键盘的输入
key_pressed=pygame.key.get_pressed()
ifkey_pressed[K_UP]orkey_pressed[K_w]:
player.moveUp()
ifkey_pressed[K_DOWN]orkey_pressed[K_s]:
player.moveDown()
ifkey_pressed[K_LEFT]orkey_pressed[K_a]:
player.moveLeft()
ifkey_pressed[K_RIGHT]orkey_pressed[K_d]:
player.moveRight()
pygame.display.update()
# 绘制游戏结束画面
screen.blit(game_over,(0,0))
# 绘制Game Over显示最终分数
font=pygame.font.Font(None,48)
text=font.render("Score:"+str(score),True,(255,0,0))
text_rect=text.get_rect()
text_rect.centerx=screen.get_rect().centerx# x轴位置
text_rect.centery=screen.get_rect().centery+24# y轴位置
screen.blit(text,text_rect)
# 使用字体
xtfont=pygame.font.SysFont("jamrul",30)
# 绘制重新开始按钮
textstart=xtfont.render('Start',True,(255,0,0))
text_rect=textstart.get_rect()
text_rect.centerx=screen.get_rect().centerx# x轴位置
text_rect.centery=screen.get_rect().centery+120# y轴位置
screen.blit(textstart,text_rect)
# 排行榜按钮
textstart=xtfont.render('Ranking',True,(255,0,0))
text_rect=textstart.get_rect()
text_rect.centerx=screen.get_rect().centerx# x轴位置
text_rect.centery=screen.get_rect().centery+180# y轴位置
screen.blit(textstart,text_rect)
# 判断得分更新排行榜
# 临时变量
j=0
# 读取文件
arrayscore=read_txt(r'score.txt')[0].split('mr')
# 循环分数列表在列表里排序
foriinrange(0,len(arrayscore)):
ifscore>int(arrayscore[i]):
# 大于排行榜上的内容 把分数和当前分数进行替换
j=arraysco.re[i]
arrayscore[i]=str(score)
score=0
# 替换下来的分数移动一位
ifint(j)>int(arrayscore[i]):
k=arrayscore[i]
arrayscore[i]=str(j)
j=k
# 循环分数列表 写入文档
foriinrange(0,len(arrayscore)):
# 判断列表的第一个分数
ifi==0:
write_txt(arrayscore[i]+'mr','w',r'score.txt')
else:
# 判断是否是最后一个
if(i==9):
# 最近添加内容最后一个分数不加 mr
write_txt(arrayscore[i],'a',r'score.txt')
else:
# 不是最后一个分数,添加的时候加 mr
write_txt(arrayscore[i]+'mr','a',r'score.txt')
# 定义排行榜函数
defgameRanking():
# 绘制背景图片
screen2=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
screen2.fill(0)
screen2.blit(background,(0,0))
# 使用系统字体
xtfont=pygame.font.SysFont('jamrul',30)
# 1.绘制标题
textstart=xtfont.render('Ranking',True,(255,0,0))
text_rect=textstart.get_rect()
text_rect.centerx=screen.get_rect().centerx# x轴位置
text_rect.centery=50# y轴位置
screen.blit(textstart,text_rect)
# 2.绘制重新开始按钮
textstart=xtfont.render('Start',True,(255,0,0))
text_rect=textstart.get_rect()
text_rect.centerx=screen.get_rect().centerx# x轴位置
text_rect.centery=screen.get_rect().centery+120# y轴位置
screen.blit(textstart,text_rect)
# 3.展示排行榜的数据
arrayscore=read_txt(r'score.txt')[0].split('mr')
foriinrange(0,len(arrayscore)):
font=pygame.font.Font(None,48)
# 编写排名
k=i+1
text=font.render(str(k)+" "+arrayscore[i],True,(255,0,0))
text_rect=text.get_rect()
text_rect.centerx=screen2.get_rect().centerx
text_rect.centery=80+30*k
# 绘制分数
screen2.blit(text,text_rect)
startGame()
whileTrue:
foreventinpygame.event.get():
ifevent.type==pygame.QUIT:
exit()
# 监控鼠标的点击
elifevent.type==pygame.MOUSEBUTTONDOWN:
# 判定重新开始范围
ifscreen.get_rect().centerx-70<=event.pos[0]\
andevent.pos[0]<=screen.get_rect().centerx+50\
andscreen.get_rect().centery+100<=event.pos[1]\
andscreen.get_rect().centery+140>=event.pos[1]:
startGame()
# 判定排行榜范围
ifscreen.get_rect().centerx-70<=event.pos[0]\
andevent.pos[0]<=screen.get_rect().centerx+50\
andscreen.get_rect().centery+160<=event.pos[1]\
andscreen.get_rect().centery+200>=event.pos[1]:
gameRanking()
pygame.display.update()