• 【pyhon】利用pygame实现彩图版飞机大战(附源码 可供大作业练习使用)


    源码请点赞关注收藏后评论区留言或私信博主

    演示视频已上传到我的主页 有需要者可自行观看 

    演示视频如下:

     

    接下来先介绍一下游戏的玩法

    在PyCharm中运行《彩图版飞机大战》即可进入如图1所示的游戏界面。

     

    具体的操作步骤如下:

    (1)玩游戏。在游戏主界面中,从屏幕的顶部不断出现下落的敌机,玩家按下键盘上的↑、↓、←、→方向键移动飞机的位置并且发射子弹打掉敌机,每打掉一只敌机得100分。当玩家飞机与敌机发生碰撞时游戏结束,同时显示游戏得分以及排行榜按钮,游戏结束界面如图2所示。

     

    图2  游戏结束界面

    (2)查看排行榜。在游戏结束界面中,单击“排行榜”按钮,将显示排行榜界面,如图3所示。在该界面中,如果想重新玩游戏,可以单击“重新开始”按钮。

     

    图3  游戏排行榜界面

    程序结构如下1:子弹类

    2:玩家飞机类

    3:敌机类

    4:然后对文件的读写操作

    5:对于背景图片的读入和初始化方法

    6:排行榜函数等等

    score.txt文件中内容如下

    14200mr12500mr11600mr10300mr6700mr6500mr4300mr4200mr4100mr4100

    部分源代码如下

    1. # -*- coding: utf-8 -*-
    2. import pygame # 导入pygame库
    3. from pygame.locals import * # 导入pygame库中的一些常量
    4. from sys import exit # 导入sys库中的exit函数
    5. import random
    6. import codecs
    7. # 设置游戏屏幕大小
    8. SCREEN_WIDTH = 480
    9. SCREEN_HEIGHT = 800
    10. # 子弹类
    11. class Bullet(pygame.sprite.Sprite):
    12. def __init__(self, bullet_img, init_pos):
    13. # 调用了父类的初始化方法来初始化sprite的属性
    14. self.rect = self.image.get_rect()
    15. self.rect.midbottom = init_pos
    16. self.speed = 10
    17. def move(self):
    18. self.rect.top -= self.speed
    19. # 玩家飞机类
    20. class Player(pygame.sprite.Sprite):
    21. def __init__(self, player_rect, init_pos):
    22. 用来存储玩家飞机图片的列表
    23. for i in range(len(player_rect)):
    24. self.image.append(player_rect[i].convert_alpha())
    25. self.rect = player_rect[0].get_rect() # 初始化图片所在的矩形
    26. self.rect.topleft = init_pos # 初始化矩形的左上角坐标
    27. self.speed = 8 # 初始化玩家飞机速度,这里是一个确定的值
    28. self.bullets = pygame.sprite.Group() # 玩家飞机所发射的子弹的集合
    29. self.img_index = 0 # 玩家飞机图片索引
    30. self.is_hit = False # 玩家是否被击中
    31. # 发射子弹
    32. def shoot(self, bullet_img):
    33. bullet = Bullet(bullet_img, self.rect.midtop)
    34. self.bullets.add(bullet)
    35. # 向上移动,需要判断边界
    36. def moveUp(self):
    37. if self.rect.top <= 0:
    38. self.rect.top = 0
    39. else:
    40. self.rect.top -= self.speed
    41. # 向下移动,需要判断边界
    42. def moveDown(self):
    43. if self.rect.top >= SCREEN_HEIGHT - self.rect.height:
    44. self.rect.top = SCREEN_HEIGHT - self.rect.height
    45. else:
    46. self.rect.top += self.speed
    47. # 向左移动,需要判断边界
    48. def moveLeft(self):
    49. if self.rect.left <= 0:
    50. self.rect.left = 0
    51. else:
    52. self.rect.left -= self.speed
    53. # 向右移动,需要判断边界
    54. def moveRight(self):
    55. if self.rect.left >= SCREEN_WIDTH - self.rect.width:
    56. self.rect.left = SCREEN_WIDTH - self.rect.width
    57. else:
    58. self.rect.left += self.speed
    59. # 敌机类
    60. class Enemy(pygame.sprite.Sprite):
    61. def __init__(self, enemy_img, enemy_down_imgs, init_pos):
    62. pygame.sprite.Sprite.__init__(self)
    63. self.image = enemy_img
    64. self.rect = self.image.get_rect()
    65. self.rect.topleft = init_pos
    66. self.down_imgs = enemy_down_imgs
    67. self.speed = 2
    68. self.down_index = 0
    69. # 敌机移动,边界判断及删除在游戏主循环里处理
    70. def move(self):
    71. self.rect.top += self.speed
    72. """
    73. 对文件的操作
    74. 写入文本:
    75. 传入参数为content,strim,path;content为需要写入的内容,数据类型为字符串。
    76. path为写入的位置,数据类型为字符串。strim写入方式
    77. 传入的path需如下定义:path= r’ D:\text.txt’
    78. f = codecs.open(path, strim, 'utf8')中,codecs为包,需要用impor引入。
    79. strim=’a’表示追加写入txt,可以换成’w’,表示覆盖写入。
    80. 'utf8'表述写入的编码,可以换成'utf16'等。
    81. """
    82. def write_txt(content, strim, path):
    83. f = codecs.open(path, strim, 'utf8')
    84. f.write(str(content))
    85. f.close()
    86. """
    87. 读取txt:
    88. 表示按行读取txt文件,utf8表 示读取编码为utf8的文件,可以根据需求改成utf16,或者GBK等。
    89. 返回的为数组,每一个数组的元素代表一行,
    90. 若想返回字符串格式,可以将改写成return ‘\n’.join(lines)
    91. """
    92. def read_txt(path):
    93. with open(path, 'r', encoding='utf8') as f:
    94. lines = f.readlines()
    95. return lines
    96. # 初始化 pygame
    97. pygame.init()
    98. # 设置游戏界面大小
    99. screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    100. # 游戏界面标题
    101. pygame.display.set_caption('彩图版飞机大战')
    102. # 图标
    103. ic_launcher = pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\ic_launcher.png').convert_alpha()
    104. pygame.display.set_icon(ic_launcher)
    105. # 背景图
    106. background = pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\background.png').convert_alpha()
    107. # 游戏结束背景图
    108. game_over = pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\gameover.png')
    109. # 子弹图片
    110. plane_bullet = pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\bullet.png')
    111. # 飞机图片
    112. player_img1= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\player1.png')
    113. player_img2= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\player2.png')
    114. player_img3= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\player_off1.png')
    115. player_img4= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\player_off2.png')
    116. player_img5= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\player_off3.png')
    117. # 敌机图片
    118. enemy_img1= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\enemy1.png')
    119. enemy_img2= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\enemy2.png')
    120. enemy_img3= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\enemy3.png')
    121. enemy_img4= pygame.image.load(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\resources\image\enemy4.png')
    122. # 开始游戏方法
    123. def startGame():
    124. # 设置玩家飞机不同状态的图片列表,多张图片展示为动画效果
    125. player_rect = []
    126. # 玩家飞机图片
    127. player_rect.append(player_img1)
    128. player_rect.append(player_img2)
    129. # 玩家爆炸图片
    130. player_rect.append(player_img2)
    131. player_rect.append(player_img3)
    132. player_rect.append(player_img4)
    133. player_rect.append(player_img5)
    134. player_pos = [200, 600]
    135. # 初始化玩家飞机
    136. player = Player(player_rect, player_pos)
    137. # 子弹图片
    138. bullet_img = plane_bullet
    139. # 敌机不同状态的图片列表,多张图片展示为动画效果
    140. enemy1_img = enemy_img1
    141. enemy1_rect=enemy1_img.get_rect()
    142. enemy1_down_imgs = []
    143. enemy1_down_imgs.append(enemy_img1)
    144. enemy1_down_imgs.append(enemy_img2)
    145. enemy1_down_imgs.append(enemy_img3)
    146. enemy1_down_imgs.append(enemy_img4)
    147. # 储存敌机
    148. enemies1 = pygame.sprite.Group()
    149. # 存储被击毁的飞机,用来渲染击毁动画
    150. enemies_down = pygame.sprite.Group()
    151. # 初始化射击及敌机移动频率
    152. shoot_frequency = 0
    153. enemy_frequency = 0
    154. # 玩家飞机被击中后的效果处理
    155. player_down_index = 16
    156. # 初始化分数
    157. score = 0
    158. # 游戏循环帧率设置
    159. clock = pygame.time.Clock()
    160. # 判断游戏循环退出的参数
    161. running = True
    162. # 游戏主循环
    163. while running:
    164. # 绘制背景
    165. screen.fill(0)
    166. screen.blit(background, (0, 0))
    167. # 控制游戏最大帧率为 60
    168. clock.tick(60)
    169. # 生成子弹,需要控制发射频率
    170. # 首先判断玩家飞机没有被击中
    171. if not player.is_hit:
    172. if shoot_frequency % 15 == 0:
    173. player.shoot(bullet_img)
    174. shoot_frequency += 1
    175. if shoot_frequency >= 15:
    176. shoot_frequency = 0
    177. for bullet in player.bullets:
    178. # 以固定速度移动子弹
    179. bullet.move()
    180. # 移动出屏幕后删除子弹
    181. if bullet.rect.bottom < 0:
    182. player.bullets.remove(bullet)
    183. # 显示子弹
    184. player.bullets.draw(screen)
    185. # 生成敌机,需要控制生成频率
    186. if enemy_frequency % 50 == 0:
    187. enemy1_pos = [random.randint(0, SCREEN_WIDTH - enemy1_rect.width), 0]
    188. enemy1 = Enemy(enemy1_img, enemy1_down_imgs, enemy1_pos)
    189. enemies1.add(enemy1)
    190. enemy_frequency += 1
    191. if enemy_frequency >= 100:
    192. enemy_frequency = 0
    193. for enemy in enemies1:
    194. # 移动敌机
    195. enemy.move()
    196. # 敌机与玩家飞机碰撞效果处理 两个精灵之间的圆检测
    197. if pygame.sprite.collide_circle(enemy, player):
    198. enemies_down.add(enemy)
    199. enemies1.remove(enemy)
    200. player.is_hit = True
    201. break
    202. # 移动出屏幕后删除飞机
    203. if enemy.rect.top < 0:
    204. enemies1.remove(enemy)
    205. # 敌机被子弹击中效果处理
    206. # 将被击中的敌机对象添加到击毁敌机 Group 中,用来渲染击毁动画
    207. # 方法groupcollide()是检测两个精灵组中精灵们的矩形冲突
    208. enemies1_down = pygame.sprite.groupcollide(enemies1, player.bullets, 1, 1)
    209. # 遍历key值 返回的碰撞敌机
    210. for enemy_down in enemies1_down:
    211. # 点击销毁的敌机到列表
    212. enemies_down.add(enemy_down)
    213. # 绘制玩家飞机
    214. if not player.is_hit:
    215. screen.blit(player.image[player.img_index], player.rect)
    216. # 更换图片索引使飞机有动画效果
    217. player.img_index = shoot_frequency // 8
    218. else:
    219. # 玩家飞机被击中后的效果处理
    220. player.img_index = player_down_index // 8
    221. screen.blit(player.image[player.img_index], player.rect)
    222. player_down_index += 1
    223. if player_down_index > 47:
    224. # 击中效果处理完成后游戏结束
    225. running = False
    226. # 敌机被子弹击中效果显示
    227. for enemy_down in enemies_down:
    228. if enemy_down.down_index == 0:
    229. pass
    230. if enemy_down.down_index > 7:
    231. enemies_down.remove(enemy_down)
    232. score += 100
    233. continue
    234. #显示碰撞图片
    235. screen.blit(enemy_down.down_imgs[enemy_down.down_index // 2], enemy_down.rect)
    236. enemy_down.down_index += 1
    237. # 显示精灵
    238. enemies1.draw(screen)
    239. # 绘制当前得分
    240. score_font = pygame.font.Font(None, 36)
    241. score_text = score_font.render(str(score), True, (255, 255, 255))
    242. text_rect = score_text.get_rect()
    243. text_rect.topleft = [10, 10]
    244. screen.blit(score_text, text_rect)
    245. # 更新屏幕
    246. pygame.display.update()
    247. # 处理游戏退出
    248. for event in pygame.event.get():
    249. if event.type == pygame.QUIT:
    250. pygame.quit()
    251. exit()
    252. # 获取键盘事件(上下左右按键)
    253. key_pressed = pygame.key.get_pressed()
    254. # 处理键盘事件(移动飞机的位置)
    255. if key_pressed[K_w] or key_pressed[K_UP]:
    256. player.moveUp()
    257. if key_pressed[K_s] or key_pressed[K_DOWN]:
    258. player.moveDown()
    259. if key_pressed[K_a] or key_pressed[K_LEFT]:
    260. player.moveLeft()
    261. if key_pressed[K_d] or key_pressed[K_RIGHT]:
    262. player.moveRight()
    263. # 绘制游戏结束背景
    264. screen.blit(game_over, (0, 0))
    265. # 游戏 Game Over 后显示最终得分
    266. font = pygame.font.Font(None, 48)
    267. text = font.render('Score: ' + str(score), True, (255, 255, 255))
    268. text_rect = text.get_rect()
    269. text_rect.centerx = screen.get_rect().centerx
    270. text_rect.centery = screen.get_rect().centery + 24
    271. screen.blit(text, text_rect)
    272. # 使用系统字体
    273. xtfont = pygame.font.SysFont('SimHei', 30)
    274. # 重新开始按钮
    275. textstart = xtfont.render('重新开始 ', True, (255, 255, 255))
    276. text_rect = textstart.get_rect()
    277. text_rect.centerx = screen.get_rect().centerx
    278. text_rect.centery = screen.get_rect().centery + 120
    279. screen.blit(textstart, text_rect)
    280. # 排行榜按钮
    281. textstart = xtfont.render('排行榜 ', True, (255, 255, 255))
    282. text_rect = textstart.get_rect()
    283. text_rect.centerx = screen.get_rect().centerx
    284. text_rect.centery = screen.get_rect().centery + 180
    285. screen.blit(textstart, text_rect)
    286. # 判断得分更新排行榜
    287. # 临时的变量在到排行榜的时候使用
    288. j = 0
    289. #获取文件中内容转换成列表使用mr分割开内容
    290. arrayscore = read_txt(r'C:\Users\Admin\Desktop\23个 Code\23个 Code\Code\05彩图版飞机大战的程序\源程序\foo\score.txt')[0].split('mr')
    291. # 循环分数列表在列表里排序
    292. for i in range(0, len(arrayscore)):
    293. # 判断当前获得的分数是否大于排行榜上的分数
    294. if score > int(arrayscore[i]):
    295. # 大于排行榜上的内容 把分数和当前分数进行替换
    296. j = arrayscore[i]
    297. arrayscore[i] = str(score)
    298. score = 0
    299. # 替换下来的分数下移动一位
    300. if int(j) > int(arrayscore[i]):
    301. k = arrayscore[i]
    302. arrayscore[i] = str(j)
    303. j = k
    304. # 循环分数列表 写入文档
    305. for i in range(0, len(arrayscore)):
    306. # 判断列表中第一个分数
    307. if i == 0:
    308. # 覆盖写入内容追加mr方便分割内容
    309. write_txt(arrayscore[i] + 'mr', 'w', r'score.txt')
    310. else:
    311. # 判断是否为最后一个分数
    312. if (i == 9):
    313. # 最近添加内容最后一个分数不添加mr
    314. write_txt(arrayscore[i], 'a', r'score.txt')
    315. else:
    316. # 不是最后一个分数,添加的时候添加mr
    317. write_txt(arrayscore[i] + 'mr', 'a', r'score.txt')
    318. # 排行榜
    319. def gameRanking():
    320. screen2 = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    321. # 绘制背景
    322. screen2.fill(0)
    323. screen2.blit(background, (0, 0))
    324. # 使用系统字体
    325. xtfont = pygame.font.SysFont('SimHei', 30)
    326. # 重新开始按钮
    327. textstart = xtfont.render('排行榜 ', True, (255, 0, 0))
    328. text_rect = textstart.get_rect()
    329. text_rect.centerx = screen.get_rect().centerx
    330. text_rect.centery = 50
    331. screen.blit(textstart, text_rect)
    332. # 重新开始按钮
    333. textstart = xtfont.render('重新开始 ', True, (255, 0, 0))
    334. text_rect = textstart.get_rect()
    335. text_rect.centerx = screen.get_rect().centerx
    336. text_rect.centery = screen.get_rect().centery + 120
    337. screen2.blit(textstart, text_rect)
    338. # 获取排行文档内容
    339. arrayscore = read_txt(r'score.txt')[0].split('mr')
    340. # 循环排行榜文件显示排行
    341. for i in range(0, len(arrayscore)):
    342. # 游戏 Game Over 后显示最终得分
    343. font = pygame.font.Font(None, 48)
    344. # 排名重110
    345. k=i+1
    346. =
    347. exit()
    348. # 鼠标单击
    349. elif event.type == pygame.MOUSEBUTTONDOWN:
    350. # 判断鼠标单击的位置是否为开始按钮位置范围内
    351. if screen.get_rect().centerx - 70 <= event.pos[0] \
    352. and event.pos[0] <= screen.get_rect().centerx + 50 \
    353. and screen.get_rect().centery + 100 <= event.pos[1] \
    354. and screen.get_rect().centery + 140 >= event.pos[1]:
    355. # 重新开始游戏
    356. startGame()
    357. # 判断鼠标是否单击排行榜按钮
    358. if screen.get_rect().centerx - 70 <= event.pos[0] \
    359. and event.pos[0] <= screen.get_rect().centerx + 50 \
    360. and screen.get_rect().centery + 160 <= event.pos[1] \
    361. and screen.get_rect().centery + 200 >= event.pos[1]:
    362. # 显示排行榜
    363. gameRanking()
    364. # 更新界面
    365. pygame.display.update()

     

  • 相关阅读:
    【C++】运算符重载 ⑨ ( 等号 = 运算符重载 | 调用默认浅拷贝构造函数的情况分析 | 等号 = 运算符重载 与 拷贝构造函数 各自使用场景 | 等号 = 操作符重载步骤 )
    JVM
    总结flutter玩转之-安卓view 承载flutter 的页面
    aardio 调用 vs 编写的dll (stdcall方式) (dll又调用另一个dll)
    React + Springboot + Quartz,从0实现Excel报表自动化
    hive的安装配置笔记
    黑马点评-异步秒杀实现
    Grafana+Prometheus打造运维监控系统(一)-安装篇
    Mybatis的关系关联配置
    MySQL间隙锁深入分析
  • 原文地址:https://blog.csdn.net/jiebaoshayebuhui/article/details/127623998