import pygame
import sys
import math
import random
from pygame.locals import *
import heapq
import os

# ---------- 初始化 ----------
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# 启用硬件加速与双缓冲
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption("Delta Force - FPS Game")
clock = pygame.time.Clock()

# ---------- 背景渐变（光影优化）----------
bg_surf = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
for y in range(SCREEN_HEIGHT):
    t = y / SCREEN_HEIGHT
    if y < SCREEN_HEIGHT // 2:
        r = int(30 + t * 2 * 50)
        g = int(30 + t * 2 * 60)
        b = int(40 + t * 2 * 70)
    else:
        r = int(80 - (t - 0.5) * 2 * 20)
        g = int(80 - (t - 0.5) * 2 * 30)
        b = int(70 - (t - 0.5) * 2 * 20)
    pygame.draw.line(bg_surf, (r, g, b), (0, y), (SCREEN_WIDTH, y))
bg_surf = bg_surf.convert()

# ---------- 字体加载 ----------
def load_font(size):
    local_fonts = ['font.ttf', 'simhei.ttf', 'msyh.ttc', 'NotoSansCJKsc-Regular.otf']
    for local_font in local_fonts:
        if os.path.exists(local_font):
            try:
                return pygame.font.Font(local_font, size)
            except:
                pass
    windows_fonts = [
        "C:/Windows/Fonts/simhei.ttf",
        "C:/Windows/Fonts/msyh.ttc",
        "C:/Windows/Fonts/simkai.ttf",
        "C:/Windows/Fonts/stheiti.ttf"
    ]
    for font_path in windows_fonts:
        if os.path.exists(font_path):
            try:
                return pygame.font.Font(font_path, size)
            except:
                continue
    mac_fonts = [
        "/System/Library/Fonts/PingFang.ttc",
        "/System/Library/Fonts/STHeiti Light.ttc"
    ]
    for font_path in mac_fonts:
        if os.path.exists(font_path):
            try:
                return pygame.font.Font(font_path, size)
            except:
                continue
    linux_fonts = [
        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
        "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf"
    ]
    for font_path in linux_fonts:
        if os.path.exists(font_path):
            try:
                return pygame.font.Font(font_path, size)
            except:
                continue
    font_names = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial']
    for name in font_names:
        try:
            font = pygame.font.SysFont(name, size)
            test_surface = font.render("测试", True, (255, 255, 255))
            if test_surface.get_width() > 0:
                return font
        except:
            continue
    print("警告：未找到中文字体，部分文字可能显示为方块")
    return pygame.font.Font(None, size)

font = load_font(24)
small_font = load_font(18)
big_font = load_font(48)

test_text = font.render("测试", True, (255, 255, 255))
if test_text.get_width() == 0:
    print("字体加载失败，将使用英文显示")
    USE_ENGLISH = True
else:
    USE_ENGLISH = False

pygame.mouse.set_visible(False)
pygame.event.set_grab(True)

def draw_text(surf, text, x, y, color=(255, 255, 255), font_obj=None, center=False):
    if font_obj is None:
        font_obj = font
    if USE_ENGLISH:
        text = text.replace("生命", "HP").replace("得分", "Score").replace("波次", "Wave")
        text = text.replace("金钱", "$").replace("换弹中", "Reloading").replace("治疗中", "Healing")
        text = text.replace("减速", "SLOW").replace("左探头", "<< Lean").replace("右探头", "Lean >>")
        text = text.replace("医疗充能", "Medkit").replace("当前金钱", "Money")
    try:
        text_surface = font_obj.render(text, True, color)
        if center:
            rect = text_surface.get_rect(center=(x, y))
            surf.blit(text_surface, rect)
        else:
            surf.blit(text_surface, (x, y))
    except:
        safe_text = ''.join(c if ord(c) < 128 else '?' for c in text)
        try:
            text_surface = font_obj.render(safe_text, True, color)
            if center:
                rect = text_surface.get_rect(center=(x, y))
                surf.blit(text_surface, rect)
            else:
                surf.blit(text_surface, (x, y))
        except:
            pass

# 游戏状态
STATE_MENU = 0
STATE_GAME = 1
STATE_BOSS = 2
game_state = STATE_MENU

MODE_ENDLESS = 0
MODE_CLASSIC = 1
current_mode = MODE_ENDLESS

selected_boss_index = 0
boss_names = ["典狱长格赫罗斯", "雷丝", "赛伊德", "渡鸦", "德穆兰"]
if USE_ENGLISH:
    boss_names = ["Warden Gheros", "Reiss", "Saeed", "Raven", "Demullan"]

# 大地图 20x20
MAP = [
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,0,1,1,0,0,0,1,1,0,0,0,1,0,1],
    [1,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1],
    [1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1],
    [1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,1,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
]
MAP_SIZE = len(MAP)

# 玩家属性
player_x, player_y = 10.5, 10.5
player_angle = 0.0
player_pitch = 0.0
PLAYER_RADIUS = 0.3
NORMAL_SPEED = 0.08
SLIDE_SPEED = 0.14
CROUCH_SPEED = 0.04
MOVE_SPEED = NORMAL_SPEED
MOUSE_SENSITIVITY = 0.002
ADS_SENSITIVITY_MULT = 0.3
BASE_FOV = math.pi / 3
ADS_FOV = math.pi / 6
current_fov = BASE_FOV
NUM_RAYS = 320          # 优化：减少射线数，提升性能

player_hp = 100
max_hp = 100
player_height = 0.0
vertical_vel = 0.0
is_grounded = True
is_sliding = False
slide_timer = 0
SLIDE_DURATION = 20
JUMP_FORCE = -0.3
GRAVITY = 0.015

invincible = False
invincible_timer = 0
INVINCIBLE_DURATION = 30

lean_offset = 0.0
LEAN_AMOUNT = 0.5

# 开镜状态
ads_active = False

heal_charges = 100
max_heal_charges = 100
heal_active = False
heal_timer = 0

player_slowed = False
player_slow_timer = 0
player_distorted = False

# 武器系统
class Weapon:
    def __init__(self, name, damage, clip_size, fire_rate, recoil, reload_time, color, price=0):
        self.name = name
        self.damage = damage
        self.clip_size = clip_size
        self.fire_rate = fire_rate
        self.recoil = math.radians(recoil)
        self.reload_time = reload_time
        self.color = color
        self.price = price
        self.cooldown_frames = int(60 / fire_rate) if fire_rate > 0 else 999

weapons = [
    Weapon("手枪", 25, 12, 3.0, 0.8, 1.5, (80,80,80), 0),
    Weapon("冲锋枪", 20, 30, 8.0, 1.5, 2.2, (100,100,150), 300),
    Weapon("霰弹枪", 45, 8, 1.2, 3.5, 2.8, (150,100,50), 600),
    Weapon("狙击枪", 80, 5, 0.8, 5.0, 3.5, (50,80,50), 1000),
    Weapon("步枪", 30, 25, 5.0, 2.0, 2.5, (120,80,60), 800),
    Weapon("轻机枪", 22, 50, 10.0, 1.8, 3.2, (80,60,100), 1200),
    Weapon("左轮手枪", 60, 6, 1.5, 4.0, 2.0, (120,120,120), 500)
]
if USE_ENGLISH:
    for i, w in enumerate(weapons):
        names = ["Pistol", "SMG", "Shotgun", "Sniper", "Rifle", "LMG", "Revolver"]
        weapons[i].name = names[i]

