坦克大战
坦克大战
1、安装pygame模块
pip install pygame
卸载模块
pip unistall pygame
如果pip总是安装失败,1)可以下载whl去安装,https://www.python.org/--->选择PypI-->搜索框输入pygame
选择对应版本下载
2)我的保存到了D:\project-pycharm盘下,进入到d盘,执行此文件
PS D:\project-pycharm> pip install pdf2docx-0.5.4-py3-none-any.whl
3)验证是否安装成功,在python文件中导入,无报错
import 模块名
2、源代码如下
# 导入pygame模块 import pygame, time, random from pygame.sprite import Sprite # 定义窗口的宽度和高度,可以是常量 SCREEN_WIDTH = 1200 SCREEN_HEIGHT = 1000 # 定义背景颜色为黑色 BG_COLOR = pygame.Color(0,0,0) # 定义字体颜色为红色 TEXT_COLOR = pygame.Color(255,0,0) # 定义一个基类 class BaseItem(Sprite): def __init__(self,color,width,height): pygame.sprite.Sprite.__init__(self) # 主类 class MainGame(): # 窗口初始化为None window = None # 初始化我方坦克 my_tank = None # 存储敌方坦克的列表 enemyTankList = [] # 定义敌方坦克的数量 enemyTankCount = 5 # 存储我方子弹的列表 myBulletList = [] # 存储地方子弹的列表 enemyBulletList = [] # 新增爆炸效果列表 explodeList = [] # 存储墙壁的列表 wallList = [] def __init__(self): pass # 开始游戏 def startGame(self): # 初始化窗口 pygame.display.init() # 设置窗口的大小及显示 MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT]) # 建立创建我方坦克的方法 self.createMytank() # 初始化敌方坦克,并将敌方坦克添加到列表中 self.createEnemyTank() # 初始化墙壁 self.createWall() # 设置窗口的标题 pygame.display.set_caption('坦克大战1.04') # 一直显示窗口 while True: # 使坦克移动的速度慢一点 time.sleep(0.02) # 给窗口设置填充色 MainGame.window.fill(BG_COLOR) # 获取事件 self.getEvent() # 绘制文字 MainGame.window.blit(self.getTextSuface('敌方坦克剩余数量%d'%len(MainGame.enemyTankList)),(10,10)) # 调用我方坦克显示方法 # 判断我方坦克是否存活 if MainGame.my_tank and MainGame.my_tank.live: MainGame.my_tank.displayTank() else: # 删除我方坦克 del MainGame.my_tank MainGame.my_tank = None # 循环遍历敌方坦克列表,展示敌方坦克 self.blitEnemyTank() # 循环遍历显示我方坦克的子弹 self.blitMyBullet() # 循环遍历敌方子弹列表,展示敌方子弹 self.blitEnemyBullet() # 循环遍历爆炸列表,展示爆炸效果 self.blitExplode() # 21.13循环遍历墙壁列表,展示墙壁 self.bliteWall() # 如果坦克的开关时开启的,才可以移动 # 添加一个我方坦克存活状态的判断 if MainGame.my_tank and MainGame.my_tank.live: if not MainGame.my_tank.stop: # 调用移动方法 MainGame.my_tank.move() # 检测我方坦克是否与墙壁发生碰撞 MainGame.my_tank.hitWall() # 检测我方坦克是否与敌方坦克发生碰撞 MainGame.my_tank.myTank_hit_enemyTank() # 更新软件显示的屏幕部分 pygame.display.update() # 循环遍历墙壁列表,展示墙壁 def bliteWall(self): for wall in MainGame.wallList: # 判断墙壁是否存活 if wall.live : # 调用墙壁的显示方法 wall.displayWall() else: # 从墙壁列表中移除 MainGame.wallList.remove(wall) # 初始化墙壁,创建墙壁方法 def createWall(self): # 循环放入墙壁按left值放入 for i in range(6): # 初始化墙壁 wall = Wall(i*200,220) # 将墙壁添加到列表中 MainGame.wallList.append(wall) # 新建我方坦克方法 def createMytank(self): # 初始化我方坦克 MainGame.my_tank = MyTank(350,350) # 创建Music对象, music = Music('image/Mytank.mp3') # 播放音乐 music.play() # 创建敌方坦克方法:初识化敌方坦克,并将敌方坦克添加到列表中 def createEnemyTank(self): top = 100 # 循环生成敌方坦克 for i in range(MainGame.enemyTankCount): left = random.randint(0, 600) speed = random.randint(1, 4) enemy = EnemyTank(left, top, speed) MainGame.enemyTankList.append(enemy) # 循环展示爆炸效果 def blitExplode(self): for explode in MainGame.explodeList: # 判断是否活着 if explode.live: # 展示 explode.displayExplode() else: # 在爆炸列表中移除 MainGame.explodeList.remove(explode) # 循环遍历敌方坦克列表,展示敌方坦克 def blitEnemyTank(self): for enemyTank in MainGame.enemyTankList: # 这里要判断敌方坦克是否活着 if enemyTank.live: enemyTank.displayTank() # 敌方坦克的移动,先注释,添加敌方坦克随机移动的方法 # enemyTank.move() # 调用敌方坦克随机移动 enemyTank.randMove() # 调用检测是否与墙壁碰撞 enemyTank.hitWall() # 检测敌方坦克是否与我方坦克发生碰撞 if MainGame.my_tank and MainGame.my_tank.live: enemyTank.enemyTank_hit_myTank() # 发射子弹:调用坦克类里的shot方法 enemyBullet = enemyTank.shot() # 判断敌方子弹是否为None,如果不为None则添加到敌方子弹列表中 if enemyBullet: # 将敌方子弹存储到敌方子弹列表中 MainGame.enemyBulletList.append(enemyBullet) else: # 不活着,从敌方坦克列表中移除 MainGame.enemyTankList.remove(enemyTank) # 循环遍历我方子弹的存储列表 def blitMyBullet(self): for myBullet in MainGame.myBulletList: # 判断当前子弹是否为活得状态,如果时则进行显示及移动,否则在列表中删除 if myBullet.live: myBullet.displayBullet() # 显示子弹调用子弹的移动方法 myBullet.move() # 调用检测我方子弹是否与敌方坦克发生碰撞 myBullet.myBullet_hit_enemyTank() # 检测我方子弹是否与墙壁碰撞 myBullet.hitWall() else: MainGame.myBulletList.remove(myBullet) # 循环遍历敌方子弹列表,展示敌方子弹 def blitEnemyBullet(self): for enemyBullet in MainGame.enemyBulletList: # 判断当前子弹是否为活得状态,如果时则进行显示及移动,否则在列表中删除 if enemyBullet.live: # 判断敌方子弹是否存活 enemyBullet.displayBullet() enemyBullet.move() # 调用敌方子弹与我方坦克碰撞的方法 enemyBullet.enemyBullet_hit_myTank() # 检测敌方子弹是否与墙壁碰撞 enemyBullet.hitWall() else: MainGame.enemyBulletList.remove(enemyBullet) # 结束游戏 def endGame(self): print("谢谢使用,欢迎再次使用") exit() # 左上角文字绘制 def getTextSuface(self,text): # 初始化字体模块 pygame.font.init() # 查看所有的字体名称 # print(pygame.font.get_fonts()) # 获取字体font对象 font = pygame.font.SysFont('kaiti', 18) # 绘制文字信息 textSurface = font.render(text,True,TEXT_COLOR,) return textSurface # 获取事件 def getEvent(self): # 获取所有事件 eventList = pygame.event.get() # 遍历事件 for event in eventList: # 判断按下的键是关闭还是键盘按下的 # 如果按下的是退出,关闭窗口 if event.type == pygame.QUIT: # 调用结束游戏的方法 self.endGame() # 如果是键盘的按下 if event.type == pygame.KEYDOWN: # 当坦克死亡, if not MainGame.my_tank: # 判断按下Esc键,让坦克重生 if event.key == pygame.K_ESCAPE: # 让我方坦克重生及调用创建坦克的方法 self.createMytank() # 添加一个我方坦克存活状态的判断 if MainGame.my_tank and MainGame.my_tank.live: # 判断按下的是上、下、左、右 if event.key == pygame.K_LEFT: # 切换方向向左 MainGame.my_tank.direction = 'L' # MainGame.my_tank.move() MainGame.my_tank.stop = False print("按下左键,坦贝向左移动") elif event.key == pygame.K_RIGHT: # 切换方向向右 MainGame.my_tank.direction = 'R' MainGame.my_tank.stop = False # MainGame.my_tank.move() print("按下右键,坦克向右移动") elif event.key == pygame.K_UP: # 切换方向向上 MainGame.my_tank.direction = 'U' MainGame.my_tank.stop = False # MainGame.my_tank.move() print("按下上键,坦克向上移动") elif event.key == pygame.K_DOWN: # 切换方向向下 MainGame.my_tank.direction = 'D' MainGame.my_tank.stop = False # MainGame.my_tank.move() print("按下下键,坦克向下移动") elif event.key == pygame.K_SPACE: print("发射子弹") # 如果我方子弹列表数量小于3才可以创建 if len(MainGame.myBulletList) < 3: # 创建我方坦克发射的子弹 myBullet = Bullet(MainGame.my_tank) # 添加子弹到我方子弹列表里 MainGame.myBulletList.append(myBullet) # 我方坦克发射子弹添加音效 music = Music('image/hit.mp3') music.play() # 松开键盘,坦克停止移动,修改坦克的开关状态 if event.type == pygame.KEYUP: # 判断松开键是上、下、左、右时候才停止坦克移动 if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: # 添加一个我方坦克存活状态的判断 if MainGame.my_tank and MainGame.my_tank.live: MainGame.my_tank.stop = True # 坦克类 class Tank(BaseItem): # 添加距离左边left距离上边top def __init__(self,left,top): # 保存加载的图片 self.images = { 'U': pygame.image.load('image/t1.png'), 'D': pygame.image.load('image/t2.png'), 'L': pygame.image.load('image/t3.png'), 'R': pygame.image.load('image/t4.png') } # 默认方向:向上 self.direction = 'U' # 根据当前图片的方向获取到图片 -->surface self.image = self.images[self.direction] # 根据图片获取区域 self.rect = self.image.get_rect() # 获取区域默认为的left和top self.rect.left = left self.rect.top = top # 速度 决定移动的快慢 self.speed = 5 # 坦克移动的开关 self.stop = True # 坦克活着的属性 self.live = True # 新增属性原来坐标 self.oldLeft = self.rect.left self.oldTop = self.rect.top # 移动 def move(self): # 移动后记录原始的坐标 self.oldLeft = self.rect.left self.oldTop = self.rect.top # 判断坦克的方向进行移动 if self.direction == 'L': if self.rect.left > 0: self.rect.left -= self.speed elif self.direction == 'U': if self.rect.top > 0: self.rect.top -= self.speed elif self.direction == 'R': if self.rect.left+self.rect.height<SCREEN_WIDTH: self.rect.left += self.speed elif self.direction == 'D': if self.rect.top+self.rect.height<SCREEN_HEIGHT: self.rect.top += self.speed # 射击 def shot(self): # 返回调用子弹类 return Bullet(self) # 检测坦克是否与墙壁发生碰撞 def hitWall(self): # 遍历墙壁的列表 for wall in MainGame.wallList: if pygame.sprite.collide_rect(self,wall): # 将坐标设置为移动之前的,调用stay方法 self.stay() # 创建stay方法 def stay(self): self.rect.left = self.oldLeft self.rect.top = self.oldTop # 展示坦克的方法 def displayTank(self): # 获取展示的对象 self.image = self.images[self.direction] # 调用blit方法展示 MainGame.window.blit(self.image,self.rect) # 我方坦克 class MyTank(Tank): def __init__(self,left,top): super(MyTank,self).__init__(left,top) # 我方坦克与敌方坦克发生碰撞 def myTank_hit_enemyTank(self): # 循环遍历敌方坦克 for enemyTank in MainGame.enemyTankList: if pygame.sprite.collide_rect(self,enemyTank): self.stay() # 敌方坦克 class EnemyTank(Tank): def __init__(self, left, top, speed): # 调用父类的初始化方法 super(EnemyTank,self).__init__(left,top) # 加载图片集 self.images = { 'U': pygame.image.load('image/et1.png'), 'D': pygame.image.load('image/et2.png'), 'L': pygame.image.load('image/et3.png'), 'R': pygame.image.load('image/et4.png') } # 方向,随机生成敌方坦克方向 self.direction = self.randDirection() # 根据方向获取图片 self.image = self.images[self.direction] # 区域 self.rect = self.image.get_rect() # 对left和top进行赋值 self.rect.left = left self.rect.top = top # 速度 self.speed = speed # 移动开关键 self.flag = True # 新增一个步数变量step self.step = 60 # 敌方坦克与我方坦克是否发生碰撞 def enemyTank_hit_myTank(self): if pygame.sprite.collide_rect(self,MainGame.my_tank): self.stay() # 随机生成敌方坦克的方向 def randDirection(self): num = random.randint(1,4) if num == 1: return 'U' elif num == 2: return 'D' elif num == 3: return 'L' elif num == 4: return 'R' # 敌方坦克随机移动的方法 def randMove(self): if self.step <= 0: # 修改方向 self.direction = self.randDirection() # 让步数复位 self.step = 60 else: self.move() # 让步数递减 self.step -= 1 # 重写shot方法 def shot(self): # 随机生成100以内的数 num = random.randint(1,200) if num < 10: return Bullet(self) # 子弹类 class Bullet(BaseItem): def __init__(self,tank): # 加载子弹图片 self.image = pygame.image.load('image/b1.png') # 坦克的方向决定子弹的方向 self.direction = tank.direction # 获取区域 self.rect = self.image.get_rect() # 子弹的lelf和top与方向有关 if self.direction == 'U': self.rect.left = tank.rect.left + int(tank.rect.width / 2) - int(self.rect.width / 2) self.rect.top = tank.rect.top - self.rect.height elif self.direction == 'D': self.rect.left = tank.rect.left + int(tank.rect.width / 2) - int(self.rect.width / 2) self.rect.top = tank.rect.top + self.rect.height elif self.direction == 'L': self.rect.left = tank.rect.left - self.rect.width self.rect.top = tank.rect.top + int(tank.rect.width / 2) - int(self.rect.width / 2) elif self.direction == 'R': self.rect.left = tank.rect.left + self.rect.width self.rect.top = tank.rect.top + int(tank.rect.width / 2) - int(self.rect.width / 2) # 子弹的速度 self.speed = 6 # 子弹的状态,是否碰到墙壁,如果碰到墙壁,修改此状态 self.live = True # 移动 def move(self): # 子弹移动方向与坦克方向一致 if self.direction == 'U': # 子弹移动方向 if self.rect.top > 0: self.rect.top -= self.speed else: # 修改子弹状态 self.live = False elif self.direction == 'D': if self.rect.top + self.rect.height < SCREEN_HEIGHT: self.rect.top += self.speed else: # 修改子弹状态 self.live = False elif self.direction == 'L': if self.rect.left > 0: self.rect.left -= self.speed else: # 修改子弹状态 self.live = False elif self.direction == 'R': if self.rect.left + self.rect.width < SCREEN_WIDTH: self.rect.left += self.speed else: # 修改子弹状态 self.live = False # 子弹是否碰撞墙壁 def hitWall(self): # 循环遍历墙壁列表 for wall in MainGame.wallList: if pygame.sprite.collide_rect(self,wall): # 修改子弹的生存状态,让子弹消失 self.live = False # 墙壁的生命值减小 wall.hp -= 1 if wall.hp <= 0: # 修改墙壁的状态 wall.live = False # 展示子弹的方法 def displayBullet(self): # 将图片的surface加载到窗口 MainGame.window.blit(self.image, self.rect) # 我方子弹与敌方坦克的碰撞 def myBullet_hit_enemyTank(self): # 循环遍历敌方坦克列表,判断是否发生碰撞 for enemyTank in MainGame.enemyTankList: if pygame.sprite.collide_rect(enemyTank,self): # 修改敌方坦克和我方子弹的状态 enemyTank.live = False self.live = False # 创建爆炸对象 explode = Explode(enemyTank) # 将爆炸对象添加到爆炸列表中 MainGame.explodeList.append(explode) # 敌方子弹与我方坦克碰撞 def enemyBullet_hit_myTank(self): # 添加一个我方坦克存活状态的判断 if MainGame.my_tank and MainGame.my_tank.live: if pygame.sprite.collide_rect(MainGame.my_tank,self): # 创建爆炸对象 explode = Explode(MainGame.my_tank) # 将爆炸对象添加到爆炸列表中 MainGame.explodeList.append(explode) # 修改敌方子弹与我方坦克的状态 self.live = False MainGame.my_tank.live = False # 墙壁类 class Wall(): def __init__(self,left,top): # 加载墙壁图片 self.images = pygame.image.load('image/steels.png') # 获取墙壁的区域 self.rect = self.images.get_rect() # 设置位置left,top self.rect.left = left self.rect.top = top # 是否活着 self.live = True # 设置生命值 self.hp = 3 # 展示墙壁的方法 def displayWall(self): # 展示墙壁的对象和位置 MainGame.window.blit(self.images,self.rect) # 爆炸类 class Explode(): def __init__(self,tank): # 爆炸位置由当前子弹打中的坦克位置决定 self.rect = tank.rect # 爆炸效果列表 self.images = [ # pygame.image.load('image/blast0.png'), # pygame.image.load('image/blast1.png'), # pygame.image.load('image/blast2.png'), # pygame.image.load('image/blast3.png'), # pygame.image.load('image/blast4.png') pygame.image.load('image/b2.png') ] # 获取图片 self.step = 0 self.image = self.images[self.step] # 是否活着 self.live = True # 展示爆炸效果的方法 def displayExplode(self): if self.step < len(self.images): # 根据索引获取爆炸对象 self.image = self.images[self.step] self.step += 1 # 添加到主窗口 MainGame.window.blit(self.image,self.rect) else: # 修改活着状态 self.live = False self.step = 0 # 音效类 class Music(): def __init__(self,filename): self.filename = filename # 初始化混合器 pygame.mixer.init() # 加载音乐 pygame.mixer.music.load(self.filename) # 播放音效的方法 def play(self): pygame.mixer.music.play() # 调用startGame() if __name__ == '__main__': MainGame().startGame() # MainGame().getTextSuface()
代码中用到的图片和音效,网上一搜一大堆,就不上传到这里了。