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