python3坦克大战
2019-07-07 19:20
211 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dycjnb/article/details/95017390
# coding = utf-8 import pygame, sys, time from pygame.locals import * from random import randint '''坦克大战主窗口''' class TankMain(object): width = 700 height = 600 wall_list = [] my_tank = None home = None lives = 3 # enemy_list = [] # 敌方坦克列表 enemy_list = pygame.sprite.Group() # 敌方坦克(精灵)族群 my_tank_missile = [] # 我方子弹列表 enemy_tank_missile = pygame.sprite.Group() # 敌方子弹(精灵)族群 explode_list = [] # 爆炸效果列表 # 开始游戏 def startGame(self): # 开始游戏 pygame.init() # pygame模块初始化,加载系统资源 # 设置一个窗口,第一个参数:(宽,高),第二个参数:窗口可变{0,RESIZABLE,FULLSCREEM,..},第三个参数:颜色位数{32,64,..} # screem是一个Surface表面对象 screem = pygame.display.set_mode((TankMain.width, TankMain.height), 0, 32) # 给窗口设置标题 pygame.display.set_caption("坦克大战") # 生成我方坦克,敌方坦克,障碍物等 self.creat(screem) # 循环显示屏幕内容,形成动态效果 while True: screem.fill((0, 0, 0)) # 设置背景颜色 RGB (255,255,255):白色 (0,0,0):黑色 # 显示 self.show(screem) # 事件处理 self.get_event(TankMain.my_tank, screem) # 获取事件进行处理 time.sleep(0.05) # 每次休息0.05秒跳到下一帧 pygame.display.update() # 显示重置 # 在屏幕上显示文字内容 def write_text(self): font = pygame.font.SysFont('simhei', 13) # 定义一个字体 参数: 字体 大小 粗细 text_sf0 = font.render("我方坦克生命:%d"%TankMain.lives, True, (255, 0, 0)) # 根据字体创建一个文字的图像 参数:内容 抗锯齿 颜色 背景 text_sf1 = font.render("敌方坦克数量:%d"%len(TankMain.enemy_list), True, (255, 0, 0)) # 根据字体创建一个文字的图像 参数:内容 抗锯齿 颜色 背景 text_sf2 = font.render("我方坦克屏幕子弹数量:%d"%len(TankMain.my_tank_missile), True, (255, 0, 0)) # 根据字体创建一个文字的图像 参数:内容 抗锯齿 颜色 背景 return text_sf0, text_sf1, text_sf2 # 生产,创建我方坦克,敌方坦克 def creat(self, screem): # 生产墙列表 for i in range(1, 14): if i % 3 == 0: TankMain.wall_list.append(GrassBarrier(screem, i * Barrier.width, TankMain.height - 400)) TankMain.wall_list.append(CobWallBarrier(screem, i * Barrier.width, 300)) elif i % 4 == 0: pass elif i % 5 == 0: TankMain.wall_list.append(GrassBarrier(screem, i * Barrier.width, TankMain.height-400)) TankMain.wall_list.append(IronWallBarrier(screem, i * Barrier.width, 300)) elif i % 7 == 0: TankMain.wall_list.append(CobWallBarrier(screem, i * Barrier.width, 300)) else: TankMain.wall_list.append(IronWallBarrier(screem, i * Barrier.width, 300)) TankMain.wall_list.append(WaterBarrier(screem, i * Barrier.width, TankMain.height - 400)) TankMain.wall_list.append(GrassBarrier(screem, i * Barrier.width, i*Barrier.height)) TankMain.wall_list.append(WaterBarrier(screem, TankMain.width-i * Barrier.width, i * Barrier.height)) # 生成我方坦克的家 for i in range(0, 3): if i == 1: TankMain.home = HomeBarrier(screem, TankMain.width/2-HomeBarrier.width/2, TankMain.height-HomeBarrier.width) TankMain.wall_list.append(CobWallBarrier(screem, (TankMain.width+(2*i-3)*HomeBarrier.width)/2, TankMain.height-HomeBarrier.width*2)) else: TankMain.wall_list.append(CobWallBarrier(screem, (TankMain.width+(2*i-3)*HomeBarrier.width)/2, TankMain.height-HomeBarrier.width)) TankMain.wall_list.append(CobWallBarrier(screem, (TankMain.width+(2*i-3)*HomeBarrier.width)/2, TankMain.height-HomeBarrier.width*2)) # 生产我方坦克 TankMain.my_tank = MyTank(screem) # 生产敌方坦克 for i in range(1, 6): if i % 3 == 0: TankMain.enemy_list.add(EnemyTankQ(screem)) # 在族群中添加3个普通坦克,就会有一个强坦克 TankMain.enemy_list.add(EnemyTank(screem)) # 在族群中添加一个精灵sprite(坦克) # 在屏幕上显示(矩形rect, sprite, image,等) def show(self, screem): # 显示文字 for i, text in enumerate(self.write_text(), 0): screem.blit(text, (0, 5 + (13 * i))) # 在左上角显示文字 参数:源 位置(x,y) # 显示我方坦克的家 if TankMain.home and TankMain.home.live: TankMain.home.display() TankMain.home.hit_other() else: TankMain.home = None TankMain.lives = 0 TankMain.my_tank = None # 显示敌方坦克 for enemy_tank in TankMain.enemy_list: if enemy_tank.live: enemy_tank.display() # enemy_tank.hit_ourself() enemy_tank.random_move() enemy_tank.random_fire() else: TankMain.enemy_list.remove(enemy_tank) # 显示我方坦克 if TankMain.my_tank and TankMain.my_tank.live: TankMain.my_tank.enemy_hit_mytank() TankMain.my_tank.display() TankMain.my_tank.move() elif TankMain.lives: TankMain.my_tank = MyTank(screem) TankMain.my_tank.live = True TankMain.lives -= 1 else: TankMain.my_tank = None pass # 显示我方炮弹 for mm in TankMain.my_tank_missile: if mm.live: mm.display() mm.hit_tank() # 检测是否命中敌方坦克 mm.move() else: TankMain.my_tank_missile.remove(mm) # 显示敌方炮弹 for em in TankMain.enemy_tank_missile: if em.live: em.display() em.move() else: TankMain.enemy_tank_missile.remove(em) # 显示墙 for wall in TankMain.wall_list: if wall.live: wall.display() wall.hit_other() else: TankMain.wall_list.remove(wall) # 显示爆炸效果 for explode in TankMain.explode_list: if explode.live: explode.display() else: TankMain.explode_list.remove(explode) # 显示胜利 if not TankMain.enemy_list: finall_text = pygame.font.SysFont('simhei', 50).render("YOU WIN", True, (255, 0, 0), (0, 255, 0)) screem.blit(finall_text, (TankMain.width / 2 - 70, TankMain.height / 2 - 25)) # 显示失败 if (TankMain.lives == 0 and not TankMain.my_tank) or not TankMain.home : finall_text = pygame.font.SysFont('simhei', 50).render("YOU LOSE", True, (127, 127, 127), (255, 0, 0)) screem.blit(finall_text, (TankMain.width / 2 - 80, TankMain.height / 2 - 25)) # 获取所有事件(敲击键盘,点击鼠标等) def get_event(self, my_tank, screem): for event in pygame.event.get(): if event.type == QUIT: # 退出事件 self.stopGame() # 退出 # if event.type == KEYDOWN and not my_tank and TankMain.lives and event.key == K_RETURN: # TankMain.lives -= 1 # TankMain.my_tank = MyTank(screem) if event.type == KEYDOWN and my_tank: # 敲击键盘事件 if event.key == K_ESCAPE: # 敲击键盘ESC self.stopGame() # 退出 if event.key == K_LEFT or event.key == K_a: # 敲击键盘方向键向左 my_tank.direction = 'L' my_tank.stop = False if event.key == K_RIGHT or event.key == K_d: # 敲击键盘方向键向右 my_tank.direction = 'R' my_tank.stop = False if event.key == K_UP or event.key == K_w: # 敲击键盘方向键向上 my_tank.direction = 'U' my_tank.stop = False if event.key == K_DOWN or event.key == K_s: # 敲击键盘方向键向下 my_tank.direction = 'D' my_tank.stop = False if event.key == K_SPACE: mm = my_tank.fire() TankMain.my_tank_missile.append(mm) if event.type == KEYUP and my_tank: if event.key == K_LEFT or event.key == K_RIGHT or event.key == K_UP or event.key == K_DOWN \ or event.key == K_a or event.key == K_d or event.key == K_w or event.key == K_s: my_tank.stop = True if TankMain.my_tank and event.type == MOUSEBUTTONDOWN: # 鼠标事件 mm = my_tank.fire() TankMain.my_tank_missile.append(mm) # 关闭游戏 def stopGame(self): # 停止游戏 sys.exit() # 坦克大战游戏中的基础父类 class BaseIetm(pygame.sprite.Sprite): def __init__(self, screem): pygame.sprite.Sprite.__init__(self) self.screem = screem # 坦克,炮弹,墙移动显示要用到的屏幕窗口 # 把坦克显示在游戏窗口上 def display(self): if self.live: self.image = self.images[self.direction] self.screem.blit(self.image, self.rect) # 坦克父类 class Tank(BaseIetm): # 定义属性,所有坦克的宽高都是一样的 width = 47 height = 47 def __init__(self, screem, left, top): super().__init__(screem) self.direction = 'D' # 表示坦克方向,默认向下(U,D,L,R) self.speed = 5 # 坦克默认速度 self.stop = False self.images = {} # 表示坦克图片字典,key:方向,value:图片(surface) self.images['L'] = pygame.image.load("image/T_L.png") # 我方坦克 self.images['R'] = pygame.image.load("image/T_R.png") self.images['U'] = pygame.image.load("image/T_U.png") self.images['D'] = pygame.image.load("image/T_D.png") self.image = self.images[self.direction] # 坦克的图片由坦克的方向决定 self.rect = self.image.get_rect() # 获得图片的边界 self.rect.left = left # 设置图片位置x self.rect.top = top # 设置图片位置y self.live = True # 决定坦克生死 self.oldtop = self.rect.top self.oldleft = self.rect.left # 坦克碰到障碍物,停止前进 def stay(self): self.rect.top = self.oldtop self.rect.left = self.oldleft # 坦克的移动 def move(self): if not self.stop: self.oldtop = self.rect.top self.oldleft = self.rect.left if self.direction == 'L': if self.rect.left > 0: self.rect.left -= self.speed else: self.rect.left = 0 elif self.direction == 'R': if self.rect.right < TankMain.width: self.rect.right += self.speed else: self.rect.right = TankMain.width elif self.direction == 'U': if self.rect.top > 0: self.rect.top -= self.speed else: self.rect.top = 0 elif self.direction == 'D': if self.rect.bottom < TankMain.height: self.rect.bottom += self.speed else: self.rect.bottom = TankMain.height # 坦克开火,发射炮弹 def fire(self): pass # 我方坦克 class MyTank(Tank): def __init__(self, screem): super().__init__(screem, TankMain.width/2-MyTank.width/2, TankMain.height-150) # 我方坦克初始化位置 self.direction = 'U' # 我方坦克默认朝上 self.stop = True def enemy_hit_mytank(self): if TankMain.enemy_tank_missile: em_list = pygame.sprite.spritecollide(self, TankMain.enemy_tank_missile, False) for em in em_list: em.live = False self.live = False explode = Explode(self.screem, self.rect) TankMain.explode_list.append(explode) # if TankMain.enemy_list: # tank_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, False) # for tank in tank_list: # tank.stop = True # tank.stay() # 坦克开火,发射炮弹 def fire(self): mm = MyMissile(self.screem, self) return mm # 敌方坦克 class EnemyTank(Tank): def __init__(self, screem): super().__init__(screem, randint(0, TankMain.width), randint(0, TankMain.height-350)) self.images['L'] = pygame.image.load("image/tan_l.png") # 敌方坦克 self.images['R'] = pygame.image.load("image/tan_r.png") self.images['U'] = pygame.image.load("image/tan_u.png") self.images['D'] = pygame.image.load("image/tan_d.png") self.speed = 4 # 敌方坦克速度 self.step = 8 # 敌方坦克按照一个方向移动6步 self.get_random_direction() # 获得一个随机方向 def get_random_direction(self): r = randint(0, 4) if r == 0: self.stop = True elif r == 1: self.direction = 'L' self.stop = False elif r == 2: self.direction = 'R' self.stop = False elif r == 3: self.direction = 'U' self.stop = False elif r == 4: self.direction = 'D' self.stop = False # 敌方坦克确定一个随机方向移动8步,然后再次改变方向移动 def random_move(self): if self.live: if self.step == 0: # 如果已经移动了8步,则又随机获得一个方向 self.get_random_direction() self.step = 8 else: self.move() self.step -= 1 # 坦克开火,发射炮弹 def random_fire(self): if randint(1, 100) > 95: em = EnemyMissile(self.screem, self) TankMain.enemy_tank_missile.add(em) else: return # 敌方坦克 class EnemyTankQ(EnemyTank): def __init__(self, screem): super().__init__(screem) self.images['L'] = pygame.image.load("image/tank_l.png") # 敌方坦克 self.images['R'] = pygame.image.load("image/tank_r.png") self.images['U'] = pygame.image.load("image/tank_u.png") self.images['D'] = pygame.image.load("image/tank_d.png") # 炮弹父类 class Missile(BaseIetm): width = 12 height = 12 def __init__(self, screem, tank): super().__init__(screem) self.tank = tank self.direction = tank.direction # 表示炮弹方向,由坦克方向决定 self.speed = 12 # 炮弹默认速度 self.images = {} # 表示炮弹图片字典,key:方向,value:图片(surface) self.images['L'] = pygame.image.load("image/pao2.png") # 我方炮弹 self.images['R'] = pygame.image.load("image/pao2.png") self.images['U'] = pygame.image.load("image/pao2.png") self.images['D'] = pygame.image.load("image/pao2.png") self.image = self.images[self.direction] # 炮弹的图片由炮弹的方向决定 self.rect = self.image.get_rect() # 获得炮弹的边界 self.rect.left = tank.rect.left + (tank.width - self.width)/2 # 设置炮弹位置x self.rect.top = tank.rect.top + (tank.height - self.height)/2 # 设置炮弹位置y self.live = True # 决定炮弹生死 # 炮弹移动 def move(self): if self.live: if self.direction == 'L': if self.rect.left > 0: self.rect.left -= self.speed else: self.live = False elif self.direction == 'R': if self.rect.right < TankMain.width: self.rect.right += self.speed else: self.live = False elif self.direction == 'U': if self.rect.top > 0: self.rect.top -= self.speed else: self.live = False elif self.direction == 'D': if self.rect.bottom < TankMain.height: self.rect.bottom += self.speed else: self.live = False # 炮弹击中坦克,第一种:我方炮弹击中敌方坦克,需要我方炮弹的边界和所有敌方坦克边界比对,看是否重叠,返回重叠位置 # 第二种:敌方炮弹击中我方坦克,需要敌方炮弹和我方坦克位置比对,若重叠,返回位置 def hit_tank(self): if TankMain.enemy_list: # 我方炮弹击中敌方坦克 # 在与另一个精灵相交的组中查找精灵,检测是否碰撞 参数:本精灵 目标精灵组 是否删除组中所有碰撞的(Sprite)精灵 em_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, False) for em in em_list: self.live = False em.live = False explode = Explode(self.screem, em.rect) # 产生一个爆炸对象 TankMain.explode_list.append(explode) # 我方炮弹 class MyMissile(Missile): def __init__(self, screem, tank): super().__init__(screem, tank) # 敌方炮弹 class EnemyMissile(Missile): def __init__(self, screem, tank): super().__init__(screem, tank) self.images['L'] = pygame.image.load("image/pao3.png") # 我方炮弹 self.images['R'] = pygame.image.load("image/pao3.png") self.images['U'] = pygame.image.load("image/pao3.png") self.images['D'] = pygame.image.load("image/pao3.png") # 爆炸类 class Explode(BaseIetm): def __init__(self, screem, rect): super().__init__(screem) self.live = True self.images = [pygame.image.load("image/bao1.png"), pygame.image.load("image/bao2.png"), pygame.image.load("image/bao3.png"), pygame.image.load("image/bao4.png"), pygame.image.load("image/bao5.png"), pygame.image.load("image/bao6.png")] self.step = 0 self.image = self.images[self.step] # 初始化第一张爆炸效果图 self.rect = rect def display(self): if self.live: if self.step == len(self.images) : # 显示最后一张 self.live = False else: self.image = self.images[self.step] self.screem.blit(self.image, self.rect) # 爆炸位置由坦克的rect位置决定 self.step += 1 else: pass # 删除该爆炸效果对象 # 游戏中的静态障碍物(建筑,草,水等) class Barrier(BaseIetm): width = 47 height = 47 def __init__(self, screem, left, top): super().__init__(screem) # self.rect = Rect(left, top, width, height) # 构建一个rect(一个物体在屏幕的位置及大小 ) self.image = pygame.transform.scale(pygame.Surface((40, 40)), (40, 40)) self.rect = self.image.get_rect() self.rect.left = left self.rect.top = top self.live = True def display(self): if self.live: self.screem.blit(self.image, self.rect) # 碰撞检测 def hit_other(self): pass # 障碍物--铁墙 class IronWallBarrier(Barrier): def __init__(self, screem, left, top): super().__init__(screem, left, top) self.image = pygame.transform.scale(pygame.image.load("image/zhuan.gif"), (Barrier.width, Barrier.height)) # 铁墙碰撞检测 def hit_other(self): if TankMain.my_tank: if pygame.sprite.collide_rect(self, TankMain.my_tank): TankMain.my_tank.stop = True TankMain.my_tank.stay() if TankMain.enemy_list: et_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, False) for et in et_list: et.stop = True et.stay() if TankMain.my_tank_missile: mm_list = pygame.sprite.spritecollide(self, TankMain.my_tank_missile, False) for mm in mm_list: mm.live = False if TankMain.enemy_tank_missile: em_list = pygame.sprite.spritecollide(self, TankMain.enemy_tank_missile, False) for em in em_list: em.live = False # 障碍物--土墙 class CobWallBarrier(Barrier): def __init__(self, screem, left, top): super().__init__(screem, left, top) self.image = pygame.transform.scale(pygame.image.load("image/tu.gif"), (Barrier.width, Barrier.height)) # 土墙碰撞检测 def hit_other(self): if TankMain.my_tank: if pygame.sprite.collide_rect(self, TankMain.my_tank): TankMain.my_tank.stop = True TankMain.my_tank.stay() if TankMain.enemy_list: et_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, False) for et in et_list: et.stop = True et.stay() if TankMain.my_tank_missile: mm_list = pygame.sprite.spritecollide(self, TankMain.my_tank_missile, False) for mm in mm_list: mm.live = False self.live = False explode = Explode(self.screem, self.rect) TankMain.explode_list.append(explode) if TankMain.enemy_tank_missile: em_list = pygame.sprite.spritecollide(self, TankMain.enemy_tank_missile, False) for em in em_list: em.live = False self.live = False explode = Explode(self.screem, self.rect) TankMain.explode_list.append(explode) # 障碍物--草 class GrassBarrier(Barrier): def __init__(self, screem, left, top): super().__init__(screem, left, top) self.image = pygame.transform.scale(pygame.image.load("image/cao.gif"), (Barrier.width, Barrier.height)) # 草碰撞检测 def hit_other(self): pass # 障碍物--水 class WaterBarrier(Barrier): def __init__(self, screem, left, top): super().__init__(screem, left, top) self.image = pygame.transform.scale(pygame.image.load("image/shui.gif"), (Barrier.width, Barrier.height)) # 水碰撞检测 def hit_other(self): pass # 我方坦克的家 class HomeBarrier(Barrier): def __init__(self, screem, left, top): super().__init__(screem, left, top) self.image = pygame.transform.scale(pygame.image.load("image/home.gif"), (Barrier.width, Barrier.height)) # 家碰撞检测 def hit_other(self): if TankMain.my_tank: if pygame.sprite.collide_rect(self, TankMain.my_tank): TankMain.my_tank.stop = True TankMain.my_tank.stay() if TankMain.enemy_list: et_list = pygame.sprite.spritecollide(self, TankMain.enemy_list, False) for et in et_list: et.stop = True et.stay() if TankMain.my_tank_missile: mm_list = pygame.sprite.spritecollide(self, TankMain.my_tank_missile, False) for mm in mm_list: mm.live = False self.live = False explode = Explode(self.screem, self.rect) TankMain.explode_list.append(explode) if TankMain.enemy_tank_missile: em_list = pygame.sprite.spritecollide(self, TankMain.enemy_tank_missile, False) for em in em_list: em.live = False self.live = False explode = Explode(self.screem, self.rect) TankMain.explode_list.append(explode) # 测试运行 if __name__=='__main__': game = TankMain() game.startGame()
图片链接:http://www.aigei.com/view/63180.html#items 自己下
运行效果图:
主要用到pygame模块
官方文档:http://www.pygame.org/docs/
相关文章推荐
- python+pygame实现坦克大战
- python 实现初步坦克大战 带详细注释
- 坦克大战 python 游戏
- python语言实现飞机大战
- java实现 坦克大战
- unity3D游戏开发实战原创视频讲座系列2之2D坦克大战开发过程
- DS课设【坦克大战最短路】(MummyDing)
- 坦克大战中,给子弹加载图片
- FC 坦克大战 老巢铁墙
- 坦克大战项目
- Android开发之坦克大战
- 脚本游戏之四: 坦克大战源码注释(待续。。。)
- 坦克大战_敌方坦克移动并发子弹
- CUMT坦克大战
- java坦克大战0.3(画出代表坦克的实心圆)
- Python项目案例介绍,炫酷飞机大战,内附源码文件领取
- NYOJ-284 坦克大战 ------BFS/优先队列
- nyoj 坦克大战 (优先队列)
- python小项目之飞机大战
- Java坦克大战代码