current_weapon_index = 0
current_weapon = weapons[current_weapon_index]
clip_ammo = current_weapon.clip_size
reserve_ammo = 300
is_reloading = False
reload_timer = 0
RELOAD_TIME = int(current_weapon.reload_time * 60)

shot_cooldown = 0
MAX_SHOT_COOLDOWN = current_weapon.cooldown_frames

money = 500
KILL_REWARD = 100
shop_open = False
score = 0
wave = 1
spawn_timer = 0
SPAWN_COOLDOWN = 180

# 技能区域
class FireZone:
    def __init__(self, x, y, duration=300, damage=10, radius=2.0):
        self.x = x
        self.y = y
        self.duration = duration
        self.max_duration = duration
        self.damage = damage
        self.radius = radius
        self.alive = True
    def update(self):
        self.duration -= 1
        if self.duration <= 0:
            self.alive = False

class PoisonZone:
    def __init__(self, x, y, duration=360, radius=2.5):
        self.x = x
        self.y = y
        self.duration = duration
        self.max_duration = duration
        self.radius = radius
        self.alive = True
    def update(self):
        self.duration -= 1
        if self.duration <= 0:
            self.alive = False

fire_zones = []
poison_zones = []

# A*寻路
def astar(start, goal, map_data, map_size):
    def heuristic(a, b):
        return abs(a[0]-b[0]) + abs(a[1]-b[1])
    def get_neighbors(node):
        x, y = node
        neighbors = []
        for dx, dy in [(0,1),(1,0),(0,-1),(-1,0),(1,1),(1,-1),(-1,1),(-1,-1)]:
            nx, ny = x+dx, y+dy
            if 0 <= nx < map_size and 0 <= ny < map_size:
                if map_data[ny][nx] == 0:
                    cost = 1.414 if dx!=0 and dy!=0 else 1.0
                    neighbors.append(((nx, ny), cost))
        return neighbors
    start = (int(start[0]), int(start[1]))
    goal = (int(goal[0]), int(goal[1]))
    frontier = []
    heapq.heappush(frontier, (0, start))
    came_from = {start: None}
    cost_so_far = {start: 0}
    while frontier:
        _, current = heapq.heappop(frontier)
        if current == goal:
            break
        for next_node, cost in get_neighbors(current):
            new_cost = cost_so_far[current] + cost
            if next_node not in cost_so_far or new_cost < cost_so_far[next_node]:
                cost_so_far[next_node] = new_cost
                priority = new_cost + heuristic(next_node, goal)
                heapq.heappush(frontier, (priority, next_node))
                came_from[next_node] = current
    if goal not in came_from:
        return []
    path = []
    current = goal
    while current != start:
        path.append(current)
        current = came_from[current]
    path.reverse()
    return path

class Bullet:
    def __init__(self, x, y, angle, pitch, speed=0.25, damage=25):
        self.x = x
        self.y = y
        self.angle = angle
        self.pitch = pitch
        self.speed = speed
        self.damage = damage
        self.alive = True
        self.life = 120
    def update(self):
        horiz_speed = self.speed * math.cos(self.pitch)
        self.x += math.cos(self.angle) * horiz_speed
        self.y += math.sin(self.angle) * horiz_speed
        self.life -= 1
        if self.life <= 0:
            self.alive = False
            return
        map_x, map_y = int(self.x), int(self.y)
        if 0 <= map_x < MAP_SIZE and 0 <= map_y < MAP_SIZE:
            if MAP[map_y][map_x] == 1:
                self.alive = False

bullets = []

class EnemyBullet:
    def __init__(self, x, y, angle, speed=0.15, damage=10, is_fire=False):
        self.x = x
        self.y = y
        self.angle = angle
        self.speed = speed
        self.damage = damage
        self.alive = True
        self.life = 80
        self.is_fire = is_fire
    def update(self):
        self.x += math.cos(self.angle) * self.speed
        self.y += math.sin(self.angle) * self.speed
        self.life -= 1
        if self.life <= 0:
            self.alive = False
            return
        map_x, map_y = int(self.x), int(self.y)
        if 0 <= map_x < MAP_SIZE and 0 <= map_y < MAP_SIZE:
            if MAP[map_y][map_x] == 1:
                self.alive = False

enemy_bullets = []

class Guard:
    def __init__(self, x, y, guard_type="assault"):
        self.x = x
        self.y = y
        self.alive = True
        self.radius = 0.4
        self.type = guard_type
        self.speed = 0.018
        self.attack_cooldown = 0
        self.shoot_cooldown = 0
        self.shoot_interval = 40
        self.shoot_range = 7.0
        self.bullet_speed = 0.16
        self.path = []
        self.path_timer = 0
        if guard_type == "shield":
            self.hp = 150
            self.max_hp = 150
            self.attack_damage = 15
            self.color = (100,100,150)
            self.has_shield = True
        else:
            self.hp = 120
            self.max_hp = 120
            self.attack_damage = 20
            self.color = (150,80,80)
            self.has_shield = False

    def update(self, px, py):
        if not self.alive:
            return
        dx = px - self.x
        dy = py - self.y
        dist = math.hypot(dx, dy)
        self.path_timer -= 1
        if self.path_timer <= 0:
            self.path = astar((self.x, self.y), (px, py), MAP, MAP_SIZE)
            self.path_timer = 30
        if len(self.path) > 0 and dist > 2.0:
            next_node = self.path[0]
            target_x, target_y = next_node[0] + 0.5, next_node[1] + 0.5
            dx = target_x - self.x
            dy = target_y - self.y
            d = math.hypot(dx, dy)
            if d > 0.1:
                self.x += (dx/d)*self.speed
                self.y += (dy/d)*self.speed
            if d < 0.3:
                self.path.pop(0)
        elif dist > 1.5:
            self.x += (dx/dist)*self.speed
            self.y += (dy/dist)*self.speed
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
        if self.shoot_cooldown > 0:
            self.shoot_cooldown -= 1
        if dist < self.shoot_range and self.shoot_cooldown <= 0:
            angle = math.atan2(py - self.y, px - self.x)
            enemy_bullets.append(EnemyBullet(self.x, self.y, angle, speed=self.bullet_speed, damage=self.attack_damage))
            self.shoot_cooldown = self.shoot_interval
        if dist < 1.2 and self.attack_cooldown == 0:
            global player_hp, invincible, invincible_timer
            if not invincible:
                player_hp -= self.attack_damage
                invincible = True
                invincible_timer = INVINCIBLE_DURATION
            self.attack_cooldown = 50

guards = []

class Tank:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.alive = True
        self.radius = 0.8
        self.hp = 200
        self.max_hp = 200
        self.speed = 0.012
        self.shoot_cooldown = 0
        self.shoot_interval = 15
        self.shoot_range = 9.0
        self.bullet_speed = 0.2
        self.attack_damage = 15
        self.color = (80,80,100)
        self.path = []
        self.path_timer = 0
    def update(self, px, py):
        if not self.alive:
            return
        dx = px - self.x
        dy = py - self.y
        dist = math.hypot(dx, dy)
        self.path_timer -= 1
        if self.path_timer <= 0:
            self.path = astar((self.x, self.y), (px, py), MAP, MAP_SIZE)
            self.path_timer = 40
        if len(self.path) > 0 and dist > 3.0:
            next_node = self.path[0]
            target_x, target_y = next_node[0] + 0.5, next_node[1] + 0.5
            dx = target_x - self.x
            dy = target_y - self.y
            d = math.hypot(dx, dy)
            if d > 0.1:
                self.x += (dx/d)*self.speed
                self.y += (dy/d)*self.speed
            if d < 0.5:
                self.path.pop(0)
        if self.shoot_cooldown > 0:
            self.shoot_cooldown -= 1
        if dist < self.shoot_range and self.shoot_cooldown <= 0:
            angle = math.atan2(py - self.y, px - self.x)
            enemy_bullets.append(EnemyBullet(self.x, self.y, angle, speed=self.bullet_speed, damage=self.attack_damage))
            self.shoot_cooldown = self.shoot_interval

