您的位置:首页 > 财经 > 产业 > 坦克大战游戏开发

坦克大战游戏开发

2024/9/9 5:49:03 来源:https://blog.csdn.net/m0_73755059/article/details/139935600  浏览:    关键词:坦克大战游戏开发

目录

  • 需求分析
  • 实现过程
    • 导包
    • 坦克类
    • 子弹类
    • 墙壁类
    • 爆炸类
    • 音效类
    • 游戏主窗口类
  • 收获

需求分析

  1. 首先要有一个主窗口,游戏中所有的图形都在这里面渲染
  2. 要有一个坦克类,有两个子类:我方坦克类、敌方坦克类
  3. 坦克发射子弹,需要有一个子弹类
  4. 游戏里有墙壁,要有墙壁类
  5. 坦克死亡时会爆炸,定义爆炸类
  6. 游戏有音乐和音效,需要定义一个音乐类

实现过程

导包

import pygame
from time import sleep
import random
from pygame.sprite import collide_rect

坦克类

  1. 坦克类的属性
  • 坦克的存活状态、坦克的移动状态、坦克的位置、坦克的图片资源、坦克的图形、坦克的移动速度,在具体实现过程中根据需要在具体添加。
  1. 坦克的行为/方法
  • 坦克的移动、射击、碰撞墙壁检测、碰撞敌方坦克检测。敌方坦克的行为和我方坦克的行为略有差距,对于有差别的部分分别创建不同的方法,对于相同的部分,把这些属性和方法写到基类里,子类进行继承即可。
  1. 代码
    基类
class Tank:'''坦克类'''def __init__(self) -> None:# 坦克存活的状态self.live = True# 记录坦克原来的位置self.old_left = 0self.old_top = 0def display_tank(self) -> None:'''显示坦克'''if self.live: #坦克存活时显示坦克# 获取坦克朝向self.image = self.images.get(self.direction)MainGame.window.blit(self.image,self.rect)else: #坦克不存活时,删除坦克MainGame.my_tank = Nonedef move(self) -> None:'''移动坦克'''# 记录坦克位置,方便还原坦克碰撞墙壁之前的位置self.old_left = self.rect.leftself.old_top = self.rect.topif self.direction == 'L':#判断坦克位置是否越过左边界if self.rect.left > 0:#向左移动坦克位置self.rect.left -= self.speedelif self.direction == 'R':#判断坦克位置是否越过有边界if self.rect.left + self.rect.width < WINDOW_WIDTH: #向右移动坦克位置self.rect.left += self.speedelif self.direction == 'U':#判断坦克位置是否越过上边界if self.rect.top > 0:#向上移动坦克位置self.rect.top -= self.speedelif self.direction == 'D':#判断坦克位置是否越过下边界if self.rect.top + self.rect.height < WINDOW_HEIGHT:# 向下移动坦克self.rect.top += self.speeddef shot(self) -> None:'''坦克射击'''passdef tank_hit_wall(self) -> None:'''检测坦克和墙壁的碰撞'''for wall in MainGame.wall_list: # 遍历墙壁列表if collide_rect(self,wall): # 判断是否碰撞# 恢复坦克位置self.rect.left = self.old_leftself.rect.top = self.old_topdef tank_collide_tank(self,tank) -> None:'''检测坦克和坦克是否碰撞'''if self and self.live and tank and tank.live: # 坦克存活时检测if collide_rect(self,tank): # 判断是否碰撞# 恢复坦克位置self.rect.left = self.old_leftself.rect.top = self.old_top 

我方坦克类

class MyTank(Tank):'''我方坦克类'''def __init__(self) -> None:super(MyTank,self).__init__() # 继承父类的构造方法# 加载坦克图片资源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.get(self.direction)# 获取图片矩形self.rect = self.image.get_rect()# 设置我方坦克位置self.rect.left = 350self.rect.top = 400# 坦克移动的速度self.speed = 15# 增加坦克移动的状态self.remove = False

敌方坦克类

class EnemyTank(Tank):'''敌方坦克类'''def __init__(self,left,top,speed) -> None:super(EnemyTank,self).__init__()# 加载敌方坦克图片资源self.images = {'U':pygame.image.load("./img/enemy1U.gif"),'D':pygame.image.load("./img/enemy1D.gif"),'R':pygame.image.load("./img/enemy1R.gif"),'L':pygame.image.load("./img/enemy1L.gif"),}# 设置坦克方向self.direction = self.rand_direction()# 获取图片信息self.image = self.images.get(self.direction)# 获取图片的矩形self.rect = self.image.get_rect()# 设置坦克速度self.speed = speed# 设置坦克位置self.rect.left = leftself.rect.top = top# 设置敌方坦克移动的步长self.step = 6def shot(self): # 方法重写'''敌方坦克射击'''num = random.randint(1,100)if num < 5:return Bullet(self)def rand_direction(self) -> str:'''生成坦克方向'''num = random.randint(1,4)if num == 1:return "U"elif num == 2:return "D"elif num == 3:return "R"elif num == 4:return "L"def rand_move(self):'''随机移动敌方坦克'''if self.step < 0:self.direction = self.rand_direction()self.step = 6else:self.move()self.step -= 1

