赞
踩
话不多说,先给我的美女们献上我的完整代码~
- import pygame, time, random
-
- _display = pygame.display
- COLOR_BLACK = pygame.Color(0, 0, 0)
- COLOR_RED = pygame.Color(255, 0, 0)
- version = 'v1.25'
-
-
- class MainGame():
- # 游戏主窗口
- window = None
- SCREEN_HEIGHT = 800
- SCREEN_WIDTH = 1300
- # 创建我方坦克
- TANK_P1 = None
- # 存储所有敌方坦克
- EnemyTank_list = []
-
- # 要创建的敌方坦克的数量
- EnemTank_count = 10
-
- # 存储我方子弹的列表
- Bullet_list = []
- # 存储敌方子弹的列表
- Enemy_bullet_list = []
- # 爆炸效果列表
- Explode_list = []
- # 墙壁列表
- Wall_list = []
-
- # 零食清单
- Classmate_list = ["糖炒板栗", "牛奶", "葡萄干", "巧克力", "芝士饼干", "肉松小贝"]
-
- # 开始游戏方法
- def startGame(self):
- _display.init()
- # 创建窗口加载窗口(借鉴官方文档)
- MainGame.window = _display.set_mode([MainGame.SCREEN_WIDTH, MainGame.SCREEN_HEIGHT])
- self.creatMyTank()
- self.creatEnemyTank()
- self.creatWalls()
- # 设置一下游戏标题
- _display.set_caption("坦克大战" + version)
- # 让窗口持续刷新操作
- while True:
- # 给窗口完成一个填充颜色
- MainGame.window.fill(COLOR_BLACK)
- # 在循环中持续完成事件的获取
- self.getEvent()
- # 将绘制文字得到的小画布,粘贴到窗口中
-
- MainGame.window.blit(self.getTextSurface("剩余敌方坦克%d辆" % len(MainGame.EnemyTank_list)), (5, 5))
-
- #定制欢迎词
- number = 600
- for Classmate in MainGame.Classmate_list:
- MainGame.window.blit(self.getTextSurface("输了请我吃%s,好人一生平安~ " % Classmate), (500, number))
- number = number + 40
-
- # 调用展示墙壁的方法
- self.blitWalls()
- if MainGame.TANK_P1 and MainGame.TANK_P1.live:
- # 将我方坦克加入到窗口中
- MainGame.TANK_P1.displayTank()
- else:
- del MainGame.TANK_P1
- MainGame.TANK_P1 = None
- # 循环展示敌方坦克
- self.blitEnemyTank()
- # 根据坦克的开关状态调用坦克的移动方法
- if MainGame.TANK_P1 and not MainGame.TANK_P1.stop:
- MainGame.TANK_P1.move()
- # 调用碰撞墙壁的方法
- MainGame.TANK_P1.hitWalls()
- MainGame.TANK_P1.hitEnemyTank()
- # 调用渲染子弹列表的一个方法
- self.blitBullet()
- # 调用渲染敌方子弹列表的一个方法
- self.blitEnemyBullet()
- # 调用展示爆炸效果的方法
- self.displayExplodes()
- time.sleep(0.02)
- # 窗口的刷新
- _display.update()
-
- # 创建我方坦克的方法
- def creatMyTank(self):
- # 创建我方坦克
- MainGame.TANK_P1 = MyTank(400, 300)
-
- # 创建音乐对象
- music = Music('img/再见深海.wav')
- # 调用播放音乐方法
- music.play()
-
- # 创建敌方坦克
- def creatEnemyTank(self):
- top = 100
- for i in range(MainGame.EnemTank_count):
- speed = random.randint(3, 6)
- # 每次都随机生成一个left值
- left = random.randint(1, 7)
- eTank = EnemyTank(left * 100, top, speed)
- MainGame.EnemyTank_list.append(eTank)
-
- # 创建墙壁的方法
- def creatWalls(self):
-
- for i in range(10): # 创建墙壁的数量
-
- wall = Wall(130 * i, 240)
- MainGame.Wall_list.append(wall)
-
- def blitWalls(self):
- for wall in MainGame.Wall_list:
- if wall.live:
- wall.displayWall()
- else:
- MainGame.Wall_list.remove(wall)
-
- # 将敌方坦克加入到窗口中
- def blitEnemyTank(self):
- for eTank in MainGame.EnemyTank_list:
- if eTank.live:
- eTank.displayTank()
- # 坦克移动的方法
- eTank.randMove()
- # 调用敌方坦克与墙壁的碰撞方法
- eTank.hitWalls()
- # 敌方坦克是否撞到我方坦克
- eTank.hitMyTank()
- # 调用敌方坦克的射击
- eBullet = eTank.shot()
- # 如果子弹为None。不加入到列表
- if eBullet:
- # 将子弹存储敌方子弹列表
- MainGame.Enemy_bullet_list.append(eBullet)
- else:
- MainGame.EnemyTank_list.remove(eTank)
-
- # 将我方子弹加入到窗口中
- def blitBullet(self):
- for bullet in MainGame.Bullet_list:
- # 如果子弹还活着,绘制出来,否则,直接从列表中移除该子弹
- if bullet.live:
- bullet.displayBullet()
- # 让子弹移动
- bullet.bulletMove()
- # 调用我方子弹与敌方坦克的碰撞方法
- bullet.hitEnemyTank()
- # 调用判断我方子弹是否碰撞到墙壁的方法
- bullet.hitWalls()
- else:
- MainGame.Bullet_list.remove(bullet)
-
- # 将敌方子弹加入到窗口中
- def blitEnemyBullet(self):
- for eBullet in MainGame.Enemy_bullet_list:
- # 如果子弹还活着,绘制出来,否则,直接从列表中移除该子弹
- if eBullet.live:
- eBullet.displayBullet()
- # 让子弹移动
- eBullet.bulletMove()
- # 调用是否碰撞到墙壁的一个方法
- eBullet.hitWalls()
- if MainGame.TANK_P1 and MainGame.TANK_P1.live:
- eBullet.hitMyTank()
- else:
- MainGame.Enemy_bullet_list.remove(eBullet)
-
- # 新增方法: 展示爆炸效果列表
- def displayExplodes(self):
- for explode in MainGame.Explode_list:
- if explode.live:
- explode.displayExplode()
- else:
- MainGame.Explode_list.remove(explode)
-
- # 获取程序期间所有事件(鼠标事件,键盘事件)
- def getEvent(self):
- # 1.获取所有事件
- eventList = pygame.event.get()
- # 2.对事件进行判断处理(1、点击关闭按钮 2、按下键盘上的某个按键)
- for event in eventList:
- # 判断event.type 是否QUIT,如果是退出的话,直接调用程序结束方法
- if event.type == pygame.QUIT:
- self.endGame()
- # 判断事件类型是否为按键按下,如果是,继续判断按键是哪一个按键,来进行对应的处理
- if event.type == pygame.KEYDOWN:
-
- # 修改重生键
- if event.key == pygame.K_TAB and not MainGame.TANK_P1:
- # 调用创建我方坦克的方法
- self.creatMyTank()
- if MainGame.TANK_P1 and MainGame.TANK_P1.live:
- # 具体是哪一个按键的处理
- if event.key == pygame.K_LEFT:
- print("坦克向左调头,移动")
- # 修改坦克方向
- MainGame.TANK_P1.direction = 'L'
- MainGame.TANK_P1.stop = False
- elif event.key == pygame.K_RIGHT:
- print("坦克向右调头,移动")
- # 修改坦克方向
- MainGame.TANK_P1.direction = 'R'
- MainGame.TANK_P1.stop = False
- elif event.key == pygame.K_UP:
- print("坦克向上调头,移动")
- # 修改坦克方向
- MainGame.TANK_P1.direction = 'U'
- MainGame.TANK_P1.stop = False
- elif event.key == pygame.K_DOWN:
- print("坦克向下掉头,移动")
- # 修改坦克方向
- MainGame.TANK_P1.direction = 'D'
- MainGame.TANK_P1.stop = False
-
- # 修改攻击键
- elif event.key == pygame.K_END:
- print("发射子弹")
-
- if len(MainGame.Bullet_list) < 3:
- # 产生一颗子弹
- m = Bullet(MainGame.TANK_P1)
- # 将子弹加入到子弹列表
- MainGame.Bullet_list.append(m)
- music = Music('img/fire.wav')
- music.play()
- else:
- print("子弹数量不足")
- print("当前屏幕中的子弹数量为:%d" % len(MainGame.Bullet_list))
- # 结束游戏方法
- if event.type == pygame.KEYUP:
- # 松开的如果是方向键,才更改移动开关状态
- if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
- if MainGame.TANK_P1 and MainGame.TANK_P1.live:
- # 修改坦克的移动状态
- MainGame.TANK_P1.stop = True
-
- # 左上角文字绘制的功能
- def getTextSurface(self, text):
- # 初始化字体模块
- pygame.font.init()
- # 查看系统支持的所有字体
- # fontList = pygame.font.get_fonts()
- # print(fontList)
- # 选中一个合适的字体
- font = pygame.font.SysFont('kaiti', 18)
- # 使用对应的字符完成相关内容的绘制
- textSurface = font.render(text, True, COLOR_RED)
- return textSurface
-
- def endGame(self):
- print("菜鸡,你行不行啊?")
- # 结束python解释器
- exit()
-
-
- class BaseItem(pygame.sprite.Sprite):
- def __init__(self):
- pygame.sprite.Sprite.__init__(self)
-
-
- class Tank(BaseItem):
- def __init__(self, left, top):
- self.images = {
- 'U': pygame.image.load('img/p1tankU.gif'),
- 'D': pygame.image.load('img/p1tankD.gif'),
- 'L': pygame.image.load('img/p1tankL.gif'),
- 'R': pygame.image.load('img/p1tankR.gif')
- }
- self.direction = 'U'
- self.image = self.images[self.direction]
- # 坦克所在的区域 Rect->
- self.rect = self.image.get_rect()
- # 指定坦克初始化位置 分别距x,y轴的位置
- self.rect.left = left
- self.rect.top = top
- # 新增速度属性
- self.speed = 5
- # 新增属性: 坦克的移动开关
- self.stop = True
- # 新增属性 live 用来记录,坦克是否活着
- 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 == 'R':
- if self.rect.left + self.rect.height < MainGame.SCREEN_WIDTH:
- self.rect.left += self.speed
- elif self.direction == 'U':
- if self.rect.top > 0:
- self.rect.top -= self.speed
- elif self.direction == 'D':
- if self.rect.top + self.rect.height < MainGame.SCREEN_HEIGHT:
- self.rect.top += self.speed
-
- def stay(self):
- self.rect.left = self.oldLeft
- self.rect.top = self.oldTop
-
- # 新增碰撞墙壁的方法
- def hitWalls(self):
- for wall in MainGame.Wall_list:
- if pygame.sprite.collide_rect(wall, self):
- self.stay()
-
- # 射击方法
- def shot(self):
- return Bullet(self)
-
- # 展示坦克(将坦克这个surface绘制到窗口中 blit())
- def displayTank(self):
- # 1.重新设置坦克的图片
- self.image = self.images[self.direction]
- # 2.将坦克加入到窗口中
- MainGame.window.blit(self.image, self.rect)
-
-
- class MyTank(Tank):
- def __init__(self, left, top):
- super(MyTank, self).__init__(left, top)
-
- # 新增主动碰撞到敌方坦克的方法
- def hitEnemyTank(self):
- for eTank in MainGame.EnemyTank_list:
- if pygame.sprite.collide_rect(eTank, self):
- self.stay()
-
-
- class EnemyTank(Tank):
- def __init__(self, left, top, speed):
- super(EnemyTank, self).__init__(left, top)
- # self.live = True
- self.images = {
- 'U': pygame.image.load('img/enemy1U.gif'),
- 'D': pygame.image.load('img/enemy1D.gif'),
- 'L': pygame.image.load('img/enemy1L.gif'),
- 'R': pygame.image.load('img/enemy1R.gif')
- }
- self.direction = self.randDirection()
- self.image = self.images[self.direction]
- # 坦克所在的区域 Rect->
- self.rect = self.image.get_rect()
- # 指定坦克初始化位置 分别距x,y轴的位置
- self.rect.left = left
- self.rect.top = top
- # 新增速度属性
- self.speed = speed
- self.stop = True
- # 新增步数属性,用来控制敌方坦克随机移动
- self.step = 30
-
- 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 displayEnemtTank(self):
- # super().displayTank()
- # 随机移动
- def randMove(self):
- if self.step <= 0:
- self.direction = self.randDirection()
- self.step = 50
- else:
- self.move()
- self.step -= 1
-
- def shot(self):
- num = random.randint(1, 1000)
- if num <= 20:
- return Bullet(self)
-
- def hitMyTank(self):
- if MainGame.TANK_P1 and MainGame.TANK_P1.live:
- if pygame.sprite.collide_rect(self, MainGame.TANK_P1):
- # 让敌方坦克停下来 stay()
- self.stay()
-
-
- class Bullet(BaseItem):
- def __init__(self, tank):
- # 子弹造型的图片
- self.image = pygame.image.load('img/enemymissile.gif')
- # 方向(坦克方向)
- self.direction = tank.direction
- # 位置
- self.rect = self.image.get_rect()
- if self.direction == 'U':
- self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
- self.rect.top = tank.rect.top - self.rect.height
- elif self.direction == 'D':
- self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
- self.rect.top = tank.rect.top + tank.rect.height
- elif self.direction == 'L':
- self.rect.left = tank.rect.left - self.rect.width / 2 - self.rect.width / 2
- self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
- elif self.direction == 'R':
- self.rect.left = tank.rect.left + tank.rect.width
- self.rect.top = tank.rect.top + tank.rect.width / 2 - self.rect.width / 2
- # 速度
- self.speed = 7
- # 用来记录子弹是否活着
- self.live = True
-
- # 子弹的移动方法
- def bulletMove(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 < MainGame.SCREEN_HEIGHT - self.rect.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 < MainGame.SCREEN_WIDTH - self.rect.width:
- self.rect.left += self.speed
- else:
- # 修改状态值
- self.live = False
-
- # 展示子弹的方法
- def displayBullet(self):
- MainGame.window.blit(self.image, self.rect)
-
- # 新增我方子弹碰撞敌方坦克的方法
- def hitEnemyTank(self):
- for eTank in MainGame.EnemyTank_list:
- if pygame.sprite.collide_rect(eTank, self):
- # 产生一个爆炸效果
- explode = Explode(eTank)
- # 将爆炸效果加入到爆炸效果列表
- MainGame.Explode_list.append(explode)
- self.live = False
- eTank.live = False
-
- # 新增敌方子弹与我方坦克的碰撞方法
- def hitMyTank(self):
- if pygame.sprite.collide_rect(self, MainGame.TANK_P1):
- # 产生爆炸效果,并加入到爆炸效果列表中
- explode = Explode(MainGame.TANK_P1)
- MainGame.Explode_list.append(explode)
- # 修改子弹状态
- self.live = False
- # 修改我方坦克状态
- MainGame.TANK_P1.live = False
-
- # 新增子弹与墙壁的碰撞
- def hitWalls(self):
- for wall in MainGame.Wall_list:
- if pygame.sprite.collide_rect(wall, self):
- # 修改子弹的live属性
- self.live = False
- wall.hp -= 1
- if wall.hp <= 0:
- wall.live = False
-
-
- class Explode():
- def __init__(self, tank):
- self.rect = tank.rect
- self.step = 0
- self.images = [
- pygame.image.load('img/blast0.gif'),
- pygame.image.load('img/blast1.gif'),
- pygame.image.load('img/blast2.gif'),
- pygame.image.load('img/blast3.gif'),
- pygame.image.load('img/blast4.gif')
- ]
- self.image = self.images[self.step]
- self.live = True
-
- # 展示爆炸效果
- def displayExplode(self):
- if self.step < len(self.images):
- MainGame.window.blit(self.image, self.rect)
- self.image = self.images[self.step]
- self.step += 1
- else:
- self.live = False
- self.step = 0
-
-
- class Wall():
- def __init__(self, left, top):
- self.image = pygame.image.load('img/steels.gif')
- self.rect = self.image.get_rect()
- self.rect.left = left
- self.rect.top = top
- # 用来判断墙壁是否应该在窗口中展示
- self.live = True
-
- # 墙壁的生命值
- self.hp = 30
-
- # 展示墙壁的方法
- def displayWall(self):
- MainGame.window.blit(self.image, self.rect)
-
-
- # 我方坦克出生
- 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()
-
-
- MainGame().startGame()
运行结果展示
代码里面是有完整注解的,还是有不明白的地方欢迎评论区留言~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。