tanks = []

class Boss:
    def __init__(self, name, x, y):
        self.name = name
        self.x = x
        self.y = y
        self.alive = True
        self.radius = 0.8
        self.hp = 500
        self.max_hp = 500
        self.speed = 0.018
        self.attack_cooldown = 0
        self.attack_damage = 25
        self.shoot_cooldown = 0
        self.shoot_interval = 20
        self.shoot_range = 12.0
        self.bullet_speed = 0.2
        self.phase = 1
        self.summon_timer = 0
        self.color = (200,50,50)
        self.path = []
        self.path_timer = 0
        if name in ["典狱长格赫罗斯", "Warden Gheros"]:
            self.attack_damage = 30
            self.shoot_interval = 25
        elif name in ["雷丝", "Reiss"]:
            self.attack_damage = 20
            self.shoot_interval = 30
            self.spread = 0.2
        elif name in ["赛伊德", "Saeed"]:
            self.attack_damage = 25
            self.shoot_interval = 15
            self.fire_cooldown = 0
        elif name in ["渡鸦", "Raven"]:
            self.attack_damage = 25
            self.shoot_interval = 20
            self.poison_cooldown = 0
        elif name in ["德穆兰", "Demullan"]:
            self.attack_damage = 45
            self.shoot_interval = 40
            self.bullet_speed = 0.35

    def update(self, px, py):
        global player_hp, invincible, invincible_timer
        if not self.alive:
            return
        dx = px - self.x
        dy = py - self.y
        dist = math.hypot(dx, dy)
        self.path_timer -= 1
        if self.path_timer <= 0:
            self.path = astar((self.x, self.y), (px, py), MAP, MAP_SIZE)
            self.path_timer = 20
        if len(self.path) > 0 and dist > 2.5:
            next_node = self.path[0]
            target_x, target_y = next_node[0] + 0.5, next_node[1] + 0.5
            dx = target_x - self.x
            dy = target_y - self.y
            d = math.hypot(dx, dy)
            if d > 0.1:
                self.x += (dx/d)*self.speed
                self.y += (dy/d)*self.speed
            if d < 0.4:
                self.path.pop(0)
        elif dist > 2.0:
            self.x += (dx/dist)*self.speed
            self.y += (dy/dist)*self.speed
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
        if self.shoot_cooldown > 0:
            self.shoot_cooldown -= 1
        if self.summon_timer > 0:
            self.summon_timer -= 1
        if hasattr(self, 'fire_cooldown') and self.fire_cooldown > 0:
            self.fire_cooldown -= 1
        if hasattr(self, 'poison_cooldown') and self.poison_cooldown > 0:
            self.poison_cooldown -= 1
        if self.hp <= self.max_hp * 0.5 and self.phase == 1:
            self.phase = 2
            if self.name in ["典狱长格赫罗斯", "Warden Gheros"]:
                self.shoot_interval = 15
            elif self.name in ["雷丝", "Reiss"]:
                self.shoot_interval = 20
                self.attack_damage = 30
            elif self.name in ["赛伊德", "Saeed"]:
                self.shoot_interval = 7
            elif self.name in ["渡鸦", "Raven"]:
                self.shoot_interval = 12
            elif self.name in ["德穆兰", "Demullan"]:
                self.shoot_interval = 25
        if dist < self.shoot_range and self.shoot_cooldown <= 0:
            angle = math.atan2(py - self.y, px - self.x)
            if self.name in ["典狱长格赫罗斯", "Warden Gheros"]:
                for i in range(4):
                    spread = random.uniform(-0.05, 0.05)
                    enemy_bullets.append(EnemyBullet(self.x, self.y, angle+spread, speed=self.bullet_speed, damage=30))
                self.shoot_cooldown = self.shoot_interval
            elif self.name in ["雷丝", "Reiss"]:
                for i in range(3):
                    spread = random.uniform(-self.spread, self.spread)
                    enemy_bullets.append(EnemyBullet(self.x, self.y, angle+spread, speed=self.bullet_speed, damage=20))
                self.shoot_cooldown = self.shoot_interval
            elif self.name in ["赛伊德", "Saeed"]:
                enemy_bullets.append(EnemyBullet(self.x, self.y, angle, speed=self.bullet_speed, damage=self.attack_damage))
                if hasattr(self, 'fire_cooldown') and self.fire_cooldown <= 0:
                    fire_zones.append(FireZone(px, py))
                    self.fire_cooldown = 180
                if self.phase == 2 and random.random() < 0.1:
                    self.x += random.uniform(-1.5, 1.5)
                    self.y += random.uniform(-1.5, 1.5)
                self.shoot_cooldown = self.shoot_interval
            elif self.name in ["渡鸦", "Raven"]:
                enemy_bullets.append(EnemyBullet(self.x, self.y, angle+0.1, speed=self.bullet_speed, damage=self.attack_damage))
                enemy_bullets.append(EnemyBullet(self.x, self.y, angle-0.1, speed=self.bullet_speed, damage=self.attack_damage))
                if hasattr(self, 'poison_cooldown') and self.poison_cooldown <= 0:
                    poison_zones.append(PoisonZone(px, py))
                    self.poison_cooldown = 240
                self.shoot_cooldown = self.shoot_interval
            elif self.name in ["德穆兰", "Demullan"]:
                enemy_bullets.append(EnemyBullet(self.x, self.y, angle, speed=self.bullet_speed, damage=self.attack_damage))
                self.shoot_cooldown = self.shoot_interval
        if dist < 1.8 and self.attack_cooldown == 0:
            if self.name in ["渡鸦", "Raven"] and dist < 1.5:
                player_hp -= 100
                invincible = True
                invincible_timer = INVINCIBLE_DURATION
                self.attack_cooldown = 120
            else:
                player_hp -= self.attack_damage
                invincible = True
                invincible_timer = INVINCIBLE_DURATION
                self.attack_cooldown = 50

boss = None

class Enemy:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.alive = True
        self.radius = 0.4
        self.hp = 30
        self.max_hp = 30
        self.speed = 0.02
        self.attack_cooldown = 0
        self.attack_damage = 10
        self.shoot_cooldown = 0
        self.shoot_interval = 90
        self.shoot_range = 8.0
        self.bullet_speed = 0.15
        self.path = []
        self.path_timer = 0
    def update(self, px, py):
        if not self.alive:
            return
        dx = px - self.x
        dy = py - self.y
        dist = math.hypot(dx, dy)
        self.path_timer -= 1
        if self.path_timer <= 0:
            self.path = astar((self.x, self.y), (px, py), MAP, MAP_SIZE)
            self.path_timer = 45
        if len(self.path) > 0 and dist > 1.5:
            next_node = self.path[0]
            target_x, target_y = next_node[0] + 0.5, next_node[1] + 0.5
            dx = target_x - self.x
            dy = target_y - self.y
            d = math.hypot(dx, dy)
            if d > 0.1:
                self.x += (dx/d)*self.speed
                self.y += (dy/d)*self.speed
            if d < 0.4:
                self.path.pop(0)
        elif dist > 1.2:
            self.x += (dx/dist)*self.speed
            self.y += (dy/dist)*self.speed
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
        if self.shoot_cooldown > 0:
            self.shoot_cooldown -= 1
        if dist < self.shoot_range and self.shoot_cooldown <= 0:
            angle_to_player = math.atan2(py - self.y, px - self.x)
            enemy_bullets.append(EnemyBullet(self.x, self.y, angle_to_player, speed=self.bullet_speed, damage=self.attack_damage))
            self.shoot_cooldown = self.shoot_interval