子弹类

  1. 子弹的属性
  • 子弹的图片资源、子弹的图形信息、子弹的位置、子弹的移动速度、子弹的存活状态
  1. 子弹的方法
  • 子弹的移动、子弹碰撞敌方坦克、子弹碰撞我方坦克、子弹碰撞墙壁、子弹的显示
  1. 代码
class Bullet:'''子弹类'''   def __init__(self,tank) -> None:# 加载图片self.images = pygame.image.load("./img/enemymissile.gif")# 获取子弹方向self.direction = tank.direction# 获得子弹图形self.rect = self.images.get_rect()# 设置子弹位置if self.direction == 'U':self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top - self.rect.heightelif self.direction == 'D':self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2self.rect.top = tank.rect.top + tank.rect.heightelif self.direction == 'L':self.rect.left = tank.rect.left - self.rect.widthself.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2elif self.direction == 'R':self.rect.left = tank.rect.left + tank.rect.widthself.rect.top = tank.rect.top + tank.rect.height / 2 - self.rect.height / 2# 设置子弹的速度self.speed = 10# 设置子弹状态self.live = Truedef hit_enemy_tank(self):'''检测子弹是否碰撞敌方坦克'''for e_tank in MainGame.etank_list:if collide_rect(self,e_tank): # 检测子弹是否碰撞敌方坦克# 爆炸效果explode = Explode(e_tank)MainGame.explode_list.append(explode)e_tank.live = False # 修改坦克状态self.live = False # 修改子弹状态def hit_my_tank(self):'''检测子弹是否碰撞我方坦克'''if MainGame.my_tank and MainGame.my_tank.live and collide_rect(self,MainGame.my_tank): # 检测子弹是否碰撞我方坦克# 爆炸效果explode = Explode(MainGame.my_tank)MainGame.explode_list.append(explode)MainGame.my_tank.live = False # 修改坦克状态self.live = False # 修改子弹状态MainGame.my_tank = Nonedef hit_wall(self):'''检测子弹是否碰撞墙壁,若碰撞墙壁,改变子弹存活状态'''for wall in MainGame.wall_list:if collide_rect(self,wall): # 检测子弹是否碰撞墙壁self.live = False # 修改子弹状态wall.hp -= 1 # 减少墙壁血量if wall.hp <= 0: # 墙壁血量小于等于0,移除墙壁wall.live = False # 修改墙壁状态# 创建攻击墙壁的声音hit_wall_music = Music("./img/hit.wav")hit_wall_music.play_music()#显示子弹def display_bullet(self) -> None:MainGame.window.blit(self.images,self.rect)#移动子弹def move(self) -> None:if self.direction == 'U':if self.rect.top > 0:self.rect.top -= self.speedelse:self.live = False # 子弹达到窗口边界,改变存活状态elif self.direction == 'D':if self.rect.top + self.rect.height < WINDOW_HEIGHT:self.rect.top += self.speedelse:self.live =  False # 子弹达到窗口边界,改变存活状态elif self.direction == 'L':if self.rect.left > 0:self.rect.left -= self.speedelse:self.live = False # 子弹达到窗口边界,改变存活状态elif self.direction == 'R':if self.rect.left + self.rect.width < WINDOW_WIDTH:self.rect.left += self.speedelse:self.live = False # 子弹达到窗口边界,改变存活状态

墙壁类

  1. 墙壁的属性
  • 墙壁的图片资源、墙壁的图形信息、墙壁的位置、墙壁的生命值、墙壁的存活状态
  1. 墙壁的方法
  • 墙壁的显示
  1. 代码
class Wall:'''墙壁类''' def __init__(self,left,top) -> None:# 加载墙壁图片资源self.image = pygame.image.load("./img/steels.gif")# 获取墙壁图形self.rect = self.image.get_rect()# 设置墙壁位置self.rect.left = leftself.rect.top = top# 设置墙壁生命值self.hp = 5# 设置墙壁状态self.live = True#显示墙壁def display_wall(self) -> None:MainGame.window.blit(self.image,self.rect)

爆炸类

  1. 爆炸的属性
  • 爆炸的图片资源、爆炸的图形信息、爆炸的位置、爆炸的状态
  1. 爆炸的方法
  • 爆炸的显示
  1. 代码
