🎮 Python坦克大战:用代码复活你的童年回忆!

还记得小时候和小伙伴们围在老式电视机前,手柄按得啪啪响,指挥着小坦克在砖块迷宫里激战的日子吗?那个经典的坦克大战,现在用Python就能亲手打造出来!今天就带你看看这个用代码重新演绎的经典游戏,保证让你手痒想马上运行试试!✨
在这里插入图片描述

🕹️ 游戏快览:你的Python版坦克战场

这个项目用Pygame库把经典坦克大战搬到了电脑屏幕上!玩家控制蓝色坦克,在充满障碍的战场里和红色AI坦克展开激烈交火。游戏里有三种关卡,弹药还限量——没错,你不能无脑突突突,得有点策略!

核心玩法一目了然

  • 🚀 WASD/方向键控制坦克移动
  • 💥 空格键发射子弹(省着点用,就20发!)
  • 🎯 目标:干掉所有红色敌人,闯过3个越来越难的关卡
  • 🏃 逃生:别被敌人打中,你只有3条命!

🎨 视觉盛宴:简洁明了的战场设计

游戏画面走的是清晰实用风:

  • 🟦 蓝色坦克是你,头顶三个小红心就是你的血条
  • 🟥 红色坦克是AI敌人,会自己移动和开火
  • 🟫 棕色墙壁可以打穿,创造新路线
  • 🪨 灰色墙壁是永久障碍,得绕道走
  • 💛 黄色子弹是你打的,❤️ 红色子弹是敌人射的

屏幕上方实时显示你的分数、当前关卡、剩余弹药和敌人数量——所有信息一眼掌握!

💻 技术揭秘:看看代码有多酷

这个项目的代码写得特别清晰,就像乐高积木一样模块化:

四大核心积木块

  1. Tank - 坦克的大脑和身体
  2. Bullet - 子弹的飞行轨迹
  3. Wall - 墙壁的坚固程度
  4. Game - 整个游戏的指挥中心

AI敌人有点小聪明

# 敌人会随机决定往哪走
move_choice = random.randint(0, 30)  # 大约3%的概率会改变方向
# 还会看心情开火(每帧2%的概率)
if random.random() < 0.02:  # “嘿,吃我一炮!”

物理碰撞真实感
坦克不能穿墙,子弹打到墙会消失,打到敌人会加分——所有互动都有模有样!

🎯 游戏体验:策略与操作的完美结合

这可不是无脑射击游戏!你得:

  • 规划路线:哪些墙该打穿,哪些该绕开
  • 管理资源:只有20发子弹,打完就得等下一关
  • 预判走位:敌人虽然有点随机,但也不是完全无规律
  • 控制节奏:太快冲出去容易被集火,太怂又打不完敌人

每过一关都有奖励:弹药回满,血量回复1点,敌人数量还变多——挑战越来越刺激!

🚀 一键开玩:超级简单的入门指南

  1. 安装必备工具(就一行命令!):

    pip install pygame
    
  2. 复制代码:把用户提供的完整代码保存为tank_game.py

  3. 运行游戏

    python tank_game.py
    
  4. 开始战斗!WASD移动,空格射击,目标是在弹药用完前消灭所有敌人!

🌟 为什么这个项目这么棒?

对新手友好:代码结构清晰,注释详细,是学习Python游戏开发的绝佳材料

可玩性高:三个关卡难度递进,每次重玩地图还会随机生成

扩展性强:想加新功能?简单!比如:

  • 加个弹药包道具(打掉特定墙壁后掉落)
  • 设计Boss坦克(血厚攻高)
  • 实现双人模式(和朋友一起玩)

怀旧感满分:经典玩法的现代重现,瞬间找回童年感觉

💡 小贴士与隐藏技巧

🎮 高手秘诀

  • 贴着墙走比较安全,但注意别被堵在死角
  • 先打穿关键墙壁,创造有利地形
  • 敌人子弹是红色的,注意闪避!
  • 每关开始的弹药规划很重要——别一开始就把子弹打光了

🐛 调试乐趣:如果想调整游戏难度,可以直接改代码里的常数:

  • 想更简单?把MAX_AMMO = 20改成30
  • 想挑战?把PLAYER_SPEED = 4改成3
  • 想爽快?把ENEMY_FIRE_RATE = 0.02改成0.01

📈 从玩家到创造者

这个项目最酷的地方在于:你不只是玩家,还是游戏设计师!运行几次后,你可能已经开始想:

“要是能加个冰冻子弹让敌人减速就好了……”
“搞个可以反弹子弹的金属墙应该很酷!”
“双人合作模式必须安排上!”

——而这些想法,你都可以自己动手实现!代码就在那里,随时等你来魔改。

🎉 结语:你的坦克,你的战场

用Python重现经典游戏,就像是给了童年回忆一次高科技升级。这个坦克大战项目不仅好玩,更是一扇通往游戏开发世界的大门。清晰的代码结构让你能轻松理解每个部分的工作原理,从碰撞检测到AI逻辑,从状态管理到资源系统——游戏开发的核心概念这里都有了。

最棒的是,当你看到自己写的代码变成可以实际游玩的游戏,那种成就感简直爆棚!屏幕上的坦克听你指挥,敌人AI按你写的逻辑行动,整个游戏世界因你的代码而生动——这就是编程的魅力。

还等什么?复制代码,运行起来,指挥你的蓝色坦克冲锋吧!记得分享给你的朋友,看看谁能通更高分~ 🏆

游戏愉快,编程快乐! 🚀


P.S. 如果卡关了,偷偷告诉你:可以在代码里给自己“开个外挂”——不过,自己挑战过关的成就感才是最棒的,不是吗?😉

🎉 完整代码

在这里插入图片描述

import pygame
import random
import math
import sys

# 初始化Pygame
pygame.init()

# 游戏窗口设置
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tank Battle")

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 100, 255)
YELLOW = (255, 255, 50)
GRAY = (150, 150, 150)
BROWN = (165, 42, 42)
DARK_GREEN = (0, 100, 0)

# 游戏常量
FPS = 60
PLAYER_SPEED = 4
BULLET_SPEED = 8
ENEMY_SPEED = 2
ENEMY_FIRE_RATE = 0.02  # 每帧敌人开火的概率
PLAYER_FIRE_RATE = 15  # 玩家发射子弹的最小帧间隔
WALL_SIZE = 30
GRID_SIZE = 20
MAX_ENEMIES = 5
MAX_AMMO = 20
ENEMY_RESPAWN_TIME = 300  # 敌人重生时间(帧)