enemies = []

def spawn_enemy():
    while True:
        ex = random.uniform(1.5, MAP_SIZE-1.5)
        ey = random.uniform(1.5, MAP_SIZE-1.5)
        if MAP[int(ey)][int(ex)] == 0:
            if math.hypot(ex - player_x, ey - player_y) > 5.0:
                enemies.append(Enemy(ex, ey))
                break

def spawn_boss_guards(boss_name):
    guards.clear()
    tanks.clear()
    base_x, base_y = boss.x, boss.y
    if boss_name in ["典狱长格赫罗斯", "Warden Gheros"]:
        for i in range(2): guards.append(Guard(base_x+random.uniform(-2,2), base_y+random.uniform(-2,2), "shield"))
        for i in range(3): guards.append(Guard(base_x+random.uniform(-2,2), base_y+random.uniform(-2,2), "assault"))
    elif boss_name in ["雷丝", "Reiss"]:
        for i in range(2): guards.append(Guard(base_x+random.uniform(-2,2), base_y+random.uniform(-2,2), "shield"))
        for i in range(2): guards.append(Guard(base_x+random.uniform(-2,2), base_y+random.uniform(-2,2), "assault"))
    elif boss_name in ["渡鸦", "Raven"]:
        for i in range(4):
            g = Guard(base_x+random.uniform(-2,2), base_y+random.uniform(-2,2), "assault")
            g.hp = 200; g.max_hp = 200; g.attack_damage = 30
            guards.append(g)
    elif boss_name in ["德穆兰", "Demullan"]:
        for i in range(2): tanks.append(Tank(base_x+random.uniform(-3,3), base_y+random.uniform(-3,3)))

def can_move_to(new_x, new_y):
    for dy in [-PLAYER_RADIUS, 0, PLAYER_RADIUS]:
        for dx in [-PLAYER_RADIUS, 0, PLAYER_RADIUS]:
            cx = new_x + dx
            cy = new_y + dy
            map_x = int(cx)
            map_y = int(cy)
            if 0 <= map_x < MAP_SIZE and 0 <= map_y < MAP_SIZE:
                if MAP[map_y][map_x] == 1:
                    cell_left = map_x
                    cell_right = map_x + 1
                    cell_top = map_y
                    cell_bottom = map_y + 1
                    closest_x = max(cell_left, min(cx, cell_right))
                    closest_y = max(cell_top, min(cy, cell_bottom))
                    if (cx-closest_x)**2 + (cy-closest_y)**2 < PLAYER_RADIUS**2:
                        return False
    return True

def cast_ray(ax, ay, angle, pitch):
    dx = math.cos(angle) * math.cos(pitch)
    dy = math.sin(angle) * math.cos(pitch)
    map_x, map_y = int(ax), int(ay)
    delta_dist_x = abs(1/dx) if dx != 0 else 1e30
    delta_dist_y = abs(1/dy) if dy != 0 else 1e30
    step_x = 1 if dx > 0 else -1
    step_y = 1 if dy > 0 else -1
    if dx > 0:
        side_dist_x = (map_x + 1 - ax) * delta_dist_x
    else:
        side_dist_x = (ax - map_x) * delta_dist_x
    if dy > 0:
        side_dist_y = (map_y + 1 - ay) * delta_dist_y
    else:
        side_dist_y = (ay - map_y) * delta_dist_y
    hit = False
    side = 0
    while not hit:
        if side_dist_x < side_dist_y:
            side_dist_x += delta_dist_x
            map_x += step_x
            side = 0
        else:
            side_dist_y += delta_dist_y
            map_y += step_y
            side = 1
        if map_x < 0 or map_x >= MAP_SIZE or map_y < 0 or map_y >= MAP_SIZE:
            return 40.0, side, (ax+dx*40, ay+dy*40)
        if MAP[map_y][map_x] == 1:
            hit = True
    if side == 0:
        perp_dist = (map_x - ax + (1 - step_x)/2) / dx
    else:
        perp_dist = (map_y - ay + (1 - step_y)/2) / dy
    hit_x = ax + dx * perp_dist
    hit_y = ay + dy * perp_dist
    return perp_dist, side, (hit_x, hit_y)