class Explode:'''爆炸效果类'''def __init__(self,tank:Tank) -> None:# 加载爆炸图片资源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.rect = tank.rect# 设置爆炸的索引self.step = 0# 获取爆炸图片self.image = self.images[self.step]# 设置爆炸状态self.live = True#显示爆炸def display_explode(self) -> None:if self.step < len(self.images):self.image = self.images[self.step] #获得爆炸动画图片MainGame.window.blit(self.image,self.rect) # 渲染爆炸效果self.step += 1 else:self.step = 0self.live = False

音效类

  1. 音效的属性
  • 音乐资源
  1. 音效的方法
  • 音效的播放:不同的音效在不同的敌方播放
  1. 代码
class Music:'''音乐音效类'''    def __init__(self,filename) -> None:# 初始化mixerpygame.mixer.init()# 加载音乐文件pygame.mixer.music.load(filename)#显示音乐def play_music(self) -> None:# 播放音乐pygame.mixer.music.play()

游戏主窗口类

  1. 游戏所有的对象都要在主窗口类中创建对象,然后调用方法运行。
  2. 主窗口类的方法:
  • 最重要的是开始游戏方法,所有的对象、方法都要在这个方法里创建、运行。
  • 另外在开发过程中,可以根据具体需求,在主窗口类中添加新的方法和属性,用来辅助一些功能的实现。
  • 对于一些参数,可以设置为全局性属性,需要修改时找到定义的变量即可。
  1. 代码
    全局性变量
# 通用属性设置
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 700
BG_COLOR = pygame.Color(0,0,0)
TEXT_COLOR = pygame.Color(255,0,0)

主窗口类

