项目代码详见:https://github.com/xiaozhou-alt/Tank-Domination
一、项目介绍
这是一个基于 Python 和 Pygame 库开发的 2D 坦克大战游戏。游戏包含以下主要功能:
- 玩家控制坦克移动和射击(方向键移动、空格键射击、Esc 复活吧我的坦克!)
- 敌方AI坦克随机移动和攻击
- 多种地图元素:墙壁、铁墙、河水、草丛
- 爆炸效果和音效
- 坦克碰撞检测和子弹碰撞检测
二、项目实现
1.文件夹结构
Tank-Domination/
├── tank.py # 主游戏文件
├── img/ # 游戏资源文件夹
│ ├── *.gif # 图片资源
│ └── *.wav # 音效资源
└── demo.gif # 游戏演示
2.代码实现
代码中使用了大量的 类 定义和图片贴图,若是读者还在为找不到游戏的图片和音效素材烦恼,那么小周建议可以看一看我的上一篇文章:《超简单!用Pygame实现贪吃蛇游戏!》,其中详细介绍的两个网站 OpenGameArt 和 Iconfont
这里我就只针对代码的实现来进行介绍:
1.主逻辑MainGame
class MainGame():
window = None
screen_width = 1000
screen_height = 700
my_tank = None
enemytank_list = []
bullet_list = []
ebullet_list = []
explode_list = []
wall_list = []
steelwall_list = []
water_list = []
grass_list = []
MainGame 类是游戏的核心控制器,负责管理整个游戏流程:
- window 变量存储游戏主窗口对象
- screen_width 和 screen_height 定义游戏窗口尺寸为1000x700像素
- my_tank 存储玩家坦克对象,enemytank_list 存储敌方坦克列表
- bullet_list 和ebullet_list 分别存储玩家和敌方子弹
- explode_list 管理爆炸效果
- wall_list 等存储各种地图元素。
2.游戏函数调用
def start_game(self):
pd.init()
MainGame.window = pd.set_mode([MainGame.screen_width, MainGame.screen_height])
pd.set_caption('坦克大战 v1.0')
self.create_mytank()
self.create_enemytank()
self.create_wall()
self.create_steelwall()
self.create_water()
self.create_grass()
start_game方法是游戏的入口点:
- 首先初始化 pygame 引擎( pd.init() ),然后创建游戏窗口并设置标题
- create_mytank 创建玩家坦克,create_enemytank 生成敌方坦克等方法(
这里函数命名还是非常浅显的,相信读者理解起来并不困难)创建各种地图元素。 - 这些初始化工作为游戏运行做好准备,确保所有游戏对象在游戏开始前都已正确创建。
3.游戏主循环
while 1:
time.sleep(0.02)
MainGame.window.fill(color_black)
self.get_Event()
MainGame.window.blit(self.get_TextSurface('剩余敌方坦克%d辆' % len(MainGame.enemytank_list)), (20, 20))
self.blit_wall()
self.blit_steelwall()
self.blit_water()
self.blit_grass()
if MainGame.my_tank.live:
MainGame.my_tank.displayTank()
self.blit_enemytank()
游戏主循环是游戏运行的核心,每帧执行以下操作:
- time.sleep(0.02) 控制游戏帧率,使游戏运行更流畅
- window.fill(color_black) 清空屏幕为黑色
- get_Event() 处理用户输入
- blit_TextSurface 显示剩余敌方坦克数量
- blit_wall 等方法渲染各种地图元素
- 最后检查玩家坦克是否存活并渲染坦克
这个循环持续运行,直到游戏结束。
4.Tank类与Bullet类
class Tank(BaseItem):
def __init__(self, left, top):
self.images = {
'UP': pygame.image.load(r'img/p1tankU.gif'),
'DOWN': pygame.image.load(r'img/p1tankD.gif'),
'LEFT': pygame.image.load(r'img/p1tankL.gif'),
'RIGHT': pygame.image.load(r'img/p1tankR.gif')
}
self.direction = 'UP'
self.image = self.images[self.direction]
self.rect = self.image.get_rect()
self.rect.left = left
self.rect.top = top
self.speed = 7
self.stop = True
self.live = True
Tank 类是坦克的基类,定义了坦克的基本属性和行为:
- images 字典存储坦克四个方向的图片资源
- direction 表示当前方向
- image 是当前显示的图片
- rect 是坦克的矩形区域用于碰撞检测
- speed 控制坦克移动速度
- stop 标志坦克是否停止移动
- live 表示坦克是否存活
这个基类为我方坦克和敌方坦克提供了共同的基础功能(作为父类,我方和敌方坦克都继承于 Tank 类)
此处选用了游戏较为经典的黄绿坦克配色:
我方坦克:
敌方坦克:
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 == 'UP':
self.rect.left = tank.rect.left + tank.rect.width / 2 - self.rect.width / 2
self.rect.top = tank.rect.top - self.rect.height
self.speed = 13
self.live = True
Bullet 类实现了子弹的逻辑:
- image 加载子弹图片
- direction 继承自发射坦克的方向
根据方向不同,子弹的初始位置也不同:
- 向上发射时,子弹位于坦克正上方;其他方向类似
- speed 控制子弹飞行速度
- live 标志子弹是否有效(我设定为普通墙壁被子弹击打两次会消失,铁墙不会消失)
这个类处理了子弹的创建、移动和碰撞检测,是游戏战斗系统的核心部分
除了以上的两个类以外,其实游戏中涉及到的普通墙壁、铁墙、草丛、河流、爆炸效果和音乐实现较为简单,留给读者自己解读代码(不过小周也是有注释的哦~(´•ω•̥`) )
5.碰撞逻辑
碰撞作为这个游戏较为重要的逻辑实现,此处格外说明一下:
def tank_hit_walls(self):
for wall in MainGame.wall_list:
if pygame.sprite.collide_rect(self, wall):
self.stay()
def bullet_move(self):
if self.direction == 'UP':
if self.rect.top > 0:
self.rect.top -= self.speed
else:
self.live = False
游戏实现了多种碰撞检测:
- tank_hit_walls 检测坦克与墙壁的碰撞
- 使用 pygame 的 collide_rect 方法进行矩形碰撞检测
- 如果碰撞则调用 stay 方法恢复坦克位置
- bullet_move 处理子弹移动和边界检测
- 当子弹到达屏幕边缘时设置 live 为 False 使其消失
6.输入处理
def get_Event(self):
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
self.end_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
MainGame.my_tank.direction = 'LEFT'
MainGame.my_tank.stop = False
MainGame.my_tank.move()
elif event.key == pygame.K_SPACE:
b = Bullet(MainGame.my_tank)
if len(MainGame.bullet_list) < 3:
MainGame.bullet_list.append(b)
get_Event 方法处理玩家输入:
- 检测 QUIT 事件(点击关闭按钮)来结束游戏,处理方向键控制坦克移动,空格键发射子弹
- 方向键改变坦克方向并开始移动,空格键创建新子弹(最多3发)
三、结果展示
基于pygame实现童年游戏《坦克大战》
如果你喜欢我的文章,不妨给小周一个免费的点赞和关注吧!