Pygame游戏引擎的安装

  1. doc窗口直接使用pip安装

win +r —>cmd—>输入:
pip install pygame
(unintall是卸载)
image.png

image.png
image.png

  1. 下载whl文件进行安装

进入官网,点击PyPI
image.png

  1. 输入pygame

image.png

  1. 选择pygame

image.png

  1. 选择Download files

image.png

  1. 选择自己对应的版本

image.png
image.pngimage.png

  1. 下载后进行安装

image.png
进入下载的文件目录,输入命令安装

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