def draw_weapon_model(surf, weapon, is_reloading=False):
    w, h = surf.get_size()
    body_rect = pygame.Rect(w//2 - 40, h - 100, 80, 40)
    pygame.draw.rect(surf, weapon.color, body_rect)
    pygame.draw.rect(surf, (40,40,40), body_rect, 2)
    barrel_rect = pygame.Rect(w//2 + 30, h - 95, 60, 15)
    pygame.draw.rect(surf, (40,40,40), barrel_rect)
    grip_rect = pygame.Rect(w//2 - 50, h - 90, 15, 40)
    pygame.draw.rect(surf, (60,50,40), grip_rect)
    mag_rect = pygame.Rect(w//2 - 30, h - 80, 20, 35)
    pygame.draw.rect(surf, (30,30,30), mag_rect)
    pygame.draw.circle(surf, (200,200,200), (w//2 + 70, h - 88), 5)
    draw_text(surf, weapon.name, w//2 - 30, h - 120, (255,255,255), small_font)
    if is_reloading:
        reload_text = "Reloading..." if USE_ENGLISH else "换弹中..."
        draw_text(surf, reload_text, w//2 - 30, h - 140, (255,200,0), small_font)

def draw_shop(surf, money, weapons, current_idx):
    overlay = pygame.Surface(surf.get_size(), pygame.SRCALPHA)
    overlay.fill((0,0,0,180))
    surf.blit(overlay, (0,0))
    title = "Weapon Shop (Press 1-7 to buy, B to close)" if USE_ENGLISH else "武器商店 (按数字键1-7购买, B关闭)"
    draw_text(surf, title, SCREEN_WIDTH//2, 80, (255,255,0), font, center=True)
    y_offset = 150
    for i, wp in enumerate(weapons):
        color = (0,255,0) if i == current_idx else (200,200,200)
        default_text = " (Default)" if USE_ENGLISH else " (默认)" if i == 0 else ""
        text = f"{i+1}. {wp.name} - DMG:{wp.damage} AMMO:{wp.clip_size} ROF:{wp.fire_rate:.1f}/s ${wp.price}{default_text}"
        draw_text(surf, text, SCREEN_WIDTH//2 - 350, y_offset, color, small_font)
        y_offset += 35
    heal_text = "8. Medkit +50 $100" if USE_ENGLISH else "8. 医疗充能 +50 价格:$100"
    draw_text(surf, heal_text, SCREEN_WIDTH//2 - 350, y_offset, (200,200,200), small_font)
    y_offset += 35
    money_text = f"Money: ${money}  Medkit: {heal_charges}" if USE_ENGLISH else f"当前金钱: ${money}  医疗充能: {heal_charges}"
    draw_text(surf, money_text, SCREEN_WIDTH//2 - 100, y_offset + 20, (255,255,0), font)

def reset_game():
    global player_x, player_y, player_angle, player_pitch, player_hp, max_hp, player_height, vertical_vel, is_grounded, is_sliding, slide_timer
    global invincible, invincible_timer, lean_offset, current_weapon_index, current_weapon, clip_ammo, reserve_ammo
    global is_reloading, reload_timer, RELOAD_TIME, shot_cooldown, MAX_SHOT_COOLDOWN, money, shop_open, score, wave, spawn_timer
    global bullets, enemy_bullets, enemies, boss, guards, tanks, fire_zones, poison_zones
    global player_slowed, player_slow_timer, player_distorted, heal_charges, heal_active, heal_timer, ads_active
    player_x, player_y = 10.5, 10.5
    player_angle = 0.0
    player_pitch = 0.0
    player_hp = max_hp
    player_height = 0.0
    vertical_vel = 0.0
    is_grounded = True
    is_sliding = False
    slide_timer = 0
    invincible = False
    invincible_timer = 0
    lean_offset = 0.0
    player_slowed = False
    player_slow_timer = 0
    player_distorted = False
    heal_charges = 100
    heal_active = False
    heal_timer = 0
    ads_active = False
    current_weapon_index = 0
    current_weapon = weapons[current_weapon_index]
    clip_ammo = current_weapon.clip_size
    reserve_ammo = 300
    is_reloading = False
    reload_timer = 0
    RELOAD_TIME = int(current_weapon.reload_time * 60)
    shot_cooldown = 0
    MAX_SHOT_COOLDOWN = current_weapon.cooldown_frames
    money = 500
    shop_open = False
    score = 0
    wave = 1
    spawn_timer = 0
    bullets.clear()
    enemy_bullets.clear()
    enemies.clear()
    guards.clear()
    tanks.clear()
    fire_zones.clear()
    poison_zones.clear()
    boss = None

# ---------- 优化：重用临时Surface（火焰/毒气） ----------
fire_overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
poison_overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)

# 主循环
running = True
while running:
    dt = clock.tick(60) / 1000.0
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            if game_state == STATE_MENU:
                running = False
            else:
                game_state = STATE_MENU
                pygame.mouse.set_visible(True)
                pygame.event.set_grab(False)
        if event.type == KEYDOWN:
            if game_state == STATE_MENU:
                if event.key == K_1:
                    current_mode = MODE_ENDLESS
                    reset_game()
                    for _ in range(4): spawn_enemy()
                    game_state = STATE_GAME
                    pygame.mouse.set_visible(False)
                    pygame.event.set_grab(True)
                elif event.key == K_2:
                    current_mode = MODE_CLASSIC
                    reset_game()
                    for _ in range(4): spawn_enemy()
                    game_state = STATE_GAME
                    pygame.mouse.set_visible(False)
                    pygame.event.set_grab(True)
                elif event.key == K_3:
                    game_state = STATE_BOSS
                    selected_boss_index = 0
                elif event.key == K_q:
                    running = False
            elif game_state == STATE_BOSS:
                if event.key == K_UP: selected_boss_index = (selected_boss_index - 1) % len(boss_names)
                elif event.key == K_DOWN: selected_boss_index = (selected_boss_index + 1) % len(boss_names)
                elif event.key == K_RETURN:
                    reset_game()
                    boss = Boss(boss_names[selected_boss_index], 15.0, 10.0)
                    spawn_boss_guards(boss_names[selected_boss_index])
                    game_state = STATE_GAME
                    pygame.mouse.set_visible(False)
                    pygame.event.set_grab(True)
                elif event.key == K_ESCAPE:
                    game_state = STATE_MENU
            elif game_state == STATE_GAME:
                if shop_open:
                    if event.key == K_b: shop_open = False
                    elif event.key in [K_1, K_2, K_3, K_4, K_5, K_6, K_7]:
                        idx = event.key - K_1
                        if idx < len(weapons):
                            wp = weapons[idx]
                            if money >= wp.price:
                                money -= wp.price
                                current_weapon_index = idx
                                current_weapon = wp
                                clip_ammo = current_weapon.clip_size
                                RELOAD_TIME = int(current_weapon.reload_time * 60)
                                MAX_SHOT_COOLDOWN = current_weapon.cooldown_frames
                    elif event.key == K_8:
                        if money >= 100 and heal_charges < max_heal_charges:
                            money -= 100
                            heal_charges = min(max_heal_charges, heal_charges + 50)
                else:
                    if event.key == K_SPACE and is_grounded:
                        vertical_vel = JUMP_FORCE
                        is_grounded = False
                    if event.key == K_LCTRL and is_grounded and not is_sliding:
                        is_sliding = True
                        slide_timer = SLIDE_DURATION
                        player_height = -0.5
                    if event.key == K_r and not is_reloading and clip_ammo < current_weapon.clip_size and reserve_ammo > 0:
                        is_reloading = True
                        reload_timer = RELOAD_TIME
                    if event.key == K_b:
                        shop_open = True
                    if event.key == K_v:
                        heal_active = True
                        heal_timer = 0
        if event.type == KEYUP:
            if event.key == K_v:
                heal_active = False
                heal_timer = 0

    # 菜单界面
    if game_state == STATE_MENU:
        screen.blit(bg_surf, (0,0))
        title = "Delta Force" if USE_ENGLISH else "三角洲行动"
        draw_text(screen, title, SCREEN_WIDTH//2, 100, (255,200,0), big_font, center=True)
        opt1 = "1. Endless Mode" if USE_ENGLISH else "1. 无尽模式 (无限波次)"
        opt2 = "2. Classic Mode" if USE_ENGLISH else "2. 经典模式 (5波通关)"
        opt3 = "3. Boss Challenge" if USE_ENGLISH else "3. Boss挑战"
        opt4 = "Q. Quit" if USE_ENGLISH else "Q. 退出"
        draw_text(screen, opt1, SCREEN_WIDTH//2, 250, (255,255,255), font, center=True)
        draw_text(screen, opt2, SCREEN_WIDTH//2, 300, (255,255,255), font, center=True)
        draw_text(screen, opt3, SCREEN_WIDTH//2, 350, (255,255,255), font, center=True)
        draw_text(screen, opt4, SCREEN_WIDTH//2, 400, (200,200,200), font, center=True)
        pygame.display.flip()
        continue

    if game_state == STATE_BOSS:
        screen.blit(bg_surf, (0,0))
        title = "Select Boss" if USE_ENGLISH else "选择 Boss"
        draw_text(screen, title, SCREEN_WIDTH//2, 80, (255,100,100), big_font, center=True)
        for i, name in enumerate(boss_names):
            color = (255,255,0) if i == selected_boss_index else (200,200,200)
            draw_text(screen, name, SCREEN_WIDTH//2, 200 + i*50, color, font, center=True)
        hint = "↑↓ Select  Enter Confirm  ESC Back" if USE_ENGLISH else "↑↓选择  Enter确认  ESC返回"
        draw_text(screen, hint, SCREEN_WIDTH//2, 500, (180,180,180), small_font, center=True)
        pygame.display.flip()
        continue

    # 游戏进行中
    keys = pygame.key.get_pressed()
    mouse_buttons = pygame.mouse.get_pressed()

    lean_left = keys[K_q] and not shop_open
    lean_right = keys[K_e] and not shop_open
    if lean_left and not lean_right:
        lean_offset = -LEAN_AMOUNT
    elif lean_right and not lean_left:
        lean_offset = LEAN_AMOUNT
    else:
        lean_offset = 0.0

    # 开镜状态
    ads_active = mouse_buttons[2] and not shop_open and game_state == STATE_GAME

    if shot_cooldown > 0:
        shot_cooldown -= 1

    # 鼠标灵敏度调整
    sens = MOUSE_SENSITIVITY * (ADS_SENSITIVITY_MULT if ads_active else 1.0)
    mouse_dx, mouse_dy = pygame.mouse.get_rel()
    player_angle += mouse_dx * sens
    player_pitch -= mouse_dy * sens
    player_pitch = max(-1.2, min(1.2, player_pitch))

    # 负面状态更新
    if player_slowed:
        player_slow_timer -= 1
        if player_slow_timer <= 0:
            player_slowed = False

    if not shop_open:
        base_speed = NORMAL_SPEED
        if player_slowed:
            base_speed *= 0.5
        if is_sliding:
            MOVE_SPEED = SLIDE_SPEED
        elif keys[K_LCTRL]:
            MOVE_SPEED = CROUCH_SPEED
            player_height = 0.5
        else:
            MOVE_SPEED = base_speed
            if not is_sliding and is_grounded:
                player_height = 0.0

        move_x = move_y = 0
        if keys[K_w]:
            move_x += math.cos(player_angle) * MOVE_SPEED
            move_y += math.sin(player_angle) * MOVE_SPEED
        if keys[K_s]:
            move_x -= math.cos(player_angle) * MOVE_SPEED
            move_y -= math.sin(player_angle) * MOVE_SPEED
        if keys[K_a]:
            move_x += math.sin(player_angle) * MOVE_SPEED
            move_y -= math.cos(player_angle) * MOVE_SPEED
        if keys[K_d]:
            move_x -= math.sin(player_angle) * MOVE_SPEED
            move_y += math.cos(player_angle) * MOVE_SPEED

        if move_x != 0 or move_y != 0:
            if can_move_to(player_x + move_x, player_y):
                player_x += move_x
            if can_move_to(player_x, player_y + move_y):
                player_y += move_y

        if not is_grounded:
            player_height += vertical_vel
            vertical_vel += GRAVITY
            if player_height <= 0.0:
                player_height = 0.0
                is_grounded = True
                vertical_vel = 0.0

        if is_sliding:
            slide_timer -= 1
            if slide_timer <= 0:
                is_sliding = False
                player_height = 0.0

        if invincible:
            invincible_timer -= 1
            if invincible_timer <= 0:
                invincible = False

        if is_reloading:
            reload_timer -= 1
            if reload_timer <= 0:
                needed = current_weapon.clip_size - clip_ammo
                take = min(needed, reserve_ammo)
                clip_ammo += take
                reserve_ammo -= take
                is_reloading = False

        if heal_active:
            heal_timer += 1
            if heal_timer >= 180:
                if player_hp < max_hp and heal_charges >= 20:
                    player_hp = min(max_hp, player_hp + 20)
                    heal_charges -= 20
                    heal_timer = 120
                else:
                    heal_active = False
        else:
            heal_timer = 0

        # 射击
        if (not shop_open and not is_reloading and clip_ammo > 0 and shot_cooldown <= 0 and mouse_buttons[0]):
            bullets.append(Bullet(player_x, player_y, player_angle, player_pitch, damage=current_weapon.damage))
            clip_ammo -= 1
            shot_cooldown = current_weapon.cooldown_frames
            recoil_amount = random.uniform(0.5, 1.0) * current_weapon.recoil
            player_pitch += recoil_amount
            player_pitch = min(1.2, player_pitch)

        # 技能区域
        for fz in fire_zones[:]:
            fz.update()
            if not fz.alive:
                fire_zones.remove(fz)
            elif (fz.x - player_x)**2 + (fz.y - player_y)**2 < fz.radius**2:
                if not invincible:
                    player_hp -= fz.damage
                    invincible = True
                    invincible_timer = INVINCIBLE_DURATION
        for pz in poison_zones[:]:
            pz.update()
            if not pz.alive:
                poison_zones.remove(pz)
            elif (pz.x - player_x)**2 + (pz.y - player_y)**2 < pz.radius**2:
                player_slowed = True
                player_slow_timer = 30
                player_distorted = True
            else:
                player_distorted = False

        # 更新子弹
        for b in bullets[:]:
            b.update()
            if not b.alive:
                bullets.remove(b)
                continue
            for e in enemies:
                if e.alive and (b.x - e.x)**2 + (b.y - e.y)**2 < e.radius**2:
                    e.hp -= b.damage
                    b.alive = False
                    if e.hp <= 0:
                        e.alive = False
                        score += 100
                        money += KILL_REWARD
                    break
            for g in guards:
                if g.alive and (b.x - g.x)**2 + (b.y - g.y)**2 < g.radius**2:
                    g.hp -= b.damage
                    b.alive = False
                    if g.hp <= 0:
                        g.alive = False
                        score += 80
                        money += 50
                    break
            for t in tanks:
                if t.alive and (b.x - t.x)**2 + (b.y - t.y)**2 < t.radius**2:
                    t.hp -= b.damage
                    b.alive = False
                    if t.hp <= 0:
                        t.alive = False
                        score += 150
                        money += 100
                    break
            if boss and boss.alive and (b.x - boss.x)**2 + (b.y - boss.y)**2 < boss.radius**2:
                boss.hp -= b.damage
                b.alive = False
                if boss.hp <= 0:
                    boss.alive = False
                    score += 1000
                    money += 500

        # 敌方子弹碰撞
        for eb in enemy_bullets[:]:
            eb.update()
            if not eb.alive:
                enemy_bullets.remove(eb)
                continue
            if (eb.x - player_x)**2 + (eb.y - player_y)**2 < PLAYER_RADIUS**2:
                if not invincible:
                    player_hp -= eb.damage
                    invincible = True
                    invincible_timer = INVINCIBLE_DURATION
                eb.alive = False

        # 更新单位
        if boss and boss.alive:
            boss.update(player_x, player_y)
        for g in guards[:]:
            if g.alive: g.update(player_x, player_y)
            else: guards.remove(g)
        for t in tanks[:]:
            if t.alive: t.update(player_x, player_y)
            else: tanks.remove(t)
        for e in enemies[:]:
            if e.alive: e.update(player_x, player_y)
            else: enemies.remove(e)

        # 波次控制
        if boss is None:
            if current_mode == MODE_ENDLESS:
                if len(enemies) == 0:
                    wave += 1
                    for _ in range(3 + wave): spawn_enemy()
                elif spawn_timer <= 0 and len(enemies) < 15:
                    spawn_enemy()
                    spawn_timer = SPAWN_COOLDOWN
                else:
                    spawn_timer -= 1
            else:
                if len(enemies) == 0:
                    if wave >= 5:
                        game_state = STATE_MENU
                        pygame.mouse.set_visible(True)
                        pygame.event.set_grab(False)
                    else:
                        wave += 1
                        for _ in range(3 + wave): spawn_enemy()
        if player_hp <= 0:
            game_state = STATE_MENU
            pygame.mouse.set_visible(True)
            pygame.event.set_grab(False)

    # ---------- 渲染 ----------
    screen.blit(bg_surf, (0,0))
    # 当前FOV
    current_fov = ADS_FOV if ads_active else BASE_FOV
    if lean_offset != 0:
        perp_angle = player_angle + (-math.pi/2 if lean_offset < 0 else math.pi/2)
        ray_start_x = player_x + abs(lean_offset) * math.cos(perp_angle)
        ray_start_y = player_y + abs(lean_offset) * math.sin(perp_angle)
    else:
        ray_start_x = player_x
        ray_start_y = player_y

    # 预计算pitch相关偏移（优化）
    tan_pitch = math.tan(player_pitch)
    global_pitch_off = int(tan_pitch * SCREEN_HEIGHT * 0.5)
    global_vert_off = int(player_height * 30) + global_pitch_off

    # 雾效颜色
    fog_r, fog_g, fog_b = 80, 90, 100
    max_dist = 40.0
    col_width = SCREEN_WIDTH / NUM_RAYS
    ray_angle = player_angle - current_fov/2

    # 绘制墙壁（带雾效，使用预计算的pitch偏移）
    for i in range(NUM_RAYS):
        dist, side, _ = cast_ray(ray_start_x, ray_start_y, ray_angle, player_pitch)
        if dist < 0.1: dist = 0.1
        dist *= math.cos(ray_angle - player_angle)
        wall_height = int(SCREEN_HEIGHT / dist)
        # 使用全局pitch偏移，避免重复计算
        height_offset = int(player_height * 50) + global_pitch_off
        wall_top = (SCREEN_HEIGHT - wall_height)//2 + height_offset
        brightness = 1.0 - min(dist / 30.0, 1.0)
        if side == 0:
            r, g, b = 180*brightness, 100*brightness, 80*brightness
        else:
            r, g, b = 200*brightness, 140*brightness, 100*brightness
        # 雾效混合
        fog = min(dist / max_dist, 1.0)
        r = int(r*(1-fog) + fog_r*fog)
        g = int(g*(1-fog) + fog_g*fog)
        b = int(b*(1-fog) + fog_b*fog)
        pygame.draw.rect(screen, (r, g, b), (i*col_width, wall_top, col_width+1, wall_height))
        ray_angle += current_fov / NUM_RAYS

    # 绘制火焰区域（重用Surface）
    if fire_zones:
        fire_overlay.fill((0,0,0,0))
        for fz in fire_zones:
            dx = fz.x - player_x
            dy = fz.y - player_y
            dist = math.hypot(dx, dy)
            if dist < 20:
                angle_to = math.atan2(dy, dx)
                angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                if 0 < screen_x < SCREEN_WIDTH:
                    flicker = 0.8 + 0.2*math.sin(pygame.time.get_ticks()*0.01)
                    base_alpha = int(120*(fz.duration/fz.max_duration)*flicker)
                    size = int(40*(1+0.1*math.sin(pygame.time.get_ticks()*0.005)))
                    pygame.draw.circle(fire_overlay, (180,30,0, base_alpha//2), (int(screen_x), SCREEN_HEIGHT//2), size+10)
                    pygame.draw.circle(fire_overlay, (255,80,0, base_alpha), (int(screen_x), SCREEN_HEIGHT//2), size)
                    pygame.draw.circle(fire_overlay, (255,220,50, base_alpha*2), (int(screen_x), SCREEN_HEIGHT//2), size//2)
        screen.blit(fire_overlay, (0,0))

    # 绘制毒气区域（重用Surface）
    if poison_zones:
        poison_overlay.fill((0,0,0,0))
        for pz in poison_zones:
            dx = pz.x - player_x
            dy = pz.y - player_y
            dist = math.hypot(dx, dy)
            if dist < 20:
                angle_to = math.atan2(dy, dx)
                angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                if 0 < screen_x < SCREEN_WIDTH:
                    progress = pz.duration / pz.max_duration
                    alpha = int(100 * progress)
                    size = int(45*(1+0.1*math.sin(pygame.time.get_ticks()*0.003)))
                    pygame.draw.circle(poison_overlay, (50,200,50, alpha//2), (int(screen_x), SCREEN_HEIGHT//2), size+15)
                    pygame.draw.circle(poison_overlay, (0,180,0, alpha), (int(screen_x), SCREEN_HEIGHT//2), size)
                    for _ in range(8):
                        offset_x = random.randint(-size, size)
                        offset_y = random.randint(-size, size)
                        if offset_x**2 + offset_y**2 < size**2:
                            pygame.draw.circle(poison_overlay, (100,255,100, alpha), (int(screen_x+offset_x), SCREEN_HEIGHT//2+offset_y), 2)
        screen.blit(poison_overlay, (0,0))

    # 绘制Boss
    if boss and boss.alive:
        dx = boss.x - player_x; dy = boss.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.3:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = int(300 / dist)
                rect = pygame.Rect(0,0,size,size)
                rect.center = (screen_x, SCREEN_HEIGHT//2 + global_vert_off)
                if "典狱长" in boss.name or "Warden" in boss.name: boss.color = (80,80,120)
                elif "雷丝" in boss.name or "Reiss" in boss.name: boss.color = (200,80,80)
                elif "赛伊德" in boss.name or "Saeed" in boss.name: boss.color = (100,120,80)
                elif "渡鸦" in boss.name or "Raven" in boss.name: boss.color = (120,80,160)
                elif "德穆兰" in boss.name or "Demullan" in boss.name: boss.color = (180,180,200)
                pygame.draw.rect(screen, boss.color, rect)
                pygame.draw.rect(screen, (255,0,0), rect, 3)
                hp_ratio = boss.hp / boss.max_hp
                pygame.draw.rect(screen, (255,0,0), (rect.x, rect.y-10, size, 8))
                pygame.draw.rect(screen, (0,255,0), (rect.x, rect.y-10, size*hp_ratio, 8))
                draw_text(screen, boss.name, rect.x, rect.y-30, (255,255,255), small_font)

    # 绘制护卫队
    for g in guards:
        if not g.alive: continue
        dx = g.x - player_x; dy = g.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.3:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = int(150 / dist)
                rect = pygame.Rect(0,0,size,size)
                rect.center = (screen_x, SCREEN_HEIGHT//2 + global_vert_off)
                pygame.draw.rect(screen, g.color, rect)
                hp_ratio = g.hp / g.max_hp
                pygame.draw.rect(screen, (0,200,0), (rect.x, rect.y-10, size*hp_ratio, 5))

    # 绘制战车
    for t in tanks:
        if not t.alive: continue
        dx = t.x - player_x; dy = t.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.3:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = int(200 / dist)
                rect = pygame.Rect(0,0,size,size)
                rect.center = (screen_x, SCREEN_HEIGHT//2 + global_vert_off)
                pygame.draw.rect(screen, t.color, rect)
                pygame.draw.rect(screen, (0,0,0), rect, 2)
                hp_ratio = t.hp / t.max_hp
                pygame.draw.rect(screen, (0,200,0), (rect.x, rect.y-10, size*hp_ratio, 5))

    # 绘制普通敌人
    for e in enemies:
        dx = e.x - player_x; dy = e.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.3:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = int(200 / dist)
                rect = pygame.Rect(0,0,size,size)
                rect.center = (screen_x, SCREEN_HEIGHT//2 + global_vert_off)
                pygame.draw.rect(screen, (0,200,0), rect)
                hp_ratio = e.hp / e.max_hp
                pygame.draw.rect(screen, (0,200,0), (rect.x, rect.y-10, size*hp_ratio, 5))
                eye_offset = int(size*0.2)
                pygame.draw.circle(screen, (255,0,0), (int(screen_x-eye_offset), int(SCREEN_HEIGHT//2 - eye_offset + global_vert_off)), max(2, size//8))

    # 玩家子弹
    for b in bullets:
        dx = b.x - player_x; dy = b.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.2:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = max(4, int(30/dist))
                rect = pygame.Rect(0,0,size,size)
                rect.center = (screen_x, SCREEN_HEIGHT//2 + global_vert_off)
                pygame.draw.rect(screen, (255,255,0), rect)
                pygame.draw.rect(screen, (255,200,0), rect.inflate(-2,-2))

    # 敌人子弹
    for eb in enemy_bullets:
        dx = eb.x - player_x; dy = eb.y - player_y
        dist = math.hypot(dx, dy)
        angle_to = math.atan2(dy, dx)
        angle_diff = (angle_to - player_angle + math.pi) % (2*math.pi) - math.pi
        if abs(angle_diff) < current_fov/1.5 and dist > 0.2:
            wall_dist, _, _ = cast_ray(ray_start_x, ray_start_y, angle_to, player_pitch)
            if dist < wall_dist:
                screen_x = SCREEN_WIDTH/2 + (angle_diff / (current_fov/2)) * SCREEN_WIDTH/2
                size = max(4, int(30/dist))
                col = (255,100,0) if eb.is_fire else (255,0,0)
                pygame.draw.circle(screen, col, (int(screen_x), int(SCREEN_HEIGHT//2 + global_vert_off)), size//2)

    # 准星
    cx, cy = SCREEN_WIDTH//2, SCREEN_HEIGHT//2
    if ads_active:
        pygame.draw.circle(screen, (255,255,255), (cx, cy), 20, 2)
        pygame.draw.circle(screen, (255,0,0), (cx, cy), 2)
    else:
        pygame.draw.line(screen, (255,255,255), (cx-12, cy), (cx+12, cy), 2)
        pygame.draw.line(screen, (255,255,255), (cx, cy-12), (cx, cy+12), 2)

    # 探头指示
    if lean_offset != 0:
        lean_text = "<< Lean Left" if USE_ENGLISH and lean_offset < 0 else "Lean Right >>" if USE_ENGLISH else "左探头" if lean_offset < 0 else "右探头"
        draw_text(screen, lean_text, SCREEN_WIDTH//2, SCREEN_HEIGHT-100, (255,255,0), small_font, center=True)

    # 开镜遮罩（模拟狙击镜边缘黑色效果）
    if ads_active:
        vignette = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        vignette.fill((0,0,0,180))
        pygame.draw.circle(vignette, (0,0,0,0), (cx, cy), 120)
        screen.blit(vignette, (0,0))

    draw_weapon_model(screen, current_weapon, is_reloading)

    # UI
    hp_bar_width = 200
    hp_fill = int(hp_bar_width * (player_hp / max_hp))
    pygame.draw.rect(screen, (60,60,60), (10,10, hp_bar_width, 20))
    pygame.draw.rect(screen, (0,200,0), (10,10, hp_fill, 20))
    hp_label = "HP" if USE_ENGLISH else "生命"
    draw_text(screen, f"{hp_label}: {player_hp}", 10, 35)

    mode_text = "Endless" if current_mode == MODE_ENDLESS else "Classic"
    if boss: mode_text = f"Boss: {boss.name}"
    score_label = "Score" if USE_ENGLISH else "得分"
    wave_label = "Wave" if USE_ENGLISH else "波次"
    money_label = "$" if USE_ENGLISH else "金钱"
    draw_text(screen, f"{score_label}: {score}  {wave_label}: {wave}  {money_label}: {money}  {mode_text}", 10, 60)

    help_text = "WASD Move | LMB Shoot | R Reload | Q/E Lean | Space Jump | Ctrl Slide | RMB ADS | B Shop | V Heal"
    draw_text(screen, help_text, 10, SCREEN_HEIGHT-30, (200,200,200), small_font)

    medkit_label = "Medkit" if USE_ENGLISH else "医疗充能"
    draw_text(screen, f"{medkit_label}: {heal_charges}", SCREEN_WIDTH-150, SCREEN_HEIGHT-80, (200,200,200), small_font)
    if heal_active:
        healing_text = "Healing..." if USE_ENGLISH else "治疗中..."
        draw_text(screen, healing_text, SCREEN_WIDTH-150, SCREEN_HEIGHT-100, (0,255,0), small_font)
    if player_slowed:
        slow_text = "SLOWED" if USE_ENGLISH else "减速"
        draw_text(screen, slow_text, SCREEN_WIDTH-80, 80, (0,255,0), small_font)

    ammo_text = f"{clip_ammo} / {reserve_ammo}"
    draw_text(screen, ammo_text, SCREEN_WIDTH-100, SCREEN_HEIGHT-50, (255,255,255), font)

    if is_reloading:
        bar_width = 100
        bar_x = SCREEN_WIDTH-120; bar_y = SCREEN_HEIGHT-30
        progress = 1 - (reload_timer / RELOAD_TIME)
        pygame.draw.rect(screen, (80,80,80), (bar_x, bar_y, bar_width, 10))
        pygame.draw.rect(screen, (0,200,200), (bar_x, bar_y, bar_width*progress, 10))
    elif shot_cooldown > 0:
        cd_bar_x = SCREEN_WIDTH-120; cd_bar_y = SCREEN_HEIGHT-70
        cd_progress = shot_cooldown / MAX_SHOT_COOLDOWN
        pygame.draw.rect(screen, (80,80,80), (cd_bar_x, cd_bar_y, 100, 5))
        pygame.draw.rect(screen, (200,150,0), (cd_bar_x, cd_bar_y, 100*cd_progress, 5))

    # 小地图
    minimap_size = 180
    minimap_surf = pygame.Surface((minimap_size, minimap_size))
    minimap_surf.fill((50,50,50))
    tile_draw_size = minimap_size // MAP_SIZE
    for my in range(MAP_SIZE):
        for mx in range(MAP_SIZE):
            if MAP[my][mx] == 1:
                pygame.draw.rect(minimap_surf, (100,100,100), (mx*tile_draw_size, my*tile_draw_size, tile_draw_size, tile_draw_size))
    px = int(player_x * tile_draw_size); py = int(player_y * tile_draw_size)
    pygame.draw.circle(minimap_surf, (0,200,0), (px, py), 3)
    line_end_x = px + int(math.cos(player_angle)*12)
    line_end_y = py + int(math.sin(player_angle)*12)
    pygame.draw.line(minimap_surf, (0,255,0), (px, py), (line_end_x, line_end_y), 1)
    for e in enemies:
        ex, ey = int(e.x*tile_draw_size), int(e.y*tile_draw_size)
        pygame.draw.circle(minimap_surf, (255,0,0), (ex, ey), 2)
    for g in guards:
        if g.alive:
            gx, gy = int(g.x*tile_draw_size), int(g.y*tile_draw_size)
            pygame.draw.circle(minimap_surf, (200,100,0), (gx, gy), 2)
    for t in tanks:
        if t.alive:
            tx, ty = int(t.x*tile_draw_size), int(t.y*tile_draw_size)
            pygame.draw.circle(minimap_surf, (100,100,200), (tx, ty), 3)
    if boss and boss.alive:
        bx, by = int(boss.x*tile_draw_size), int(boss.y*tile_draw_size)
        pygame.draw.circle(minimap_surf, (255,0,0), (bx, by), 5)
    screen.blit(minimap_surf, (SCREEN_WIDTH - minimap_size - 10, 10))

    if shop_open:
        draw_shop(screen, money, weapons, current_weapon_index)

    if invincible and (invincible_timer // 5) % 2 == 0:
        pygame.draw.rect(screen, (255,255,255), (0,0, SCREEN_WIDTH, SCREEN_HEIGHT), 5)

    pygame.display.flip()

pygame.quit()
sys.exit()