首先,我们得分析这个项目的结构,设计出它的框架
坦克大战游戏项目开发
需求分析
1.分析项目需要多少个类
2.分析每个类有哪些方法
1.坦克类(敌方坦克,我方坦克)
移动、射击、展示
2.子d类
移动、展示
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
#我方坦克子d列表
myBulletList = []
#敌方坦克子d列表
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()
#循环我方子d列表,进行展示
self.blitMyBullet()
# 循环敌方子d列表,进行展示
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:
# 判断当前子d是否存活,是的话则展示
if EnenmyBullet.live:
EnenmyBullet.displayBullet()
# 调用子d移动的方法
EnenmyBullet.move()
#调用敌方子d击中我方坦克的方法
EnenmyBullet.enemyBullet_hit_myTank()
#调用子d碰撞墙壁的方法
EnenmyBullet.bullet_hit_wall()
else:
# 删除子d
MainGame.enemyBulletList.remove(EnenmyBullet)
# 循环我方子d列表,进行展示
def blitMyBullet(self):
for MyBullet in MainGame.myBulletList:
#判断当前子d是否存活,是的话则展示
if MyBullet.live:
MyBullet.displayBullet()
# 调用子d移动的方法
MyBullet.move()
#调用我们子d与敌方坦克发生碰撞的方法
if MainGame.my_tank and MainGame.my_tank.live:
MyBullet.myBullet_hit_enemyTank()
# 调用子d碰撞墙壁的方法
MyBullet.bullet_hit_wall()
else:
#删除子d
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()
# 发射子d
enemyBullet = enemyTank.shoot()
# 判断子d的是否为None
if enemyBullet:
# 将敌方坦克子d存储到子d列表中
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('发射子d')
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文件必须要对应!
重要的事情说三遍!
游戏里的素材私信我
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)