当前位置:   article > 正文

用pygame做经典坦克大战游戏(附源码)_pygame 车 墙

pygame 车 墙

首先,我们得分析这个项目的结构,设计出它的框架

坦克大战游戏项目开发

    需求分析

    1.分析项目需要多少个类

    2.分析每个类有哪些方法

1.坦克类(敌方坦克,我方坦克)

    移动、射击、展示

2.子弹类

    移动、展示

3.墙壁类

    属性:是否可以通过

4.爆炸效果类

    展示

5.音效类

    播放音乐

6.主类

    开始游戏

    结束游戏

好了,直接上代码,不用担心看不懂,几乎每行都会有注释

  1. import pygame
  2. import time
  3. import random
  4. SCREEN_WIDTH = 800
  5. SCREEN_HEIGHT = 600
  6. BG_COLOR = pygame.Color(0,0,0)
  7. TEXT_COLOR = pygame.Color(255,0,0)
  8. #定义一个基类
  9. class BaseItem(pygame.sprite.Sprite):
  10. def __init__(self):
  11. pygame.sprite.Sprite.__init__(self)
  12. class MainGame():
  13. window = None
  14. my_tank = None
  15. #存储敌方坦克的列表
  16. enemyTankList = []
  17. #定义敌方坦克的数量
  18. enemyTankCount = 5
  19. #我方坦克子弹列表
  20. myBulletList = []
  21. #敌方坦克子弹列表
  22. enemyBulletList = []
  23. #坦克爆效果列表
  24. explodeList = []
  25. #墙壁列表
  26. wallList = []
  27. def __init__(self):
  28. pass
  29. #开始游戏
  30. def startGame(self):
  31. #加载主窗口
  32. #创建窗口对象
  33. pygame.display.init()
  34. #设置窗口的大小及显示
  35. MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
  36. #创建我方坦克
  37. self.creatMyTank()
  38. #初始化敌方坦克,并添加到列表中
  39. self.creatEnemyTank()
  40. # 初始化墙壁
  41. self.creatWall()
  42. #设置窗口标题
  43. pygame.display.set_caption('坦克大战1.0')
  44. while True:
  45. #让坦克的速度慢一点
  46. time.sleep(0.05)
  47. #给窗口设置填充色
  48. MainGame.window.fill(BG_COLOR)
  49. #获取事件
  50. self.getevent()
  51. #绘制文字
  52. MainGame.window.blit(self.getTextSurface('敌方坦克剩余数量:%d'%len(MainGame.enemyTankList)),(10,10))
  53. #调用显示坦克的方法
  54. #判断我方坦克是否存活
  55. if MainGame.my_tank and MainGame.my_tank.live:
  56. MainGame.my_tank.displayTank()
  57. else:
  58. #删除我方坦克
  59. del MainGame.my_tank
  60. MainGame.my_tank = None
  61. #循环坦克列表,进行展示
  62. self.blitEnemyTank()
  63. #循环我方子弹列表,进行展示
  64. self.blitMyBullet()
  65. # 循环敌方子弹列表,进行展示
  66. self.blitEnemyBullet()
  67. # 循环爆炸效果列表,进行展示
  68. self.blitExplode()
  69. # 循环墙壁列表,进行展示
  70. self.blitWall()
  71. #调用坦克移动的方法
  72. #如果坦克的开关是开 才可以启动
  73. if MainGame.my_tank and MainGame.my_tank.live:
  74. if not MainGame.my_tank.stop:
  75. MainGame.my_tank.move()
  76. #检测我方坦克是否与墙体发生碰撞
  77. MainGame.my_tank.tank_hit_wall()
  78. #检测我方坦克是否与敌方坦克发生碰撞
  79. MainGame.my_tank.myTank_hit_enemyTank()
  80. pygame.display.update()
  81. # 循环墙壁列表,进行展示
  82. def blitWall(self):
  83. for wall in MainGame.wallList:
  84. if wall.live:
  85. wall.displayWall()
  86. else:
  87. MainGame.wallList.remove(wall)
  88. # 初始化墙壁
  89. def creatWall(self):
  90. for i in range(6):
  91. wall = Wall(i*150,230)
  92. MainGame.wallList.append(wall)
  93. def creatMyTank(self):
  94. MainGame.my_tank = MyTank(300, 300)
  95. #初始化音乐
  96. music = Music('img/start.wav')
  97. #播放音乐
  98. music.play()
  99. # 循环爆炸效果列表,进行展示
  100. def blitExplode(self):
  101. for explode in MainGame.explodeList:
  102. #判断是否活着
  103. if explode.live:
  104. explode.displayExplode()
  105. else:
  106. MainGame.explodeList.remove(explode)
  107. #循环敌方坦克列表,进行展示
  108. def blitEnemyBullet(self):
  109. for EnenmyBullet in MainGame.enemyBulletList:
  110. # 判断当前子弹是否存活,是的话则展示
  111. if EnenmyBullet.live:
  112. EnenmyBullet.displayBullet()
  113. # 调用子弹移动的方法
  114. EnenmyBullet.move()
  115. #调用敌方子弹击中我方坦克的方法
  116. EnenmyBullet.enemyBullet_hit_myTank()
  117. #调用子弹碰撞墙壁的方法
  118. EnenmyBullet.bullet_hit_wall()
  119. else:
  120. # 删除子弹
  121. MainGame.enemyBulletList.remove(EnenmyBullet)
  122. # 循环我方子弹列表,进行展示
  123. def blitMyBullet(self):
  124. for MyBullet in MainGame.myBulletList:
  125. #判断当前子弹是否存活,是的话则展示
  126. if MyBullet.live:
  127. MyBullet.displayBullet()
  128. # 调用子弹移动的方法
  129. MyBullet.move()
  130. #调用我们子弹与敌方坦克发生碰撞的方法
  131. if MainGame.my_tank and MainGame.my_tank.live:
  132. MyBullet.myBullet_hit_enemyTank()
  133. # 调用子弹碰撞墙壁的方法
  134. MyBullet.bullet_hit_wall()
  135. else:
  136. #删除子弹
  137. MainGame.myBulletList.remove(MyBullet)
  138. #循环敌方坦克列表进行展示
  139. def blitEnemyTank(self):
  140. for enemyTank in MainGame.enemyTankList:
  141. #判断敌方坦克状态是否存活
  142. if enemyTank.live:
  143. enemyTank.displayTank()
  144. enemyTank.randMove()
  145. # 调用检测敌方坦克是否与墙体发生碰撞
  146. enemyTank.tank_hit_wall()
  147. # 调用检测敌方坦克是否与我方坦克发生碰撞
  148. if MainGame.my_tank and MainGame.my_tank.live:
  149. enemyTank.enemyTank_hit_MyTank()
  150. # 发射子弹
  151. enemyBullet = enemyTank.shoot()
  152. # 判断子弹的是否为None
  153. if enemyBullet:
  154. # 将敌方坦克子弹存储到子弹列表中
  155. MainGame.enemyBulletList.append(enemyBullet)
  156. else:
  157. MainGame.enemyTankList.remove(enemyTank)
  158. # 初始化敌方坦克,并添加到列表中
  159. def creatEnemyTank(self):
  160. top = 100
  161. #循环生成敌方坦克
  162. for i in range(MainGame.enemyTankCount):
  163. left = random.randint(1,700)
  164. speed = random.randint(1,7)
  165. enemy = EnemyTank(left,top,speed)
  166. MainGame.enemyTankList.append(enemy)
  167. #结束游戏
  168. def endGame(self):
  169. print('谢谢,欢迎下次使用')
  170. exit()
  171. #左上角的文字绘制
  172. def getTextSurface(self,text):
  173. #初始化字体模块
  174. pygame.font.init()
  175. #查看所有字体名称
  176. # print(pygame.font.get_fonts())
  177. #获取字体对象
  178. font = pygame.font.SysFont('kaiti',18)
  179. #绘制文本信息
  180. textSurface = font.render(text,True,TEXT_COLOR)
  181. return textSurface
  182. def getevent(self):
  183. #获取所有事件
  184. event_list = pygame.event.get()
  185. for event in event_list:
  186. #判断按下的是关闭还是键盘按下
  187. #如果是退出,关闭窗口
  188. if event.type == pygame.QUIT:
  189. self.endGame()
  190. #如果是键盘的按下
  191. if event.type == pygame.KEYDOWN:
  192. #当我方坦克不存在死亡时
  193. if not MainGame.my_tank:
  194. #判断按下的键是否ESC,是则重生
  195. if event.key == pygame.K_ESCAPE:
  196. self.creatMyTank()
  197. if MainGame.my_tank and MainGame.my_tank.live:
  198. # 判断按下的是上下左右
  199. if event.key == pygame.K_LEFT:
  200. # 切换方向
  201. MainGame.my_tank.direction = 'L'
  202. MainGame.my_tank.stop = False
  203. # MainGame.my_tank.move()
  204. print('按下的是左键,坦克向左移动')
  205. elif event.key == pygame.K_RIGHT:
  206. # 切换方向
  207. MainGame.my_tank.direction = 'R'
  208. MainGame.my_tank.stop = False
  209. # MainGame.my_tank.move()
  210. print('按下的是右键,坦克向右移动')
  211. elif event.key == pygame.K_UP:
  212. # 切换方向
  213. MainGame.my_tank.direction = 'U'
  214. MainGame.my_tank.stop = False
  215. # MainGame.my_tank.move()
  216. print('按下的是上键,坦克向上移动')
  217. elif event.key == pygame.K_DOWN:
  218. # 切换方向
  219. MainGame.my_tank.direction = 'D'
  220. MainGame.my_tank.stop = False
  221. # MainGame.my_tank.move()
  222. print('按下的是下键,坦克向下移动')
  223. elif event.key == pygame.K_SPACE:
  224. print('发射子弹')
  225. if len(MainGame.myBulletList) < 3:
  226. myBullet = Bullet(MainGame.my_tank)
  227. MainGame.myBulletList.append(myBullet)
  228. #加载音乐
  229. music = Music('img/fire.wav')
  230. music.play()
  231. #松开按键,坦克停止移动,修改坦克开关
  232. if event.type == pygame.KEYUP:
  233. #判断松开的是上下左右才停止移动
  234. if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
  235. if MainGame.my_tank and MainGame.my_tank.live:
  236. MainGame.my_tank.stop = True
  237. class Tank(BaseItem):
  238. #添加距离左边left,距离上边top
  239. def __init__(self,left,top):
  240. #保存加载的图片
  241. self.images = {'U':pygame.image.load('img/p1tankU.gif'),
  242. 'R':pygame.image.load('img/p1tankR.gif'),
  243. 'L':pygame.image.load('img/p1tankL.gif'),
  244. 'D':pygame.image.load('img/p1tankD.gif')
  245. }
  246. #方向
  247. self.direction = 'U'
  248. #根据当前图片方向获取图片的 surface
  249. self.image = self.images[self.direction]
  250. #根据图片获取区域
  251. self.rect = self.image.get_rect()
  252. #设置区域的 left 和 top
  253. self.rect.left = left
  254. self.rect.top = top
  255. #速度 决定移动的快慢
  256. self.speed = 10
  257. #坦克的开关
  258. self.stop = True
  259. #坦克存活状态
  260. self.live = True
  261. #坦克原来的坐标
  262. self.oldleft = self.rect.left
  263. self.oldtop = self.rect.top
  264. #移动
  265. def move(self):
  266. # 坦克原来的坐标
  267. self.oldleft = self.rect.left
  268. self.oldtop = self.rect.top
  269. #判断坦克的方向进行移动
  270. if self.direction == 'L':
  271. if self.rect.left >0:
  272. self.rect.left -= self.speed
  273. elif self.direction == 'R':
  274. if self.rect.left + self.rect.height < SCREEN_WIDTH:
  275. self.rect.left += self.speed
  276. elif self.direction == 'U':
  277. if self.rect.top >0:
  278. self.rect.top -= self.speed
  279. elif self.direction == 'D':
  280. if self.rect.top + self.rect.height < SCREEN_HEIGHT:
  281. self.rect.top += self.speed
  282. #射击
  283. def shoot(self):
  284. return Bullet(self)
  285. def stay(self):
  286. self.rect.left = self.oldleft
  287. self.rect.top = self.oldtop
  288. #坦克与墙体发生碰撞
  289. def tank_hit_wall(self):
  290. for wall in MainGame.wallList:
  291. if pygame.sprite.collide_rect(self,wall):
  292. #修改坦克的位置
  293. self.stay()
  294. #展示
  295. def displayTank(self):
  296. #获取展示的对象
  297. self.image = self.images[self.direction]
  298. #调用blit方法展示
  299. MainGame.window.blit(self.image,self.rect)
  300. class MyTank(Tank):
  301. def __init__(self,left,top):
  302. super(MyTank,self).__init__(left,top)
  303. pass
  304. #检测我方坦克与敌方坦克发生碰撞
  305. def myTank_hit_enemyTank(self):
  306. for enemy in MainGame.enemyTankList:
  307. if pygame.sprite.collide_rect(self,enemy):
  308. self.stay()
  309. class EnemyTank(Tank):
  310. def __init__(self,left,top,speed):
  311. #调用父类的初始化方法
  312. super(EnemyTank,self).__init__(left,top)
  313. #加载图片集
  314. self.images = {
  315. 'U':pygame.image.load('img/enemy1U.gif'),
  316. 'R':pygame.image.load('img/enemy1R.gif'),
  317. 'L':pygame.image.load('img/enemy1L.gif'),
  318. 'D':pygame.image.load('img/enemy1D.gif')
  319. }
  320. #方向 随机生成敌方坦克的方向
  321. self.direction = self.randDirection()
  322. #根据方向获取图片
  323. self.image = self.images[self.direction]
  324. #区域
  325. self.rect = self.image.get_rect()
  326. #对left和top赋值
  327. self.rect.left = left
  328. self.rect.top = top
  329. #速度
  330. self.speed = speed
  331. #移动开关
  332. self.flag = True
  333. #步数
  334. self.step = 30
  335. #敌方坦克与我方坦克发生碰撞
  336. def enemyTank_hit_MyTank(self):
  337. if pygame.sprite.collide_rect(self,MainGame.my_tank):
  338. self.stay()
  339. #随机生成敌方坦克的方向
  340. def randDirection(self):
  341. num = random.randint(1,4)
  342. if num == 1:
  343. return 'U'
  344. elif num == 2:
  345. return 'R'
  346. elif num == 3:
  347. return 'L'
  348. elif num == 4:
  349. return 'D'
  350. def randMove(self):
  351. if self.step <=0:
  352. #修改方向
  353. self.direction = self.randDirection()
  354. #恢复步数
  355. self.step = 40
  356. else:
  357. self.move()
  358. #步数递减
  359. self.step -= 1
  360. #重写shoot
  361. def shoot(self):
  362. num = random.randint(1,100)
  363. if num <= 5:
  364. return Bullet(self)
  365. class Explode():
  366. def __init__(self,tank):
  367. #爆炸效果位置由坦克被击中的位置决定
  368. self.rect = tank.rect
  369. #加载图片
  370. self.images = [
  371. pygame.image.load('img/blast0.gif'),
  372. pygame.image.load('img/blast1.gif'),
  373. pygame.image.load('img/blast2.gif'),
  374. pygame.image.load('img/blast3.gif'),
  375. pygame.image.load('img/blast4.gif')
  376. ]
  377. self.step = 0
  378. self.image = self.images[self.step]
  379. self.live = True
  380. #展示爆炸效果
  381. def displayExplode(self):
  382. if self.step < len(self.images):
  383. #根据索引获取爆炸对象
  384. self.image = self.images[self.step]
  385. self.step += 1
  386. #添加到主窗口
  387. MainGame.window.blit(self.image,self.rect)
  388. else:
  389. #修改活着的状态
  390. self.live = False
  391. self.step = 0
  392. class Wall():
  393. def __init__(self,left,top):
  394. #加载图片
  395. self.image = pygame.image.load('img/steels.gif')
  396. #获取区域
  397. self.rect = self.image.get_rect()
  398. #设置位置
  399. self.rect.left = left
  400. self.rect.top = top
  401. #设置存活状态
  402. self.live = True
  403. #设置生命值
  404. self.hp = 5
  405. #展示墙的效果
  406. def displayWall(self):
  407. MainGame.window.blit(self.image,self.rect)
  408. class Music():
  409. def __init__(self,filename):
  410. self.filename = filename
  411. #初始化混合器的方法
  412. pygame.mixer.init()
  413. #加载音乐
  414. pygame.mixer.music.load(self.filename)
  415. #播放音乐
  416. def play(self):
  417. pygame.mixer.music.play()
  418. class Bullet(BaseItem):
  419. def __init__(self,tank):
  420. #加载图片
  421. self.image = pygame.image.load('img/enemymissile.gif')
  422. #坦克的方向决定子弹的方向
  423. self.direction = tank.direction
  424. #获取区域
  425. self.rect = self.image.get_rect()
  426. #子弹的left和top和坦克方向有关
  427. if self.direction == 'U':
  428. self.rect.left = tank.rect.left + tank.rect.width/2 - self.rect.width/2
  429. self.rect.top = tank.rect.top - self.rect.height
  430. elif self.direction == 'D':
  431. self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
  432. self.rect.top = tank.rect.top + tank.rect.height
  433. elif self.direction == 'L':
  434. self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2
  435. self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
  436. elif self.direction == 'R':
  437. self.rect.left = tank.rect.left + tank.rect.width
  438. self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
  439. # 速度
  440. self.speed = 10
  441. # 用来记录子弹是否活着
  442. self.live = True
  443. #移动
  444. def move(self):
  445. if self.direction == 'U':
  446. if self.rect.top >0:
  447. self.rect.top -= self.speed
  448. else:
  449. #碰到墙壁,修改存活状态
  450. self.live = False
  451. elif self.direction == 'R':
  452. if self.rect.left + self.rect.width < SCREEN_WIDTH:
  453. self.rect.left += self.speed
  454. else:
  455. # 碰到墙壁,修改存活状态
  456. self.live = False
  457. elif self.direction == 'L':
  458. if self.rect.left >0:
  459. self.rect.left -= self.speed
  460. else:
  461. # 碰到墙壁,修改存活状态
  462. self.live = False
  463. elif self.direction == 'D':
  464. if self.rect.top + self.rect.height < SCREEN_HEIGHT:
  465. self.rect.top += self.speed
  466. else:
  467. # 碰到墙壁,修改存活状态
  468. self.live = False
  469. # 我方子弹与敌方坦克发生碰撞
  470. def myBullet_hit_enemyTank(self):
  471. # 遍历敌方坦克的列表,判断是否发生碰撞
  472. for enemyTank in MainGame.enemyTankList:
  473. if pygame.sprite.collide_rect(enemyTank, self):
  474. # 修改敌方坦克和我方子弹的状态
  475. enemyTank.live = False
  476. self.live = False
  477. #创建爆炸对象
  478. explode = Explode(enemyTank)
  479. #将爆炸对象添加到列表中
  480. MainGame.explodeList.append(explode)
  481. #敌方子弹与我方坦克发生碰撞
  482. def enemyBullet_hit_myTank(self):
  483. if MainGame.my_tank and MainGame.my_tank.live:
  484. if pygame.sprite.collide_rect(MainGame.my_tank, self):
  485. # 创建爆炸对象
  486. explode = Explode(MainGame.my_tank)
  487. # 将爆炸对象添加到列表中
  488. MainGame.explodeList.append(explode)
  489. # 修改我方坦克和敌方方子弹的状态
  490. MainGame.my_tank.live = False
  491. self.live = False
  492. #子弹与墙发生碰撞
  493. def bullet_hit_wall(self):
  494. #循环墙的列表
  495. for wall in MainGame.wallList:
  496. if pygame.sprite.collide_rect(self,wall):
  497. #修改子弹的状态
  498. self.live = False
  499. #修改墙的生命值
  500. wall.hp -= 1
  501. if wall.hp <= 0:
  502. #修改墙的状态
  503. wall.live = False
  504. #展示
  505. def displayBullet(self):
  506. MainGame.window.blit(self.image,self.rect)
  507. if __name__ == '__main__':
  508. MainGame().startGame()
  509. # MainGame().getTextSuface()

最终效果如下

 ps:代码中的敌方坦克数量,墙体数量等都是自定义的,我方坦克阵亡后按ESC键重生!

以上代码中的图片素材与py文件必须要对应!

以上代码中的图片素材与py文件必须要对应!

以上代码中的图片素材与py文件必须要对应!

重要的事情说三遍!

游戏里的素材私信我

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/513738
推荐阅读
相关标签
  

闽ICP备14008679号