赞
踩
首先,我们得分析这个项目的结构,设计出它的框架
坦克大战游戏项目开发
需求分析
1.分析项目需要多少个类
2.分析每个类有哪些方法
1.坦克类(敌方坦克,我方坦克)
移动、射击、展示
2.子弹类
移动、展示
3.墙壁类
属性:是否可以通过
4.爆炸效果类
展示
5.音效类
播放音乐
6.主类
开始游戏
结束游戏
好了,直接上代码,不用担心看不懂,几乎每行都会有注释
- import pygame
- import time
- import random
- SCREEN_WIDTH = 800
- SCREEN_HEIGHT = 600
- BG_COLOR = pygame.Color(0,0,0)
- TEXT_COLOR = pygame.Color(255,0,0)
- #定义一个基类
- class BaseItem(pygame.sprite.Sprite):
- def __init__(self):
- pygame.sprite.Sprite.__init__(self)
-
- class MainGame():
- 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.creatMyTank()
- #初始化敌方坦克,并添加到列表中
- self.creatEnemyTank()
- # 初始化墙壁
- self.creatWall()
- #设置窗口标题
- pygame.display.set_caption('坦克大战1.0')
- while True:
- #让坦克的速度慢一点
- time.sleep(0.05)
- #给窗口设置填充色
- MainGame.window.fill(BG_COLOR)
- #获取事件
- self.getevent()
- #绘制文字
- MainGame.window.blit(self.getTextSurface('敌方坦克剩余数量:%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()
- # 循环墙壁列表,进行展示
- self.blitWall()
- #调用坦克移动的方法
- #如果坦克的开关是开 才可以启动
- if MainGame.my_tank and MainGame.my_tank.live:
- if not MainGame.my_tank.stop:
- MainGame.my_tank.move()
- #检测我方坦克是否与墙体发生碰撞
- MainGame.my_tank.tank_hit_wall()
- #检测我方坦克是否与敌方坦克发生碰撞
- MainGame.my_tank.myTank_hit_enemyTank()
- pygame.display.update()
-
- # 循环墙壁列表,进行展示
- def blitWall(self):
- for wall in MainGame.wallList:
- if wall.live:
- wall.displayWall()
- else:
- MainGame.wallList.remove(wall)
- # 初始化墙壁
- def creatWall(self):
- for i in range(6):
- wall = Wall(i*150,230)
- MainGame.wallList.append(wall)
-
- def creatMyTank(self):
- MainGame.my_tank = MyTank(300, 300)
- #初始化音乐
- music = Music('img/start.wav')
- #播放音乐
- music.play()
- # 循环爆炸效果列表,进行展示
- def blitExplode(self):
- for explode in MainGame.explodeList:
- #判断是否活着
- if explode.live:
- explode.displayExplode()
- else:
- MainGame.explodeList.remove(explode)
-
- #循环敌方坦克列表,进行展示
- def blitEnemyBullet(self):
- for EnenmyBullet in MainGame.enemyBulletList:
- # 判断当前子弹是否存活,是的话则展示
- if EnenmyBullet.live:
- EnenmyBullet.displayBullet()
- # 调用子弹移动的方法
- EnenmyBullet.move()
- #调用敌方子弹击中我方坦克的方法
- EnenmyBullet.enemyBullet_hit_myTank()
- #调用子弹碰撞墙壁的方法
- EnenmyBullet.bullet_hit_wall()
- else:
- # 删除子弹
- MainGame.enemyBulletList.remove(EnenmyBullet)
-
-
- # 循环我方子弹列表,进行展示
- def blitMyBullet(self):
- for MyBullet in MainGame.myBulletList:
- #判断当前子弹是否存活,是的话则展示
- if MyBullet.live:
- MyBullet.displayBullet()
- # 调用子弹移动的方法
- MyBullet.move()
- #调用我们子弹与敌方坦克发生碰撞的方法
- if MainGame.my_tank and MainGame.my_tank.live:
- MyBullet.myBullet_hit_enemyTank()
- # 调用子弹碰撞墙壁的方法
- MyBullet.bullet_hit_wall()
- else:
- #删除子弹
- MainGame.myBulletList.remove(MyBullet)
- #循环敌方坦克列表进行展示
- def blitEnemyTank(self):
- for enemyTank in MainGame.enemyTankList:
- #判断敌方坦克状态是否存活
- if enemyTank.live:
- enemyTank.displayTank()
- enemyTank.randMove()
- # 调用检测敌方坦克是否与墙体发生碰撞
- enemyTank.tank_hit_wall()
- # 调用检测敌方坦克是否与我方坦克发生碰撞
- if MainGame.my_tank and MainGame.my_tank.live:
- enemyTank.enemyTank_hit_MyTank()
- # 发射子弹
- enemyBullet = enemyTank.shoot()
- # 判断子弹的是否为None
- if enemyBullet:
- # 将敌方坦克子弹存储到子弹列表中
- MainGame.enemyBulletList.append(enemyBullet)
- else:
- MainGame.enemyTankList.remove(enemyTank)
-
- # 初始化敌方坦克,并添加到列表中
- def creatEnemyTank(self):
- top = 100
- #循环生成敌方坦克
- for i in range(MainGame.enemyTankCount):
- left = random.randint(1,700)
- speed = random.randint(1,7)
- enemy = EnemyTank(left,top,speed)
- MainGame.enemyTankList.append(enemy)
-
- #结束游戏
- def endGame(self):
- print('谢谢,欢迎下次使用')
- exit()
- #左上角的文字绘制
- def getTextSurface(self,text):
- #初始化字体模块
- pygame.font.init()
- #查看所有字体名称
- # print(pygame.font.get_fonts())
- #获取字体对象
- font = pygame.font.SysFont('kaiti',18)
- #绘制文本信息
- textSurface = font.render(text,True,TEXT_COLOR)
- return textSurface
-
- def getevent(self):
- #获取所有事件
- event_list = pygame.event.get()
- for event in event_list:
- #判断按下的是关闭还是键盘按下
- #如果是退出,关闭窗口
- 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.creatMyTank()
- if MainGame.my_tank and MainGame.my_tank.live:
- # 判断按下的是上下左右
- if event.key == pygame.K_LEFT:
- # 切换方向
- MainGame.my_tank.direction = 'L'
- MainGame.my_tank.stop = False
- # MainGame.my_tank.move()
- 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('发射子弹')
- if len(MainGame.myBulletList) < 3:
- myBullet = Bullet(MainGame.my_tank)
- MainGame.myBulletList.append(myBullet)
- #加载音乐
- music = Music('img/fire.wav')
- music.play()
- #松开按键,坦克停止移动,修改坦克开关
- 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.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('img/p1tankU.gif'),
- 'R':pygame.image.load('img/p1tankR.gif'),
- 'L':pygame.image.load('img/p1tankL.gif'),
- 'D':pygame.image.load('img/p1tankD.gif')
- }
- #方向
- 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 = 10
- #坦克的开关
- 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 == 'R':
- if self.rect.left + self.rect.height < 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 < SCREEN_HEIGHT:
- self.rect.top += self.speed
-
- #射击
- def shoot(self):
- return Bullet(self)
- def stay(self):
- self.rect.left = self.oldleft
- self.rect.top = self.oldtop
- #坦克与墙体发生碰撞
- def tank_hit_wall(self):
- for wall in MainGame.wallList:
- if pygame.sprite.collide_rect(self,wall):
- #修改坦克的位置
- self.stay()
- #展示
- 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)
- pass
- #检测我方坦克与敌方坦克发生碰撞
- def myTank_hit_enemyTank(self):
- for enemy in MainGame.enemyTankList:
- if pygame.sprite.collide_rect(self,enemy):
- self.stay()
-
- class EnemyTank(Tank):
- def __init__(self,left,top,speed):
- #调用父类的初始化方法
- super(EnemyTank,self).__init__(left,top)
- #加载图片集
- self.images = {
- 'U':pygame.image.load('img/enemy1U.gif'),
- 'R':pygame.image.load('img/enemy1R.gif'),
- 'L':pygame.image.load('img/enemy1L.gif'),
- 'D':pygame.image.load('img/enemy1D.gif')
- }
- #方向 随机生成敌方坦克的方向
- 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
- #步数
- self.step = 30
- #敌方坦克与我方坦克发生碰撞
- 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 'R'
- elif num == 3:
- return 'L'
- elif num == 4:
- return 'D'
- def randMove(self):
- if self.step <=0:
- #修改方向
- self.direction = self.randDirection()
- #恢复步数
- self.step = 40
- else:
- self.move()
- #步数递减
- self.step -= 1
- #重写shoot
- def shoot(self):
- num = random.randint(1,100)
- if num <= 5:
- return Bullet(self)
-
- class Explode():
- def __init__(self,tank):
- #爆炸效果位置由坦克被击中的位置决定
- self.rect = tank.rect
- #加载图片
- 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.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 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 = 5
-
- #展示墙的效果
- 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()
-
- 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()
- #子弹的left和top和坦克方向有关
- 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 = 10
- # 用来记录子弹是否活着
- 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 == 'R':
- if self.rect.left + self.rect.width < SCREEN_WIDTH:
- self.rect.left += 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 == 'D':
- if self.rect.top + self.rect.height < SCREEN_HEIGHT:
- self.rect.top += self.speed
- else:
- # 碰到墙壁,修改存活状态
- self.live = False
-
- # 我方子弹与敌方坦克发生碰撞
- 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)
- # 修改我方坦克和敌方方子弹的状态
- MainGame.my_tank.live = False
- self.live = False
- #子弹与墙发生碰撞
- def bullet_hit_wall(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):
- MainGame.window.blit(self.image,self.rect)
-
- if __name__ == '__main__':
- MainGame().startGame()
- # MainGame().getTextSuface()
最终效果如下
ps:代码中的敌方坦克数量,墙体数量等都是自定义的,我方坦克阵亡后按ESC键重生!
以上代码中的图片素材与py文件必须要对应!
以上代码中的图片素材与py文件必须要对应!
以上代码中的图片素材与py文件必须要对应!
重要的事情说三遍!
游戏里的素材私信我
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。