class Tank:
    def __init__(self, x, y, color, is_player=False):
        self.x = x
        self.y = y
        self.color = color
        self.width = 40
        self.height = 40
        self.direction = 0  # 0: 上, 1: 右, 2: 下, 3: 左
        self.is_player = is_player
        self.health = 3 if is_player else 1
        self.cooldown = 0
        self.alive = True
        self.speed = PLAYER_SPEED if is_player else ENEMY_SPEED

    def move(self, dx, dy, walls):
        # 计算新位置
        new_x = self.x + dx
        new_y = self.y + dy

        # 创建坦克的矩形
        tank_rect = pygame.Rect(new_x, new_y, self.width, self.height)

        # 检查是否与墙壁碰撞
        can_move = True
        for wall in walls:
            if tank_rect.colliderect(wall.rect) and wall.destructible:
                can_move = False
                break

        # 检查边界
        if new_x < 0 or new_x + self.width > WIDTH or new_y < 0 or new_y + self.height > HEIGHT:
            can_move = False

        # 如果可移动,则更新位置
        if can_move:
            self.x = new_x
            self.y = new_y

        # 更新方向
        if dx > 0:
            self.direction = 1
        elif dx < 0:
            self.direction = 3
        elif dy > 0:
            self.direction = 2
        elif dy < 0:
            self.direction = 0

    def update(self, walls):
        if not self.alive:
            return

        if self.cooldown > 0:
            self.cooldown -= 1

        # 敌人AI
        if not self.is_player and self.alive:
            # 简单AI:随机移动和开火
            move_choice = random.randint(0, 30)
            if move_choice == 0:
                self.move(-self.speed, 0, walls)
            elif move_choice == 1:
                self.move(self.speed, 0, walls)
            elif move_choice == 2:
                self.move(0, -self.speed, walls)
            elif move_choice == 3:
                self.move(0, self.speed, walls)

            # 随机开火
            if random.random() < ENEMY_FIRE_RATE and self.cooldown == 0:
                return self.fire()
        return None

    def fire(self):
        if self.cooldown > 0:
            return None

        self.cooldown = PLAYER_FIRE_RATE if self.is_player else 30

        # 根据坦克方向计算子弹起始位置
        if self.direction == 0:  # 上
            bullet_x = self.x + self.width // 2
            bullet_y = self.y
            dx, dy = 0, -1
        elif self.direction == 1:  # 右
            bullet_x = self.x + self.width
            bullet_y = self.y + self.height // 2
            dx, dy = 1, 0
        elif self.direction == 2:  # 下
            bullet_x = self.x + self.width // 2
            bullet_y = self.y + self.height
            dx, dy = 0, 1
        else:  # 左
            bullet_x = self.x
            bullet_y = self.y + self.height // 2
            dx, dy = -1, 0

        return Bullet(bullet_x, bullet_y, dx, dy, self.is_player)

    def take_damage(self):
        self.health -= 1
        if self.health <= 0:
            self.alive = False
            return True
        return False

    def draw(self, surface):
        if not self.alive:
            return

        # 绘制坦克主体
        tank_rect = pygame.Rect(self.x, self.y, self.width, self.height)
        pygame.draw.rect(surface, self.color, tank_rect)
        pygame.draw.rect(surface, WHITE, tank_rect, 2)

        # 绘制坦克炮管
        if self.direction == 0:  # 上
            pygame.draw.rect(surface, DARK_GREEN,
                             (self.x + self.width // 2 - 5, self.y - 15, 10, 20))
        elif self.direction == 1:  # 右
            pygame.draw.rect(surface, DARK_GREEN,
                             (self.x + self.width, self.y + self.height // 2 - 5, 20, 10))
        elif self.direction == 2:  # 下
            pygame.draw.rect(surface, DARK_GREEN,
                             (self.x + self.width // 2 - 5, self.y + self.height, 10, 20))
        else:  # 左
            pygame.draw.rect(surface, DARK_GREEN,
                             (self.x - 20, self.y + self.height // 2 - 5, 20, 10))

        # 绘制生命值(仅对玩家)
        if self.is_player:
            for i in range(self.health):
                pygame.draw.rect(surface, RED,
                                 (self.x + i * 12, self.y - 15, 10, 10))


class Bullet:
    def __init__(self, x, y, dx, dy, is_player):
        self.x = x
        self.y = y
        self.dx = dx
        self.dy = dy
        self.radius = 5
        self.speed = BULLET_SPEED
        self.is_player = is_player
        self.color = YELLOW if is_player else RED
        self.alive = True

    def update(self):
        self.x += self.dx * self.speed
        self.y += self.dy * self.speed

        # 检查是否出界
        if (self.x < 0 or self.x > WIDTH or
                self.y < 0 or self.y > HEIGHT):
            self.alive = False

    def draw(self, surface):
        if self.alive:
            pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)
            pygame.draw.circle(surface, WHITE, (int(self.x), int(self.y)), self.radius, 1)

    def get_rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius,
                           self.radius * 2, self.radius * 2)


class Wall:
    def __init__(self, x, y, destructible=True):
        self.x = x
        self.y = y
        self.destructible = destructible
        self.color = BROWN if destructible else GRAY
        self.rect = pygame.Rect(x, y, WALL_SIZE, WALL_SIZE)
        self.alive = True

    def draw(self, surface):
        if self.alive:
            pygame.draw.rect(surface, self.color, self.rect)
            pygame.draw.rect(surface, WHITE, self.rect, 1)
            # 添加纹理
            if self.destructible:
                pygame.draw.line(surface, (139, 69, 19),
                                 (self.x + 5, self.y + 5),
                                 (self.x + WALL_SIZE - 5, self.y + WALL_SIZE - 5), 2)
                pygame.draw.line(surface, (139, 69, 19),
                                 (self.x + WALL_SIZE - 5, self.y + 5),
                                 (self.x + 5, self.y + WALL_SIZE - 5), 2)
            else:
                # 不可破坏的墙壁有网格纹理
                for i in range(0, WALL_SIZE, 5):
                    pygame.draw.line(surface, (100, 100, 100),
                                     (self.x, self.y + i),
                                     (self.x + WALL_SIZE, self.y + i), 1)


class Game:
    def __init__(self):
        self.player = Tank(WIDTH // 2, HEIGHT - 100, BLUE, True)
        self.enemies = []
        self.bullets = []
        self.walls = []
        self.score = 0
        self.level = 1
        self.ammo = MAX_AMMO
        self.game_over = False
        self.game_won = False
        self.enemy_respawn_timer = 0
        self.generate_walls()
        self.spawn_enemies(3)

    def generate_walls(self):
        # 创建边界墙
        for x in range(0, WIDTH, WALL_SIZE):
            self.walls.append(Wall(x, 0, False))
            self.walls.append(Wall(x, HEIGHT - WALL_SIZE, False))

        for y in range(WALL_SIZE, HEIGHT - WALL_SIZE, WALL_SIZE):
            self.walls.append(Wall(0, y, False))
            self.walls.append(Wall(WIDTH - WALL_SIZE, y, False))

        # 创建随机可破坏墙壁
        for _ in range(30):
            x = random.randint(3, (WIDTH // WALL_SIZE) - 4) * WALL_SIZE
            y = random.randint(3, (HEIGHT // WALL_SIZE) - 4) * WALL_SIZE

            # 确保不在玩家起始位置周围生成墙
            if (abs(x - self.player.x) > 100 or abs(y - self.player.y) > 100):
                self.walls.append(Wall(x, y, True))

        # 创建一些不可破坏的障碍物
        for _ in range(10):
            x = random.randint(2, (WIDTH // WALL_SIZE) - 3) * WALL_SIZE
            y = random.randint(2, (HEIGHT // WALL_SIZE) - 3) * WALL_SIZE

            if (abs(x - self.player.x) > 100 or abs(y - self.player.y) > 100):
                self.walls.append(Wall(x, y, False))

    def spawn_enemies(self, count):
        for _ in range(count):
            # 在远离玩家的位置生成敌人
            while True:
                x = random.randint(50, WIDTH - 50)
                y = random.randint(50, HEIGHT // 2)

                # 确保敌人不与玩家太近
                if (abs(x - self.player.x) > 200 or abs(y - self.player.y) > 200):
                    break

            self.enemies.append(Tank(x, y, RED))

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return False

                if self.game_over or self.game_won:
                    if event.key == pygame.K_r:
                        self.__init__()  # 重置游戏
                elif event.key == pygame.K_SPACE and self.ammo > 0:
                    bullet = self.player.fire()
                    if bullet:
                        self.bullets.append(bullet)
                        self.ammo -= 1

        if not self.game_over and not self.game_won:
            keys = pygame.key.get_pressed()
            dx, dy = 0, 0

            if keys[pygame.K_LEFT] or keys[pygame.K_a]:
                dx = -PLAYER_SPEED
            if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
                dx = PLAYER_SPEED
            if keys[pygame.K_UP] or keys[pygame.K_w]:
                dy = -PLAYER_SPEED
            if keys[pygame.K_DOWN] or keys[pygame.K_s]:
                dy = PLAYER_SPEED

            # 对角线移动速度修正
            if dx != 0 and dy != 0:
                dx *= 0.7071
                dy *= 0.7071

            self.player.move(dx, dy, self.walls)

        return True

    def update(self):
        if self.game_over or self.game_won:
            return

        # 更新玩家
        self.player.update(self.walls)

        # 更新敌人
        for enemy in self.enemies[:]:
            bullet = enemy.update(self.walls)
            if bullet:
                self.bullets.append(bullet)

        # 更新子弹
        for bullet in self.bullets[:]:
            bullet.update()

            # 检查子弹是否击中墙壁
            for wall in self.walls[:]:
                if wall.alive and bullet.get_rect().colliderect(wall.rect):
                    bullet.alive = False
                    if wall.destructible:
                        wall.alive = False
                        self.walls.remove(wall)
                    break

            # 检查子弹是否击中玩家
            if not bullet.is_player and bullet.alive:
                player_rect = pygame.Rect(self.player.x, self.player.y,
                                          self.player.width, self.player.height)
                if bullet.get_rect().colliderect(player_rect) and self.player.alive:
                    bullet.alive = False
                    if self.player.take_damage():
                        self.game_over = True

            # 检查子弹是否击中敌人
            if bullet.is_player and bullet.alive:
                for enemy in self.enemies[:]:
                    enemy_rect = pygame.Rect(enemy.x, enemy.y, enemy.width, enemy.height)
                    if bullet.get_rect().colliderect(enemy_rect) and enemy.alive:
                        bullet.alive = False
                        if enemy.take_damage():
                            self.enemies.remove(enemy)
                            self.score += 100

            # 移除已消失的子弹
            if not bullet.alive and bullet in self.bullets:
                self.bullets.remove(bullet)

        # 敌人重生逻辑
        if len(self.enemies) < MAX_ENEMIES:
            self.enemy_respawn_timer += 1
            if self.enemy_respawn_timer >= ENEMY_RESPAWN_TIME:
                self.spawn_enemies(1)
                self.enemy_respawn_timer = 0

        # 检查关卡完成
        if len(self.enemies) == 0 and self.level < 3:
            self.level += 1
            self.spawn_enemies(self.level + 2)
            self.ammo = MAX_AMMO
            self.player.health = min(3, self.player.health + 1)

        # 检查游戏胜利
        if self.level >= 3 and len(self.enemies) == 0:
            self.game_won = True

    def draw(self, surface):
        # 绘制背景
        surface.fill(BLACK)

        # 绘制网格背景
        for x in range(0, WIDTH, GRID_SIZE):
            pygame.draw.line(surface, (20, 20, 20), (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, GRID_SIZE):
            pygame.draw.line(surface, (20, 20, 20), (0, y), (WIDTH, y))

        # 绘制墙壁
        for wall in self.walls:
            wall.draw(surface)

        # 绘制子弹
        for bullet in self.bullets:
            bullet.draw(surface)

        # 绘制敌人
        for enemy in self.enemies:
            enemy.draw(surface)

        # 绘制玩家
        self.player.draw(surface)

        # 绘制UI
        self.draw_ui(surface)

        # 绘制游戏结束/胜利画面
        if self.game_over:
            self.draw_game_over(surface)
        elif self.game_won:
            self.draw_game_won(surface)

    def draw_ui(self, surface):
        # 分数
        font = pygame.font.SysFont(None, 36)
        score_text = font.render(f"score: {self.score}", True, GREEN)
        surface.blit(score_text, (10, 10))

        # 等级
        level_text = font.render(f"level: {self.level}/3", True, GREEN)
        surface.blit(level_text, (10, 50))

        # 弹药
        ammo_text = font.render(f"bullet: {self.ammo}/{MAX_AMMO}", True, YELLOW)
        surface.blit(ammo_text, (WIDTH - 150, 10))

        # 敌人数量
        enemies_text = font.render(f"enemy: {len(self.enemies)}", True, RED)
        surface.blit(enemies_text, (WIDTH - 150, 50))

        # 控制说明
        controls_font = pygame.font.SysFont(None, 24)
        controls = [
            "Controls: WASD/Arrow Keys to move, Space to fire",
            "Objective: Eliminate all enemies (3 levels)",
            "Note: Limited ammunition, can destroy brown walls"
        ]

        for i, text in enumerate(controls):
            control_text = controls_font.render(text, True, WHITE)
            surface.blit(control_text, (WIDTH // 2 - 150, 10 + i * 25))

    def draw_game_over(self, surface):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 200))
        surface.blit(overlay, (0, 0))

        font_large = pygame.font.SysFont(None, 72)
        font_medium = pygame.font.SysFont(None, 36)

        game_over_text = font_large.render("game over", True, RED)
        surface.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 100))

        score_text = font_medium.render(f"finial score: {self.score}", True, WHITE)
        surface.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2))

        restart_text = font_medium.render("Press R to restart", True, GREEN)
        surface.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 100))

        quit_text = font_medium.render("Press ESC to exit", True, YELLOW)
        surface.blit(quit_text, (WIDTH // 2 - quit_text.get_width() // 2, HEIGHT // 2 + 150))

    def draw_game_won(self, surface):
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 200))
        surface.blit(overlay, (0, 0))

        font_large = pygame.font.SysFont(None, 72)
        font_medium = pygame.font.SysFont(None, 36)

        win_text = font_large.render("Victory!", True, GREEN)
        surface.blit(win_text, (WIDTH // 2 - win_text.get_width() // 2, HEIGHT // 2 - 100))

        score_text = font_medium.render(f"Final Score: {self.score}", True, WHITE)
        surface.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, HEIGHT // 2))

        restart_text = font_medium.render("Press R to restart", True, GREEN)
        surface.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 100))

        quit_text = font_medium.render("Press ESC to exit", True, YELLOW)
        surface.blit(quit_text, (WIDTH // 2 - quit_text.get_width() // 2, HEIGHT // 2 + 150))


def main():
    clock = pygame.time.Clock()
    game = Game()

    running = True
    while running:
        running = game.handle_events()
        game.update()
        game.draw(screen)

        pygame.display.flip()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