class MainGame:'''游戏主窗口类'''# 游戏主窗口对象window = None# 坦克对象my_tank = None# 敌方坦克数量etank_count = 6# 存储敌方坦克列表etank_list = []# 存储子弹列表my_bullet_list = []# 存储敌方子弹列表etank_bullet_list = []# 存储爆炸列表explode_list = []# 存储墙壁列表wall_list = []def __init__(self) -> None:passdef start_game(self) -> None:'''开始游戏'''# 初始化窗口模块pygame.display.init()# 创建窗口MainGame.window = pygame.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))#设置窗口标题pygame.display.set_caption("坦克大战1.0")# 创建一个我方坦克self.create_my_tank()# 创建敌方坦克self.create_enemy_tank()# 创建墙壁self.create_wall()# 刷新窗口while True:# 刷新的慢一点sleep(0.03)# 设置窗口背景颜色MainGame.window.fill(BG_COLOR)# 设置提示文字# 1.获得文字#num = 6text = self.get_surface_text(f"敌方坦克剩余{len(MainGame.etank_list)}")# 2.把文字放到窗口中MainGame.window.blit(text,(10,10))# 增加事件处理self.get_event()# 判断我方坦克是否存活if MainGame.my_tank and MainGame.my_tank.live:# 显示我方坦克MainGame.my_tank.display_tank()# 移动我方坦克if MainGame.my_tank.remove:MainGame.my_tank.move()# 检测我方坦克是否和墙壁发生碰撞MainGame.my_tank.tank_hit_wall()for e_tank in MainGame.etank_list:# 检测我方坦克是否和敌方坦克发生碰撞MainGame.my_tank.tank_collide_tank(e_tank)# 显示敌方坦克self.display_etank()# # 坦克移动状态为True时再移动# if MainGame.my_tank and MainGame.my_tank.live and MainGame.my_tank.remove:#     MainGame.my_tank.move()# 显示我方子弹self.display_my_bullet()# 显示敌方子弹self.display_etank_bullet()# 显示爆炸效果self.display_explode()# 显示墙壁self.display_wall()pygame.display.update()def create_wall(self) -> None:'''创建墙壁'''for i in range(7):wall = Wall(i*120,300)MainGame.wall_list.append(wall)def display_wall(self) -> None:'''显示墙壁'''for wall in MainGame.wall_list: # 遍历墙壁列表if wall.live: # 墙壁存活时在显示墙壁wall.display_wall()else:MainGame.wall_list.remove(wall)def create_my_tank(self) -> None:'''创建我方坦克'''MainGame.my_tank = MyTank()# 播放音乐start_music = Music("./img/start.wav") #创建音乐对象start_music.play_music() # 播放音乐def display_explode(self) -> None:'''显示爆炸效果'''for explode in MainGame.explode_list: # 遍历爆炸列表if explode.live: # 爆炸存活才爆炸explode.display_explode()else:MainGame.explode_list.remove(explode)# 显示我方子弹def display_my_bullet(self):for my_bullet in MainGame.my_bullet_list: # 遍历子弹列表if my_bullet.live: # 子弹存活才在窗口显示子弹my_bullet.display_bullet() # 在窗口显示子弹my_bullet.move() #子弹移动my_bullet.hit_enemy_tank() # 子弹与敌方坦克碰撞检测my_bullet.hit_wall() # 子弹与墙壁碰撞检测else:MainGame.my_bullet_list.remove(my_bullet) # 子弹不存活,不显示且把该子弹从列表中删除def create_enemy_tank(self):'''创建敌方坦克'''self.top = 100self.speed = 6for _ in range(MainGame.etank_count):left = random.randint(0,600)# 创建地方坦克对象eTank = EnemyTank(left,self.top,self.speed)# 把生成的敌方坦克对象放入列表self.etank_list.append(eTank)def display_etank(self) -> None:'''显示敌方坦克'''for e_tank in self.etank_list:if e_tank.live: # 敌方坦克存活e_tank.display_tank() # 显示坦克e_tank.rand_move() # 随机移动e_tank.tank_hit_wall() # 敌方坦克与墙壁碰撞检测e_tank.tank_collide_tank(MainGame.my_tank) # 敌方坦克与我方坦克碰撞检测e_bullet = e_tank.shot() # 敌方坦克射击if e_bullet:MainGame.etank_bullet_list.append(e_bullet) else:MainGame.etank_list.remove(e_tank) # 敌方坦克不存活,不显示且把该坦克从列表中删除def display_etank_bullet(self):'''显示敌方坦克子弹'''for e_bullet in MainGame.etank_bullet_list: # 遍历子弹列表if e_bullet.live: # 子弹存活才显示子弹e_bullet.display_bullet() # 显示子弹e_bullet.move() # 子弹移动e_bullet.hit_my_tank() # 子弹与我方坦克碰撞检测e_bullet.hit_wall() # 子弹与墙壁碰撞检测else:MainGame.etank_bullet_list.remove(e_bullet)def end_game(self) -> None:'''结束游戏'''print("谢谢使用,欢迎再次使用")exit()def get_event(self) -> None:'''获取事件'''# 从系统的输入队列获取所有事件event_list = pygame.event.get()# 遍历事件for event in event_list:# 判断事件# 关闭游戏if event.type == pygame.QUIT:# 关闭按钮self.end_game()# 键盘检测if event.type == pygame.KEYDOWN:# 我方坦克不存活时if not MainGame.my_tank and event.key == pygame.K_ESCAPE:# 按下esc我方坦克重生print("我方坦克重生")self.create_my_tank()# 我方坦克存活存活时if MainGame.my_tank and MainGame.my_tank.live:# 坦克移动if event.key == pygame.K_LEFT:print("坦克向左移动")MainGame.my_tank.direction = 'L'# 改变坦克移动状态MainGame.my_tank.remove = Trueelif event.key == pygame.K_RIGHT:print("坦克向右移动")MainGame.my_tank.direction = 'R'# 改变坦克移动状态MainGame.my_tank.remove = Trueelif event.key == pygame.K_UP:print("坦克向上移动")MainGame.my_tank.direction = 'U'# 改变坦克移动状态MainGame.my_tank.remove = Trueelif event.key == pygame.K_DOWN:MainGame.my_tank.direction = 'D'# 改变坦克移动状态MainGame.my_tank.remove = Trueprint("坦克向下移动")elif event.key == pygame.K_SPACE:if len(MainGame.my_bullet_list) < 5: # 限制子弹数量print("发射子弹")# 创建子弹my_bullet = Bullet(MainGame.my_tank)# 将子弹添加到列表中MainGame.my_bullet_list.append(my_bullet)# 播放发射子弹的音效shot_music = Music("./img/fire.wav")shot_music.play_music()# 键盘检测:松开特定键盘时触发的事件if event.type == pygame.KEYUP and event.key in (pygame.K_LEFT,pygame.K_RIGHT,pygame.K_UP,pygame.K_DOWN) and MainGame.my_tank:MainGame.my_tank.remove = Falsedef get_surface_text(self,text:str) -> None:'''获得文字的图片'''# 初始化字体模块pygame.font.init()# 创建字体font = pygame.font.SysFont("kaiti",18)# 绘制文字信息surface_text = font.render(text,True,TEXT_COLOR)# 将绘制的文字信息返回return surface_text

收获

  1. 熟悉了使用python的pygame库来开发游戏的一些常用模块和方法。
  2. 学会了使用面向对象思想和第三方库来设计并开发游戏的流程和方法。
  3. 学会了在开发过程中为了开发某个功能而去添加某个属性或方法,并且可以检索并解决因为属性和方法的变动产生的报错。
  4. 对于项目功能的整体设计可以去略微有效的去摸索合理优雅的写法。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com