import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';

// 게임 상수
const GAME_DURATION = 180;
const MAP_SIZE = 500;
const TANK_HEIGHT = 0.5;
const ENEMY_GROUND_HEIGHT = 0;
const ENEMY_SCALE = 1;
const MAX_HEALTH = 1000;
const ENEMY_MOVE_SPEED = 0.1;
const ENEMY_COUNT_MAX = 3;
const PARTICLE_COUNT = 15;
const BUILDING_COUNT = 25;
const ENEMY_CONFIG = {
    ATTACK_RANGE: 100,
    ATTACK_INTERVAL: 2000,
    BULLET_SPEED: 2
};

// TankPlayer 클래스
class TankPlayer {
    constructor() {
        this.body = null;
        this.turret = null;
        this.position = new THREE.Vector3(0, 0, 0);
        this.rotation = new THREE.Euler(0, 0, 0);
        this.turretRotation = 0;
        this.moveSpeed = 0.5;
        this.turnSpeed = 0.03;
        this.turretGroup = new THREE.Group();
        this.health = MAX_HEALTH;
        this.isLoaded = false;
        this.ammo = 1;  // 변경: 10 -> 1
        this.maxAmmo = 1;  // 추가: 최대 포탄 수
        this.isReloading = false;  // 추가: 재장전 상태
        this.reloadTime = 3000;  // 추가: 3초 재장전 시간
        this.lastShootTime = 0;
        this.bullets = [];
        this.obstacles = [];
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
    }
     // 별도의 메서드로 분리
    createExplosionEffect(scene, position) {
    // 폭발 중심 플래시
    const flashGeometry = new THREE.SphereGeometry(3);
    const flashMaterial = new THREE.MeshBasicMaterial({
        color: 0xffff00,
        transparent: true,
        opacity: 1
    });
    const flash = new THREE.Mesh(flashGeometry, flashMaterial);
    flash.position.copy(position);
    scene.add(flash);

    // 폭발 파티클
    for (let i = 0; i < 30; i++) {
        const size = Math.random() * 0.5 + 0.3;
        const geometry = new THREE.SphereGeometry(size);
        
        // 다양한 색상의 파티클
        const colors = [0xff4500, 0xff8c00, 0xff0000, 0xffd700];
        const material = new THREE.MeshBasicMaterial({
            color: colors[Math.floor(Math.random() * colors.length)],
            transparent: true,
            opacity: 1
        });
        
        const particle = new THREE.Mesh(geometry, material);
        particle.position.copy(position);

        // 파티클 속도와 방향 설정
        const speed = Math.random() * 0.5 + 0.3;
        const angle = Math.random() * Math.PI * 2;
        const elevation = Math.random() * Math.PI - Math.PI / 2;

        particle.velocity = new THREE.Vector3(
            Math.cos(angle) * Math.cos(elevation) * speed,
            Math.sin(elevation) * speed,
            Math.sin(angle) * Math.cos(elevation) * speed
        );

        particle.gravity = -0.015;
        particle.life = Math.random() * 30 + 30;
        particle.fadeRate = 0.97;

        scene.add(particle);
        window.gameInstance.particles.push({
            mesh: particle,
            velocity: particle.velocity,
            gravity: particle.gravity,
            life: particle.life,
            fadeRate: particle.fadeRate
        });
    }

    // 폭발 링 이펙트
    const ringGeometry = new THREE.RingGeometry(0.1, 2, 32);
    const ringMaterial = new THREE.MeshBasicMaterial({
        color: 0xff8c00,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide
    });
    const ring = new THREE.Mesh(ringGeometry, ringMaterial);
    ring.position.copy(position);
    ring.lookAt(new THREE.Vector3(0, 1, 0));
    scene.add(ring);

    // 링 확장 애니메이션
    const expandRing = () => {
        ring.scale.x += 0.2;
        ring.scale.y += 0.2;
        ring.material.opacity *= 0.95;

        if (ring.material.opacity > 0.01) {
            requestAnimationFrame(expandRing);
        } else {
            scene.remove(ring);
        }
    };
    expandRing();

    // 폭발음 효과
    const explosionSound = new Audio('sounds/bang.ogg');
    explosionSound.volume = 0.4;
    explosionSound.play();

    // 카메라 흔들림 효과
    if (window.gameInstance && window.gameInstance.camera) {
        const camera = window.gameInstance.camera;
        const originalPosition = camera.position.clone();
        let shakeTime = 0;
        const shakeIntensity = 0.3;
        const shakeDuration = 500;

        const shakeCamera = () => {
            if (shakeTime < shakeDuration) {
                camera.position.x = originalPosition.x + (Math.random() - 0.5) * shakeIntensity;
                camera.position.y = originalPosition.y + (Math.random() - 0.5) * shakeIntensity;
                camera.position.z = originalPosition.z + (Math.random() - 0.5) * shakeIntensity;

                shakeTime += 16;
                requestAnimationFrame(shakeCamera);
            } else {
                camera.position.copy(originalPosition);
            }
        };
        shakeCamera();
    }

    // 중심 플래시 제거
    setTimeout(() => {
        scene.remove(flash);
    }, 100);
}

    async initialize(scene, loader) {
    try {
        const bodyResult = await loader.loadAsync('/models/abramsBody.glb');
        this.body = bodyResult.scene;
        
        const turretResult = await loader.loadAsync('/models/abramsTurret.glb');
        this.turret = turretResult.scene;
        
        this.turretGroup.position.y = 0.2;
        this.turretGroup.add(this.turret);
        this.body.add(this.turretGroup);
        
        // 그림자 설정은 그대로 유지
        this.body.traverse((child) => {
            if (child.isMesh) {
                child.castShadow = true;
                child.receiveShadow = true;
                child.material.shadowSide = THREE.BackSide;
                child.material.needsUpdate = true;
            }
        });
        
        this.turret.traverse((child) => {
            if (child.isMesh) {
                child.castShadow = true;
                child.receiveShadow = true;
                child.material.shadowSide = THREE.BackSide;
                child.material.needsUpdate = true;
            }
        });

        // 그림자 평면
        const shadowPlaneGeometry = new THREE.PlaneGeometry(8, 8);
        const shadowPlaneMaterial = new THREE.ShadowMaterial({
            opacity: 0.3
        });
        this.shadowPlane = new THREE.Mesh(shadowPlaneGeometry, shadowPlaneMaterial);
        this.shadowPlane.receiveShadow = true;
        this.shadowPlane.rotation.x = -Math.PI / 2;
        this.shadowPlane.position.y = 0.1;
        this.body.add(this.shadowPlane);

        // 간단한 스폰 위치 설정
        const spawnPosition = new THREE.Vector3(
            (Math.random() - 0.5) * (MAP_SIZE * 0.8), // MAP_SIZE의 80%만 사용
            TANK_HEIGHT, // 고정된 높이 사용
            (Math.random() - 0.5) * (MAP_SIZE * 0.8)
        );
        
        this.body.position.copy(spawnPosition);

        // 폭발 이펙트 메서드 추가
        this.createExplosionEffect = (scene, position) => {
            // 폭발 파티클
            for (let i = 0; i < 15; i++) {
                const size = Math.random() * 0.2 + 0.1;
                const geometry = new THREE.SphereGeometry(size);
                const material = new THREE.MeshBasicMaterial({
                    color: Math.random() < 0.5 ? 0xff4500 : 0xff8c00
                });
                const particle = new THREE.Mesh(geometry, material);
                particle.position.copy(position);

                const speed = Math.random() * 0.3 + 0.2;
                const angle = Math.random() * Math.PI * 2;
                const elevation = Math.random() * Math.PI - Math.PI / 2;

                particle.velocity = new THREE.Vector3(
                    Math.cos(angle) * Math.cos(elevation) * speed,
                    Math.sin(elevation) * speed,
                    Math.sin(angle) * Math.cos(elevation) * speed
                );

                particle.gravity = -0.01;
                particle.life = Math.random() * 20 + 20;
                particle.fadeRate = 1 / particle.life;

                scene.add(particle);
                window.gameInstance.particles.push({
                    mesh: particle,
                    velocity: particle.velocity,
                    gravity: particle.gravity,
                    life: particle.life,
                    fadeRate: particle.fadeRate
                });
            }

            // 충돌 사운드 재생
            const explosionSound = new Audio('sounds/explosion.ogg');
            explosionSound.volume = 0.3;
            explosionSound.play();
        };

        scene.add(this.body);
        this.isLoaded = true;
        this.updateAmmoDisplay();
        
    } catch (error) {
        console.error('Error loading tank models:', error);
        this.isLoaded = false;
    }
}

    shoot(scene) {
    // 재장전 중이거나 탄약이 없으면 발사하지 않음
    if (this.isReloading || this.ammo <= 0) {
        return null;
    }

    // 발사 딜레이 체크 (연속 발사 방지)
    const currentTime = Date.now();
    if (currentTime - this.lastShootTime < 100) { // 100ms의 발사 딜레이
        return null;
    }
    this.lastShootTime = currentTime;

    // 발사음 효과 (한 번만 재생)
    const sounds = ['sounds/mbtfire1.ogg', 'sounds/mbtfire2.ogg', 'sounds/mbtfire3.ogg', 'sounds/mbtfire4.ogg'];
    const randomSound = sounds[Math.floor(Math.random() * sounds.length)];
    const audio = new Audio(randomSound);
    audio.volume = 0.5;
    
    // 이전 오디오 인스턴스가 있다면 중지
    if (this.lastAudio) {
        this.lastAudio.pause();
        this.lastAudio.currentTime = 0;
    }
    
    this.lastAudio = audio;
    audio.play();

    // 발사 이펙트
    this.createMuzzleFlash(scene);

    // 포탄 생성
    const bullet = this.createBullet(scene);
    if (bullet) {
        this.ammo--;
        this.updateAmmoDisplay();
        
        // 탄약을 모두 소진했을 때만 재장전 시작
        if (this.ammo <= 0) {
            this.startReload();
        }
    }
    return bullet;
}

startReload() {
    if (this.isReloading) return; // 이미 재장전 중이면 무시
    
    this.isReloading = true;
    const reloadingText = document.getElementById('reloadingText');
    reloadingText.style.display = 'block';
    
    setTimeout(() => {
        this.ammo = this.maxAmmo;
        this.isReloading = false;
        reloadingText.style.display = 'none';
        this.updateAmmoDisplay();
    }, this.reloadTime);
}

  createMuzzleFlash(scene) {
    if (!this.turret) return;
    const flashGroup = new THREE.Group();
    
    // 화염 크기 증가
    const flameGeometry = new THREE.SphereGeometry(1.0, 8, 8);
    const flameMaterial = new THREE.MeshBasicMaterial({
        color: 0xffa500,
        transparent: true,
        opacity: 0.8
    });
    const flame = new THREE.Mesh(flameGeometry, flameMaterial);
    flame.scale.set(2, 2, 3);
    flashGroup.add(flame);

    // 연기 효과 크기 증가
    const smokeGeometry = new THREE.SphereGeometry(0.8, 8, 8);
    const smokeMaterial = new THREE.MeshBasicMaterial({
        color: 0x555555,
        transparent: true,
        opacity: 0.5
    });
    
    for (let i = 0; i < 5; i++) { // 연기 파티클 수 증가
        const smoke = new THREE.Mesh(smokeGeometry, smokeMaterial);
        smoke.position.set(
            Math.random() * 1 - 0.5,
            Math.random() * 1 - 0.5,
            -1 - Math.random()
        );
        smoke.scale.set(1.5, 1.5, 1.5);
        flashGroup.add(smoke);
    }

    // 포구 위치 계산
    const muzzleOffset = new THREE.Vector3(0, 0.5, 4);
    const muzzlePosition = new THREE.Vector3();
    const turretWorldQuaternion = new THREE.Quaternion();
    
    this.turret.getWorldPosition(muzzlePosition);
    this.turret.getWorldQuaternion(turretWorldQuaternion);
    
    muzzleOffset.applyQuaternion(turretWorldQuaternion);
    muzzlePosition.add(muzzleOffset);

    flashGroup.position.copy(muzzlePosition);
    flashGroup.quaternion.copy(turretWorldQuaternion);

    scene.add(flashGroup);

    // 이펙트 지속 시간 증가
    setTimeout(() => {
        scene.remove(flashGroup);
    }, 500);
}



    createBullet(scene) {
      if (!this.turret) return null; // 터렛이 없으면 null 반환
    // 포탄 크기 증가
    const bulletGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2, 8);
    const bulletMaterial = new THREE.MeshBasicMaterial({ color: 0xffd700 });
    const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);

    // 포탑의 월드 위치와 방향 가져오기
    const muzzleOffset = new THREE.Vector3(0, 0.5, 4); // 포구 위치 조정 (앞쪽으로 더 이동)
    const muzzlePosition = new THREE.Vector3();
    const turretWorldQuaternion = new THREE.Quaternion();
    
    // 포탑의 월드 변환 행렬 가져오기
    this.turret.getWorldPosition(muzzlePosition);
    this.turret.getWorldQuaternion(turretWorldQuaternion);
    
    // 포구 오프셋 적용
    muzzleOffset.applyQuaternion(turretWorldQuaternion);
    muzzlePosition.add(muzzleOffset);
    
    // 포탄 위치와 회전 설정
    bullet.position.copy(muzzlePosition);
    bullet.quaternion.copy(turretWorldQuaternion);
    
    // 발사 방향 설정
    const direction = new THREE.Vector3(0, 0, 1);
    direction.applyQuaternion(turretWorldQuaternion);
    bullet.velocity = direction.multiplyScalar(5);

    scene.add(bullet);
    this.bullets.push(bullet);

    return bullet;
}


    update(mouseX, mouseY, scene) {
    if (!this.body || !this.turretGroup) return;

    const absoluteTurretRotation = mouseX;
    this.turretGroup.rotation.y = absoluteTurretRotation - this.body.rotation.y;
    this.turretRotation = absoluteTurretRotation;

    // 총알 업데이트 및 충돌 체크
    for (let i = this.bullets.length - 1; i >= 0; i--) {
        const bullet = this.bullets[i];
        const oldPosition = bullet.position.clone();
        bullet.position.add(bullet.velocity);

        // 지형 높이 체크
        const terrainHeight = window.gameInstance.getHeightAtPosition(
            bullet.position.x,
            bullet.position.z
        );

        if (bullet.position.y < terrainHeight ||
            Math.abs(bullet.position.x) > MAP_SIZE / 2 ||
            Math.abs(bullet.position.z) > MAP_SIZE / 2) {
            
            // 폭발 이펙트 생성
            this.createExplosionEffect(scene, bullet.position);
            
            scene.remove(bullet);
            this.bullets.splice(i, 1);
        }
    }
}

    move(direction) {
    if (!this.body) return;
    
    const moveVector = new THREE.Vector3();
    moveVector.x = direction.x * this.moveSpeed;
    moveVector.z = direction.z * this.moveSpeed;
    
    // 새로운 위치 계산
    const newPosition = this.body.position.clone().add(moveVector);
    
    // 새로운 위치의 지형 높이 가져오기
    const heightAtNewPos = window.gameInstance.getHeightAtPosition(newPosition.x, newPosition.z);
    
    // 탱크 높이만큼 더해서 지형 위에 위치시킴
    newPosition.y = heightAtNewPos + TANK_HEIGHT;
    
    // 경사가 너무 가파른지 체크
    const currentHeight = this.body.position.y;
    const heightDifference = Math.abs(newPosition.y - currentHeight);
    const maxClimbAngle = 0.5; // 최대 등반 각도
    
    if (heightDifference / this.moveSpeed < maxClimbAngle) {
        this.body.position.copy(newPosition);
        
        // 탱크의 방향 벡터 계산
        const forwardVector = new THREE.Vector3(0, 0, 1).applyQuaternion(this.body.quaternion);
        const rightVector = new THREE.Vector3(1, 0, 0).applyQuaternion(this.body.quaternion);
        
        // 탱크 주변의 높이 계산
        const frontHeight = window.gameInstance.getHeightAtPosition(
            newPosition.x + forwardVector.x,
            newPosition.z + forwardVector.z
        );
        const backHeight = window.gameInstance.getHeightAtPosition(
            newPosition.x - forwardVector.x,
            newPosition.z - forwardVector.z
        );
        const rightHeight = window.gameInstance.getHeightAtPosition(
            newPosition.x + rightVector.x,
            newPosition.z + rightVector.z
        );
        const leftHeight = window.gameInstance.getHeightAtPosition(
            newPosition.x - rightVector.x,
            newPosition.z - rightVector.z
        );
        
        // 탱크의 기울기 계산 및 적용
        const pitch = Math.atan2(frontHeight - backHeight, 2);
        const roll = Math.atan2(rightHeight - leftHeight, 2);
        
        // 기존 y축 회전은 유지하면서 새로운 기울기 적용
        const currentYRotation = this.body.rotation.y;
        this.body.rotation.set(pitch, currentYRotation, roll);
    }
}

    rotate(angle) {
        if (!this.body) return;
        
        // y축 회전 적용
        this.body.rotation.y += angle * this.turnSpeed;
        
        // 현재 위치에서의 지형에 맞춰 탱크 기울기 조정
        const position = this.body.position;
        const forwardVector = new THREE.Vector3(0, 0, 1).applyQuaternion(this.body.quaternion);
        const rightVector = new THREE.Vector3(1, 0, 0).applyQuaternion(this.body.quaternion);
        
        // 탱크 주변의 높이 계산
        const frontHeight = window.gameInstance.getHeightAtPosition(
            position.x + forwardVector.x,
            position.z + forwardVector.z
        );
        const backHeight = window.gameInstance.getHeightAtPosition(
            position.x - forwardVector.x,
            position.z - forwardVector.z
        );
        const rightHeight = window.gameInstance.getHeightAtPosition(
            position.x + rightVector.x,
            position.z + rightVector.z
        );
        const leftHeight = window.gameInstance.getHeightAtPosition(
            position.x - rightVector.x,
            position.z - rightVector.z
        );
        
        // 탱크의 기울기 계산 및 적용
        const pitch = Math.atan2(frontHeight - backHeight, 2);
        const roll = Math.atan2(rightHeight - leftHeight, 2);
        
        // 현재 y축 회전은 유지하면서 새로운 기울기 적용
        const currentYRotation = this.body.rotation.y;
        this.body.rotation.set(pitch, currentYRotation, roll);
    }
    
    getPosition() {
        return this.body ? this.body.position : new THREE.Vector3();
    }
    
    takeDamage(damage) {
    this.health -= damage;

    // 사망 여부 체크
    if (this.health <= 0) {
        const deathSound = new Audio('sounds/bang.ogg');
        deathSound.play();
        return true; // 사망
    }
    return false; // 생존
}
    startReload() {
        this.isReloading = true;
        const reloadingText = document.getElementById('reloadingText');
        reloadingText.style.display = 'block';
        setTimeout(() => {
            this.ammo = this.maxAmmo;
            this.isReloading = false;
            reloadingText.style.display = 'none';
            this.updateAmmoDisplay();
        }, this.reloadTime);
    }
    
    updateAmmoDisplay() {
        document.getElementById('ammoDisplay').textContent = `APFSDS: ${this.ammo}/${this.maxAmmo}`;
    }
}

// Enemy 클래스
class Enemy {
    constructor(scene, position, type = 'tank') {
        // 기본 속성
        this.scene = scene;
        this.position = position;
        this.mesh = null;
        this.type = type;
        this.health = type === 'tank' ? 100 : 200;
        this.lastAttackTime = 0;
        this.bullets = [];
        this.isLoaded = false;
        this.alternativePath = null;
        this.pathFindingTimeout = 0;
        this.lastPathUpdateTime = 0;
        this.pathUpdateInterval = 3000; // 3초마다 경로 업데이트
        this.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
        this.hasPlayedWarning = false; // 경고음 재생 여부 추적
        
        // AI 상태 관리
        this.aiState = {
            mode: 'pursue',
            lastStateChange: 0,
            stateChangeCooldown: 3000,
            lastVisibilityCheck: 0,
            visibilityCheckInterval: 500,
            canSeePlayer: false,
            lastKnownPlayerPosition: null,
            searchStartTime: null,
            targetRotation: 0,
            currentRotation: 0,
            isAiming: false,
            aimingTime: 0,
            requiredAimTime: 1000 // 조준에 필요한 시간
        };

        // 경로 탐색 및 회피 시스템
        this.pathfinding = {
            currentPath: [],
            pathUpdateInterval: 1000,
            lastPathUpdate: 0,
            isAvoidingObstacle: false,
            avoidanceDirection: null,
            obstacleCheckDistance: 10,
            avoidanceTime: 0,
            maxAvoidanceTime: 3000, // 최대 회피 시간
            sensorAngles: [-45, 0, 45], // 전방 감지 각도
            sensorDistance: 15 // 감지 거리
        };

        // 전투 시스템
        this.combat = {
            minEngagementRange: 30,
            maxEngagementRange: 150,
            optimalRange: 80,
            aimThreshold: 0.1, // 조준 정확도 임계값
            lastShotAccuracy: 0,
            consecutiveHits: 0,
            maxConsecutiveHits: 3
        };
    }
    // 장애물 감지 시스템
    detectObstacles() {
        const obstacles = [];
        const position = this.mesh.position.clone();
        position.y += 1; // 센서 높이 조정

        this.pathfinding.sensorAngles.forEach(angle => {
            const direction = new THREE.Vector3(0, 0, 1)
                .applyQuaternion(this.mesh.quaternion)
                .applyAxisAngle(new THREE.Vector3(0, 1, 0), angle * Math.PI / 180);

            const raycaster = new THREE.Raycaster(position, direction, 0, this.pathfinding.sensorDistance);
            const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);

            if (intersects.length > 0) {
                obstacles.push({
                    angle: angle,
                    distance: intersects[0].distance,
                    point: intersects[0].point
                });
            }
        });

        return obstacles;
    }

    // 회피 방향 계산
    calculateAvoidanceDirection(obstacles) {
        if (obstacles.length === 0) return null;

        // 모든 장애물의 방향을 고려하여 최적의 회피 방향 계산
        const avoidanceVector = new THREE.Vector3();
        obstacles.forEach(obstacle => {
            const avoidDir = new THREE.Vector3()
                .subVectors(this.mesh.position, obstacle.point)
                .normalize()
                .multiplyScalar(1 / obstacle.distance); // 거리에 반비례하는 가중치
            avoidanceVector.add(avoidDir);
        });

        return avoidanceVector.normalize();
    }

    // 조준 시스템
    updateAiming(playerPosition) {
    const targetDirection = new THREE.Vector3()
        .subVectors(playerPosition, this.mesh.position)
        .normalize();

    // 목표 회전각 계산
    this.aiState.targetRotation = Math.atan2(targetDirection.x, targetDirection.z);

    // 현재 회전각 부드럽게 조정 - 선회 속도를 느리게 하기 위해 조정
    const rotationDiff = this.aiState.targetRotation - this.aiState.currentRotation;
    let rotationStep = Math.sign(rotationDiff) * Math.min(Math.abs(rotationDiff), 0.05); // 기존 0.02에서 0.05로 수정
    this.aiState.currentRotation += rotationStep;

    // 메시 회전 적용
    this.mesh.rotation.y = this.aiState.currentRotation;

    // 조준 정확도 계산
    const aimAccuracy = 1 - Math.abs(rotationDiff) / Math.PI;
    return aimAccuracy > this.combat.aimThreshold;
}

    // 전투 거리 관리
    maintainCombatDistance(playerPosition) {
        const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);
        let moveDirection = new THREE.Vector3();

        if (distanceToPlayer < this.combat.minEngagementRange) {
            // 너무 가까우면 후진
            moveDirection.subVectors(this.mesh.position, playerPosition).normalize();
        } else if (distanceToPlayer > this.combat.maxEngagementRange) {
            // 너무 멀면 전진
            moveDirection.subVectors(playerPosition, this.mesh.position).normalize();
        } else if (Math.abs(distanceToPlayer - this.combat.optimalRange) > 10) {
            // 최적 거리로 조정
            const targetDistance = this.combat.optimalRange;
            moveDirection.subVectors(playerPosition, this.mesh.position).normalize();
            if (distanceToPlayer > targetDistance) {
                moveDirection.multiplyScalar(1);
            } else {
                moveDirection.multiplyScalar(-1);
            }
        }

        return moveDirection;
    }

    // 발사 조건 확인
    canShoot(playerPosition) {
        const distance = this.mesh.position.distanceTo(playerPosition);
        const hasLineOfSight = this.checkLineOfSight(playerPosition);
        const isAimed = this.updateAiming(playerPosition);

        return distance <= this.combat.maxEngagementRange && 
               distance >= this.combat.minEngagementRange && 
               hasLineOfSight && 
               isAimed;
    }

    // 메인 업데이트 함수
    update(playerPosition) {
    if (!this.mesh || !this.isLoaded) return;

      // 플레이어와의 거리 체크 및 경고음 재생
    const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);
    if (!this.hasPlayedWarning && distanceToPlayer <= ENEMY_CONFIG.ATTACK_RANGE) {
        const warningSound = new Audio('sounds/warning.ogg');
        warningSound.volume = 0.5;
        warningSound.play();
        this.hasPlayedWarning = true;
    }

    // AI 상태 업데이트
    this.updateAIState(playerPosition);

    // 장애물 감지 및 시야 체크
    const obstacles = this.detectObstacles();
    const currentTime = Date.now();
    const hasLineOfSight = this.checkLineOfSight(playerPosition);
    const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);

    // 경로 업데이트 주기 체크
    if (currentTime - this.lastPathUpdateTime > this.pathUpdateInterval) {
        if (!hasLineOfSight) {
            this.alternativePath = this.findAlternativePath(playerPosition);
        }
        this.lastPathUpdateTime = currentTime;
    }

    // 장애물 회피 로직
    if (obstacles.length > 0 && !this.pathfinding.isAvoidingObstacle) {
        this.pathfinding.isAvoidingObstacle = true;
        this.pathfinding.avoidanceDirection = this.calculateAvoidanceDirection(obstacles);
        this.pathfinding.avoidanceTime = 0;
    }

    // 이동 로직 실행
    if (this.pathfinding.isAvoidingObstacle) {
        // 회피 동작
        this.pathfinding.avoidanceTime += 16;
        if (this.pathfinding.avoidanceTime >= this.pathfinding.maxAvoidanceTime) {
            this.pathfinding.isAvoidingObstacle = false;
        } else {
            const avoidMove = this.pathfinding.avoidanceDirection.multiplyScalar(this.moveSpeed);
            this.mesh.position.add(avoidMove);
        }
    } else if (!hasLineOfSight) {
        // 시야가 없을 때의 이동
        if (this.alternativePath) {
            const pathDirection = new THREE.Vector3()
                .subVectors(this.alternativePath, this.mesh.position)
                .normalize();
            this.mesh.position.add(pathDirection.multiplyScalar(this.moveSpeed));

            const targetRotation = Math.atan2(pathDirection.x, pathDirection.z);
            this.mesh.rotation.y = this.smoothRotation(this.mesh.rotation.y, targetRotation, 0.1);
        }
    } else {
        // 시야가 있을 때의 이동
        this.alternativePath = null;

        // AI 상태에 따른 이동
        switch (this.aiState.mode) {
            case 'pursue':
                if (distanceToPlayer > ENEMY_CONFIG.ATTACK_RANGE * 0.7) {
                    const moveDirection = new THREE.Vector3()
                        .subVectors(playerPosition, this.mesh.position)
                        .normalize();
                    this.mesh.position.add(moveDirection.multiplyScalar(this.moveSpeed));
                }
                break;

            case 'flank':
                const flankPosition = this.calculateFlankPosition(playerPosition);
                this.findPathToTarget(flankPosition);
                this.moveAlongPath();
                break;

            case 'retreat':
                if (distanceToPlayer < ENEMY_CONFIG.ATTACK_RANGE * 0.3) {
                    const retreatDirection = new THREE.Vector3()
                        .subVectors(this.mesh.position, playerPosition)
                        .normalize();
                    this.mesh.position.add(retreatDirection.multiplyScalar(this.moveSpeed));
                }
                break;
        }

        // 플레이어 방향으로 회전
        const directionToPlayer = new THREE.Vector3()
            .subVectors(playerPosition, this.mesh.position)
            .normalize();
        const targetRotation = Math.atan2(directionToPlayer.x, directionToPlayer.z);
        this.mesh.rotation.y = this.smoothRotation(this.mesh.rotation.y, targetRotation, 0.1);
    }

    // 전투 거리 조정
    const combatMove = this.maintainCombatDistance(playerPosition);
    if (combatMove.length() > 0) {
        this.mesh.position.add(combatMove.multiplyScalar(this.moveSpeed));
    }

    // 공격 처리
    if (hasLineOfSight && distanceToPlayer <= ENEMY_CONFIG.ATTACK_RANGE && this.canShoot(playerPosition)) {
        this.shoot(playerPosition);
    }

    // 총알 업데이트
    this.updateBullets();

    // 탱크 기울기 조정
    this.adjustTankTilt();
}

checkLineOfSight(targetPosition) {
    if (!this.mesh) return false;

    const startPos = this.mesh.position.clone();
    startPos.y += 2; // 포탑 높이
    const direction = new THREE.Vector3()
        .subVectors(targetPosition, startPos)
        .normalize();
    const distance = startPos.distanceTo(targetPosition);

    const raycaster = new THREE.Raycaster(startPos, direction, 0, distance);
    const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);

    return intersects.length === 0;
}

findAlternativePath(playerPosition) {
    const currentPos = this.mesh.position.clone();
    const directionToPlayer = new THREE.Vector3()
        .subVectors(playerPosition, currentPos)
        .normalize();

    // 좌우 90도 방향 계산
    const leftDirection = new THREE.Vector3()
        .copy(directionToPlayer)
        .applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
    const rightDirection = new THREE.Vector3()
        .copy(directionToPlayer)
        .applyAxisAngle(new THREE.Vector3(0, 1, 0), -Math.PI / 2);

    // 좌우 30미터 지점 확인
    const checkDistance = 30;
    const leftPoint = currentPos.clone().add(leftDirection.multiplyScalar(checkDistance));
    const rightPoint = currentPos.clone().add(rightDirection.multiplyScalar(checkDistance));

    // 각 방향의 장애물 체크
    const leftClear = this.checkPathClear(currentPos, leftPoint);
    const rightClear = this.checkPathClear(currentPos, rightPoint);

    if (leftClear && rightClear) {
        // 둘 다 가능하면 랜덤 선택
        return Math.random() < 0.5 ? leftPoint : rightPoint;
    } else if (leftClear) {
        return leftPoint;
    } else if (rightClear) {
        return rightPoint;
    }

    return null;
}

checkPathClear(start, end) {
    const direction = new THREE.Vector3().subVectors(end, start).normalize();
    const distance = start.distanceTo(end);
    const raycaster = new THREE.Raycaster(start, direction, 0, distance);
    const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);
    return intersects.length === 0;
}

  async initialize(loader) {
        try {
            const modelPath = this.type === 'tank' ? '/models/t90.glb' : '/models/t90.glb';
            const result = await loader.loadAsync(modelPath);
            this.mesh = result.scene;
            this.mesh.position.copy(this.position);
            this.mesh.scale.set(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE);
            
            this.mesh.traverse((child) => {
                if (child.isMesh) {
                    child.castShadow = true;
                    child.receiveShadow = true;
                }
            });
            
            this.scene.add(this.mesh);
            this.isLoaded = true;
        } catch (error) {
            console.error('Error loading enemy model:', error);
            this.isLoaded = false;
        }
    }

   // 시야 확인 메서드 (기존 코드 수정)
    checkLineOfSight(playerPosition) {
        if (!this.mesh) return false;

        const startPos = this.mesh.position.clone();
        startPos.y += 2; // 포탑 높이
        const direction = new THREE.Vector3()
            .subVectors(playerPosition, startPos)
            .normalize();
        const distance = startPos.distanceTo(playerPosition);

        const raycaster = new THREE.Raycaster(startPos, direction, 0, distance);
        const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);

        // 장애물과의 충돌이 있는지 확인
        return intersects.length === 0;
    }
    // 대체 경로 찾기 메서드
    findAlternativePath(playerPosition) {
        const currentPos = this.mesh.position.clone();
        const directionToPlayer = new THREE.Vector3()
            .subVectors(playerPosition, currentPos)
            .normalize();

        // 좌우 90도 방향 계산
        const leftDirection = new THREE.Vector3()
            .copy(directionToPlayer)
            .applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
        const rightDirection = new THREE.Vector3()
            .copy(directionToPlayer)
            .applyAxisAngle(new THREE.Vector3(0, 1, 0), -Math.PI / 2);

        // 좌우 30미터 지점 확인
        const checkDistance = 30;
        const leftPoint = currentPos.clone().add(leftDirection.multiplyScalar(checkDistance));
        const rightPoint = currentPos.clone().add(rightDirection.multiplyScalar(checkDistance));

        // 각 방향의 장애물 체크
        const leftClear = this.checkPathClear(currentPos, leftPoint);
        const rightClear = this.checkPathClear(currentPos, rightPoint);

        if (leftClear && rightClear) {
            // 둘 다 가능하면 랜덤 선택
            return Math.random() < 0.5 ? leftPoint : rightPoint;
        } else if (leftClear) {
            return leftPoint;
        } else if (rightClear) {
            return rightPoint;
        }

        return null;
    }
    // 경로 유효성 확인
    checkPathClear(start, end) {
        const direction = new THREE.Vector3().subVectors(end, start).normalize();
        const distance = start.distanceTo(end);
        const raycaster = new THREE.Raycaster(start, direction, 0, distance);
        const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);
        return intersects.length === 0;
    }

    // 부드러운 회전 처리
    smoothRotation(current, target, factor) {
        let delta = target - current;
        
        // 각도 차이를 -PI에서 PI 사이로 정규화
        while (delta > Math.PI) delta -= Math.PI * 2;
        while (delta < -Math.PI) delta += Math.PI * 2;
        
        return current + delta * factor;
    }


    updateAIState(playerPosition) {
        const currentTime = Date.now();
        const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);

        if (currentTime - this.aiState.lastVisibilityCheck > this.aiState.visibilityCheckInterval) {
            this.aiState.canSeePlayer = this.checkLineOfSight(playerPosition);
            this.aiState.lastVisibilityCheck = currentTime;

            if (this.aiState.canSeePlayer) {
                this.aiState.lastKnownPlayerPosition = playerPosition.clone();
                this.aiState.searchStartTime = null;
            }
        }
        // 상태 변경 쿨다운을 2초로 설정
        const stateChangeCooldown = 2000;

        if (currentTime - this.aiState.lastStateChange > this.aiState.stateChangeCooldown) {
            if (this.health < 30) {
                this.aiState.mode = 'retreat';
            } else if (distanceToPlayer < 30 && this.aiState.canSeePlayer) {
                this.aiState.mode = 'flank';
            } else {
                this.aiState.mode = 'pursue';
            }
            this.aiState.lastStateChange = currentTime;
        }
    }

    findPathToTarget(targetPosition) {
        const currentTime = Date.now();
        if (currentTime - this.pathfinding.lastPathUpdate < this.pathfinding.pathUpdateInterval) {
            return;
        }

        this.pathfinding.currentPath = this.generatePathPoints(this.mesh.position.clone(), targetPosition);
        this.pathfinding.lastPathUpdate = currentTime;
    }

    generatePathPoints(start, end) {
        const points = [];
        const direction = new THREE.Vector3().subVectors(end, start).normalize();
        const distance = start.distanceTo(end);
        const steps = Math.ceil(distance / 10);

        for (let i = 0; i <= steps; i++) {
            const point = start.clone().add(direction.multiplyScalar(i * 10));
            points.push(point);
        }

        return points;
    }

    moveAlongPath() {
        if (this.pathfinding.currentPath.length === 0) return;

        const targetPoint = this.pathfinding.currentPath[0];
        const direction = new THREE.Vector3()
            .subVectors(targetPoint, this.mesh.position)
            .normalize();

        const moveVector = direction.multiplyScalar(this.moveSpeed);
        this.mesh.position.add(moveVector);

        if (this.mesh.position.distanceTo(targetPoint) < 2) {
            this.pathfinding.currentPath.shift();
        }
    }

    calculateFlankPosition(playerPosition) {
        const angle = Math.random() * Math.PI * 2;
        const radius = 40;
        return new THREE.Vector3(
            playerPosition.x + Math.cos(angle) * radius,
            playerPosition.y,
            playerPosition.z + Math.sin(angle) * radius
        );
    }

    calculateRetreatPosition(playerPosition) {
        const direction = new THREE.Vector3()
            .subVectors(this.mesh.position, playerPosition)
            .normalize();
        return this.mesh.position.clone().add(direction.multiplyScalar(50));
    }

    adjustTankTilt() {
        const forwardVector = new THREE.Vector3(0, 0, 1).applyQuaternion(this.mesh.quaternion);
        const rightVector = new THREE.Vector3(1, 0, 0).applyQuaternion(this.mesh.quaternion);
        
        const frontHeight = window.gameInstance.getHeightAtPosition(
            this.mesh.position.x + forwardVector.x,
            this.mesh.position.z + forwardVector.z
        );
        const backHeight = window.gameInstance.getHeightAtPosition(
            this.mesh.position.x - forwardVector.x,
            this.mesh.position.z - forwardVector.z
        );
        const rightHeight = window.gameInstance.getHeightAtPosition(
            this.mesh.position.x + rightVector.x,
            this.mesh.position.z + rightVector.z
        );
        const leftHeight = window.gameInstance.getHeightAtPosition(
            this.mesh.position.x - rightVector.x,
            this.mesh.position.z - rightVector.z
        );
        
        const pitch = Math.atan2(frontHeight - backHeight, 2);
        const roll = Math.atan2(rightHeight - leftHeight, 2);
        
        const currentRotation = this.mesh.rotation.y;
        this.mesh.rotation.set(pitch, currentRotation, roll);
    }

    updateBullets() {
        for (let i = this.bullets.length - 1; i >= 0; i--) {
            const bullet = this.bullets[i];
            bullet.position.add(bullet.velocity);
            
            if (Math.abs(bullet.position.x) > MAP_SIZE / 2 || 
                Math.abs(bullet.position.z) > MAP_SIZE / 2) {
                this.scene.remove(bullet);
                this.bullets.splice(i, 1);
                continue;
            }
            
            const bulletBox = new THREE.Box3().setFromObject(bullet);
            for (const obstacle of window.gameInstance.obstacles) {
                const obstacleBox = new THREE.Box3().setFromObject(obstacle);
                if (bulletBox.intersectsBox(obstacleBox)) {
                    this.scene.remove(bullet);
                    this.bullets.splice(i, 1);
                    break;
                }
            }
        }
    }

    createMuzzleFlash() {
        if (!this.mesh) return;
        
        const flashGroup = new THREE.Group();
        
        const flameGeometry = new THREE.SphereGeometry(1.0, 8, 8);
        const flameMaterial = new THREE.MeshBasicMaterial({
            color: 0xffa500,
            transparent: true,
            opacity: 0.8
        });
        const flame = new THREE.Mesh(flameGeometry, flameMaterial);
        flame.scale.set(2, 2, 3);
        flashGroup.add(flame);

        const smokeGeometry = new THREE.SphereGeometry(0.8, 8, 8);
        const smokeMaterial = new THREE.MeshBasicMaterial({
            color: 0x555555,
            transparent: true,
            opacity: 0.5
        });
        
        for (let i = 0; i < 5; i++) {
            const smoke = new THREE.Mesh(smokeGeometry, smokeMaterial);
            smoke.position.set(
                Math.random() * 1 - 0.5,
                Math.random() * 1 - 0.5,
                -1 - Math.random()
            );
            smoke.scale.set(1.5, 1.5, 1.5);
            flashGroup.add(smoke);
        }

        const muzzleOffset = new THREE.Vector3(0, 0.5, 4);
        const muzzlePosition = new THREE.Vector3();
        const meshWorldQuaternion = new THREE.Quaternion();
        
        this.mesh.getWorldPosition(muzzlePosition);
        this.mesh.getWorldQuaternion(meshWorldQuaternion);
        
        muzzleOffset.applyQuaternion(meshWorldQuaternion);
        muzzlePosition.add(muzzleOffset);

        flashGroup.position.copy(muzzlePosition);
        flashGroup.quaternion.copy(meshWorldQuaternion);

        this.scene.add(flashGroup);

        setTimeout(() => {
            this.scene.remove(flashGroup);
        }, 500);
    }
    createMassiveExplosion() {
    // 중심 폭발
    const explosionGroup = new THREE.Group();
    
    // 주 폭발 플래시 (크기 감소)
    const flashGeometry = new THREE.SphereGeometry(4); // 8에서 4로 감소
    const flashMaterial = new THREE.MeshBasicMaterial({
        color: 0xffff00,
        transparent: true,
        opacity: 1
    });
    const flash = new THREE.Mesh(flashGeometry, flashMaterial);
    flash.position.copy(this.mesh.position);
    this.scene.add(flash);

    // 다중 폭발 파티클 (수와 크기 감소)
    for (let i = 0; i < 50; i++) { // 100에서 50으로 감소
        const size = Math.random() * 1 + 0.5; // 크기 범위 감소
        const geometry = new THREE.SphereGeometry(size);
        
        // 다양한 폭발 색상
        const colors = [0xff4500, 0xff8c00, 0xff0000, 0xffd700];
        const material = new THREE.MeshBasicMaterial({
            color: colors[Math.floor(Math.random() * colors.length)],
            transparent: true,
            opacity: 1
        });
        
        const particle = new THREE.Mesh(geometry, material);
        particle.position.copy(this.mesh.position);

        // 파티클 속도 감소
        const speed = Math.random() * 1 + 0.5; // 속도 범위 감소
        const angle = Math.random() * Math.PI * 2;
        const elevation = Math.random() * Math.PI - Math.PI / 2;

        particle.velocity = new THREE.Vector3(
            Math.cos(angle) * Math.cos(elevation) * speed,
            Math.sin(elevation) * speed,
            Math.sin(angle) * Math.cos(elevation) * speed
        );

        particle.gravity = -0.05; // 중력 효과 감소
        particle.life = Math.random() * 30 + 30; // 수명 감소
        particle.fadeRate = 0.98;

        this.scene.add(particle);
        window.gameInstance.particles.push({
            mesh: particle,
            velocity: particle.velocity,
            gravity: particle.gravity,
            life: particle.life,
            fadeRate: particle.fadeRate
        });
    }

    // 폭발 링 이펙트 (크기와 확장 속도 감소)
    for (let i = 0; i < 2; i++) { // 3에서 2로 감소
        const ringGeometry = new THREE.RingGeometry(0.1, 2, 32);
        const ringMaterial = new THREE.MeshBasicMaterial({
            color: 0xff8c00,
            transparent: true,
            opacity: 1,
            side: THREE.DoubleSide
        });
        const ring = new THREE.Mesh(ringGeometry, ringMaterial);
        ring.position.copy(this.mesh.position);
        ring.rotation.x = Math.random() * Math.PI;
        ring.rotation.y = Math.random() * Math.PI;
        this.scene.add(ring);

        // 링 확장 애니메이션 (확장 속도 감소)
        const expandRing = () => {
            ring.scale.x += 0.15; // 0.3에서 0.15로 감소
            ring.scale.y += 0.15;
            ring.material.opacity *= 0.96;

            if (ring.material.opacity > 0.01) {
                requestAnimationFrame(expandRing);
            } else {
                this.scene.remove(ring);
            }
        };
        expandRing();
    }

    // 화염 기둥 효과 (크기와 수 감소)
    const fireColumn = new THREE.Group();
    for (let i = 0; i < 10; i++) { // 20에서 10으로 감소
        const fireGeometry = new THREE.ConeGeometry(1, 4, 8); // 크기 감소
        const fireMaterial = new THREE.MeshBasicMaterial({
            color: 0xff4500,
            transparent: true,
            opacity: 0.8
        });
        const fire = new THREE.Mesh(fireGeometry, fireMaterial);
        fire.position.y = i * 0.3; // 0.5에서 0.3으로 감소
        fire.rotation.x = Math.random() * Math.PI;
        fire.rotation.z = Math.random() * Math.PI;
        fireColumn.add(fire);
    }
    fireColumn.position.copy(this.mesh.position);
    this.scene.add(fireColumn);

    // 화염 기둥 애니메이션 (확장 속도 감소)
    const animateFireColumn = () => {
        fireColumn.scale.y += 0.05; // 0.1에서 0.05로 감소
        fireColumn.children.forEach(fire => {
            fire.material.opacity *= 0.95;
        });

        if (fireColumn.children[0].material.opacity > 0.01) {
            requestAnimationFrame(animateFireColumn);
        } else {
            this.scene.remove(fireColumn);
        }
    };
    animateFireColumn();

    // 폭발 사운드 효과
    const explosionSounds = [
        new Audio('sounds/explosion.ogg'),
        new Audio('sounds/bang.ogg')
    ];
    explosionSounds.forEach(sound => {
        sound.volume = 0.5;
        sound.play();
    });

    // 카메라 흔들림 효과 (강도 감소)
    if (window.gameInstance && window.gameInstance.camera) {
        const camera = window.gameInstance.camera;
        const originalPosition = camera.position.clone();
        let shakeTime = 0;
        const shakeIntensity = 0.5; // 1.0에서 0.5로 감소
        const shakeDuration = 500; // 1000에서 500으로 감소

        const shakeCamera = () => {
            if (shakeTime < shakeDuration) {
                camera.position.x = originalPosition.x + (Math.random() - 0.5) * shakeIntensity;
                camera.position.y = originalPosition.y + (Math.random() - 0.5) * shakeIntensity;
                camera.position.z = originalPosition.z + (Math.random() - 0.5) * shakeIntensity;

                shakeTime += 16;
                requestAnimationFrame(shakeCamera);
            } else {
                camera.position.copy(originalPosition);
            }
        };
        shakeCamera();
    }

    // 중심 플래시 제거
    setTimeout(() => {
        this.scene.remove(flash);
    }, 100); // 200에서 100으로 감소
}


   shoot(playerPosition) {
    const currentTime = Date.now();
    const attackInterval = this.type === 'tank' ? 
        ENEMY_CONFIG.ATTACK_INTERVAL : 
        ENEMY_CONFIG.ATTACK_INTERVAL * 1.5;

    if (currentTime - this.lastAttackTime < attackInterval) return;

    // 플레이어와의 방향 차이 계산
    const directionToPlayer = new THREE.Vector3()
        .subVectors(playerPosition, this.mesh.position)
        .normalize();
    const forwardDirection = new THREE.Vector3(0, 0, 1)
        .applyQuaternion(this.mesh.quaternion)
        .normalize();

    const dotProduct = forwardDirection.dot(directionToPlayer);
    const angleToPlayer = Math.acos(dotProduct);

    // 일정 각도 이하일 경우에만 공격
    const attackAngleThreshold = Math.PI / 8; // 약 22.5도
    if (angleToPlayer > attackAngleThreshold) return;

    this.createMuzzleFlash();

    const enemyFireSound = new Audio('sounds/mbtfire5.ogg');
    enemyFireSound.volume = 0.3;
    enemyFireSound.play();

    const bulletGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2, 8);
    const bulletMaterial = new THREE.MeshBasicMaterial({ 
        color: 0xff0000,
        emissive: 0xff0000,
        emissiveIntensity: 0.5
    });
    const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);

    const muzzleOffset = new THREE.Vector3(0, 0.5, 4);
    const muzzlePosition = new THREE.Vector3();
    this.mesh.getWorldPosition(muzzlePosition);
    muzzleOffset.applyQuaternion(this.mesh.quaternion);
    muzzlePosition.add(muzzleOffset);
    
    bullet.position.copy(muzzlePosition);
    bullet.quaternion.copy(this.mesh.quaternion);
    
    const direction = new THREE.Vector3()
        .subVectors(playerPosition, muzzlePosition)
        .normalize();
    
    const bulletSpeed = this.type === 'tank' ? 
        ENEMY_CONFIG.BULLET_SPEED : 
        ENEMY_CONFIG.BULLET_SPEED * 0.8;
    
    bullet.velocity = direction.multiplyScalar(bulletSpeed);
    
    const trailGeometry = new THREE.CylinderGeometry(0.1, 0.1, 1, 8);
    const trailMaterial = new THREE.MeshBasicMaterial({
        color: 0xff4444,
        transparent: true,
        opacity: 0.5
    });
    
    const trail = new THREE.Mesh(trailGeometry, trailMaterial);
    trail.position.z = -1;
    bullet.add(trail);
    
    this.scene.add(bullet);
    this.bullets.push(bullet);
    this.lastAttackTime = currentTime;
}

    takeDamage(damage) {
    this.health -= damage;

    // 사망 여부 체크
    if (this.health <= 0) {
        const deathSound = new Audio('sounds/bang.ogg');
        deathSound.play();
        return true; // 사망
    }
    return false; // 생존
}
    destroy() {
        if (this.mesh) {
            this.scene.remove(this.mesh);
            this.bullets.forEach(bullet => this.scene.remove(bullet));
            this.bullets = [];
            this.isLoaded = false;
        }
    }
}

// Particle 클래스
class Particle {
    constructor(scene, position) {
        const geometry = new THREE.SphereGeometry(0.1);
        const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        this.mesh = new THREE.Mesh(geometry, material);
        this.mesh.position.copy(position);
        
        this.velocity = new THREE.Vector3(
            (Math.random() - 0.5) * 0.3,
            Math.random() * 0.2,
            (Math.random() - 0.5) * 0.3
        );
        
        this.gravity = -0.01;
        this.lifetime = 60;
        this.age = 0;
        
        scene.add(this.mesh);
    }

    update() {
        this.velocity.y += this.gravity;
        this.mesh.position.add(this.velocity);
        this.age++;
        return this.age < this.lifetime;
    }

    destroy(scene) {
        scene.remove(this.mesh);
    }
}

// Game 클래스
class Game {
    constructor() {
        // 게임 시작 여부를 추적하는 플래그 추가
        this.isStarted = false;
        // 오디오 관련 속성 추가
        this.bgmPlaying = false; // BGM 재생 상태 추적
        this.bgm = null; // BGM 오디오 객체 저장
        this.engineSound = null;
        this.engineStopSound = null;
        this.isEngineRunning = false;
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 부드러운 그림자
        this.renderer.outputColorSpace = THREE.SRGBColorSpace;
        this.enemyLabels = new Map(); // 적 라벨을 추적하기 위한 Map 추가
        this.raycaster = new THREE.Raycaster();
        this.crosshair = document.getElementById('crosshair');
        document.getElementById('gameContainer').appendChild(this.renderer.domElement);
        

        // 레이더 관련 속성 추가
        this.radarUpdateInterval = 100; // 100ms마다 레이더 업데이트
        this.lastRadarUpdate = 0;
        this.radarRange = 200; // 레이더 감지 범위

        this.tank = new TankPlayer();
        this.enemies = [];
        this.particles = [];
        this.buildings = [];
        this.loader = new GLTFLoader();
        this.controls = null;
        this.gameTime = GAME_DURATION;
        this.score = 0;
        this.isGameOver = false;
        this.isLoading = true;
        this.previousTankPosition = new THREE.Vector3();
        this.lastTime = performance.now();
        this.gameTimer = null;
        this.animationFrameId = null;
        this.lastAudio = null; // 마지막 발사음 추적을 위한 속성 추가

        this.mouse = { x: 0, y: 0 };
        this.keys = {
            forward: false,
            backward: false,
            left: false,
            right: false
        };

        this.setupEventListeners();
        this.initialize();
        this.obstacles = []; // obstacles 배열 추가
    }
        setupScene() {
        // 씬 초기화
        this.scene.background = new THREE.Color(0x87CEEB); // 하늘색 배경
        
        // 안개 설정
        this.scene.fog = new THREE.FogExp2(0x87CEEB, 0.0008);
        
        // 렌더러 설정
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.setPixelRatio(window.devicePixelRatio);
        
        // 카메라 초기 설정
        this.camera.position.set(0, 15, -30);
        this.camera.lookAt(0, 0, 0);
        
        // 씬 경계 설정
        const mapBoundary = MAP_SIZE / 2;
        this.sceneBounds = {
            minX: -mapBoundary,
            maxX: mapBoundary,
            minZ: -mapBoundary,
            maxZ: mapBoundary
        };
    }
    
      async initialize() {
    try {
        // BGM이 아직 재생되지 않은 경우에만 재생
        if (!this.bgmPlaying && !this.bgm) {
            this.bgm = new Audio('sounds/BGM.ogg');
            this.bgm.volume = 0.5;
            this.bgm.loop = true;
            this.bgm.play();
            this.bgmPlaying = true;
        }
      
        // 시작 사운드 재생
        const startSounds = ['sounds/start1.ogg', 'sounds/start2.ogg', 'sounds/start3.ogg'];
        const randomStartSound = startSounds[Math.floor(Math.random() * startSounds.length)];
        const startAudio = new Audio(randomStartSound);
        startAudio.volume = 0.5;
        startAudio.play();
        
        // 렌더러 설정
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.outputColorSpace = THREE.SRGBColorSpace;

        // 기본 씬 설정
        this.setupScene();
        
        // 안개 효과
        this.scene.fog = new THREE.FogExp2(0x87CEEB, 0.0008);
        this.scene.background = new THREE.Color(0x87CEEB);

        // 조명 설정
        // 주변광
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
        this.scene.add(ambientLight);

        // 메인 태양광
        const mainLight = new THREE.DirectionalLight(0xffffff, 1.0);
        mainLight.position.set(MAP_SIZE/2, MAP_SIZE/2, MAP_SIZE/2);
        mainLight.castShadow = true;

        // 그림자 설정
        mainLight.shadow.mapSize.width = 4096;
        mainLight.shadow.mapSize.height = 4096;
        mainLight.shadow.camera.near = 0.5;
        mainLight.shadow.camera.far = MAP_SIZE * 2;
        mainLight.shadow.camera.left = -MAP_SIZE;
        mainLight.shadow.camera.right = MAP_SIZE;
        mainLight.shadow.camera.top = MAP_SIZE;
        mainLight.shadow.camera.bottom = -MAP_SIZE;
        mainLight.shadow.bias = -0.001;
        mainLight.shadow.radius = 2;
        mainLight.shadow.normalBias = 0.02;

        this.scene.add(mainLight);

        // 보조 태양광
        const secondaryLight = new THREE.DirectionalLight(0xffffff, 0.3);
        secondaryLight.position.set(-50, 50, -50);
        this.scene.add(secondaryLight);

        // 환경광
        const hemisphereLight = new THREE.HemisphereLight(
            0x87CEEB,
            0xFFE87C,
            0.3
        );
        this.scene.add(hemisphereLight);
        // 지형 생성
        const groundGeometry = new THREE.PlaneGeometry(MAP_SIZE, MAP_SIZE, 100, 100);
        const groundMaterial = new THREE.MeshStandardMaterial({
            color: 0xD2B48C,
            roughness: 0.8,
            metalness: 0.2,
            envMapIntensity: 1.0
        });
        
        const ground = new THREE.Mesh(groundGeometry, groundMaterial);
        ground.rotation.x = -Math.PI / 2;
        ground.receiveShadow = true;
        
        // 지형 높이 설정
        const vertices = ground.geometry.attributes.position.array;
        for (let i = 0; i < vertices.length; i += 3) {
            vertices[i + 2] = 0;  // 모든 높이를 0으로 설정
        }
        
        ground.geometry.attributes.position.needsUpdate = true;
        ground.geometry.computeVertexNormals();
        this.ground = ground;
        this.scene.add(ground);
        
        // 격자 효과 추가
        const gridHelper = new THREE.GridHelper(MAP_SIZE, 50, 0x000000, 0x000000);
        gridHelper.material.opacity = 0.1;
        gridHelper.material.transparent = true;
        gridHelper.position.y = 0.1;
        this.scene.add(gridHelper);
        
        // 사막 장식 추가
        await this.addDesertDecorations();
        
        // 탱크 초기화
        await this.tank.initialize(this.scene, this.loader);
        if (!this.tank.isLoaded) {
            throw new Error('Tank loading failed');
        }
        
        // 스폰 위치 검증
        const spawnPos = this.findValidSpawnPosition();
        const heightAtSpawn = this.getHeightAtPosition(spawnPos.x, spawnPos.z);
        const slopeCheckPoints = [
            { x: spawnPos.x + 2, z: spawnPos.z },
            { x: spawnPos.x - 2, z: spawnPos.z },
            { x: spawnPos.x, z: spawnPos.z + 2 },
            { x: spawnPos.x, z: spawnPos.z - 2 }
        ];
        
        const slopes = slopeCheckPoints.map(point => {
            const pointHeight = this.getHeightAtPosition(point.x, point.z);
            return Math.abs(pointHeight - heightAtSpawn) / 2;
        });
        
        const maxSlope = Math.max(...slopes);
        if (maxSlope > 0.3) {
            location.reload();
            return;
        }
        
        // 카메라 초기 설정
        const tankPosition = this.tank.getPosition();
        this.camera.position.set(
            tankPosition.x,
            tankPosition.y + 15,
            tankPosition.z - 30
        );
        this.camera.lookAt(tankPosition);
        
        // 로딩 완료 처리
        this.isLoading = false;
        document.getElementById('loading').style.display = 'none';
        
        // 게임 시작
        this.animate();
        this.spawnEnemies();
        this.startGameTimer();
        
        } catch (error) {
            console.error('Game initialization error:', error);
            this.handleLoadingError();
        }
      }

    // 레이더 업데이트 메서드 추가
    updateRadar() {
        const currentTime = Date.now();
        if (currentTime - this.lastRadarUpdate < this.radarUpdateInterval) return;
        
        const radar = document.getElementById('radar');
        const radarRect = radar.getBoundingClientRect();
        const radarCenter = {
            x: radarRect.width / 2,
            y: radarRect.height / 2
        };

        // 기존 적 도트 제거
        const oldDots = radar.getElementsByClassName('enemy-dot');
        while (oldDots[0]) {
            oldDots[0].remove();
        }

        // 탱크 위치 가져오기
        const tankPos = this.tank.getPosition();

        // 모든 적에 대해 레이더에 표시
        this.enemies.forEach(enemy => {
            if (!enemy.mesh || !enemy.isLoaded) return;

            const enemyPos = enemy.mesh.position;
            const distance = tankPos.distanceTo(enemyPos);

            // 레이더 범위 내에 있는 경우만 표시
            if (distance <= this.radarRange) {
                // 탱크 기준 상대 각도 계산
                const angle = Math.atan2(
                    enemyPos.x - tankPos.x,
                    enemyPos.z - tankPos.z
                );

                // 상대 거리를 레이더 크기에 맞게 스케일링
                const relativeDistance = distance / this.radarRange;
                const dotX = radarCenter.x + Math.sin(angle) * (radarCenter.x * relativeDistance);
                const dotY = radarCenter.y + Math.cos(angle) * (radarCenter.y * relativeDistance);

                // 적 도트 생성 및 추가
                const dot = document.createElement('div');
                dot.className = 'enemy-dot';
                dot.style.left = `${dotX}px`;
                dot.style.top = `${dotY}px`;
                radar.appendChild(dot);
            }
        });

        this.lastRadarUpdate = currentTime;
    }

   async addDesertDecorations() {
    if (!this.obstacles) {
        this.obstacles = [];
    }

    const BUILDING_COUNT = 25;
    const buildingModels = [
        'models/house1.glb',
        'models/house2.glb',
        'models/house3.glb',
        'models/house4.glb'
    ];

    // 충돌 박스 시각화를 위한 재질
    const collisionBoxMaterial = new THREE.LineBasicMaterial({
        color: 0xff0000,
        linewidth: 2
    });

    // 플레이어 충돌 반경 및 최소 거리 계산
    const playerCollisionRadius = 2; // 플레이어 충돌 반경 (탱크의 크기 기준)
    const clearanceBuffer = 1; // 여유 공간
    const minimumDistance = playerCollisionRadius * 2 + clearanceBuffer; // 건물 간 최소 거리

    for (let i = 0; i < BUILDING_COUNT; i++) {
        try {
            const modelPath = buildingModels[Math.floor(Math.random() * buildingModels.length)];
            const result = await this.loader.loadAsync(modelPath);
            const building = result.scene;

            let x, z;
            const edgeSpawn = Math.random() < 0.7;

            if (edgeSpawn) {
                if (Math.random() < 0.5) {
                    x = (Math.random() < 0.5 ? -1 : 1) * (MAP_SIZE * 0.4 + Math.random() * MAP_SIZE * 0.1);
                    z = (Math.random() - 0.5) * MAP_SIZE * 0.9;
                } else {
                    x = (Math.random() - 0.5) * MAP_SIZE * 0.9;
                    z = (Math.random() < 0.5 ? -1 : 1) * (MAP_SIZE * 0.4 + Math.random() * MAP_SIZE * 0.1);
                }
            } else {
                x = (Math.random() - 0.5) * MAP_SIZE * 0.6;
                z = (Math.random() - 0.5) * MAP_SIZE * 0.6;
            }

            building.position.set(x, 0, z);
            building.rotation.y = Math.random() * Math.PI * 2;
            building.scale.set(1, 1, 1);

            // 그림자 설정
            building.traverse((child) => {
                if (child.isMesh) {
                    child.castShadow = true;
                    child.receiveShadow = true;
                }
            });

            // 충돌 박스 생성 및 시각화
            const boundingBox = new THREE.Box3().setFromObject(building);
            const boxSize = boundingBox.getSize(new THREE.Vector3());

            // 충돌 박스의 와이어프레임 생성
            const boxGeometry = new THREE.BufferGeometry();
            const positions = new Float32Array([
                // 바닥 사각형
                -boxSize.x / 2, 0.1, -boxSize.z / 2,
                -boxSize.x / 2, 0.1, boxSize.z / 2,
                boxSize.x / 2, 0.1, boxSize.z / 2,
                boxSize.x / 2, 0.1, -boxSize.z / 2,
                -boxSize.x / 2, 0.1, -boxSize.z / 2
            ]);

            boxGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            const collisionBoxLine = new THREE.Line(boxGeometry, collisionBoxMaterial);
            collisionBoxLine.position.copy(building.position);
            collisionBoxLine.rotation.y = building.rotation.y;

            // 충돌 데이터 설정
            building.userData.isCollidable = true;
            building.userData.type = 'building';
            building.userData.collisionBox = collisionBoxLine;

            let tooClose = false;
            for (const obstacle of this.obstacles) {
                const distance = building.position.distanceTo(obstacle.position);
                if (distance < minimumDistance) { // 최소 거리 조건 추가
                    tooClose = true;
                    break;
                }
            }

            if (!tooClose) {
                this.obstacles.push(building);
                this.scene.add(building);
                this.scene.add(collisionBoxLine); // 충돌 박스 라인 추가
            }

        } catch (error) {
            console.error('Error loading building model:', error);
        }
    }

    // 선인장 추가 (기존 코드 유지)
    const cactusGeometry = new THREE.CylinderGeometry(0.5, 0.7, 4, 8);
    const cactusMaterial = new THREE.MeshStandardMaterial({
        color: 0x2F4F2F,
        roughness: 0.8
    });

    for (let i = 0; i < 50; i++) {
        const cactus = new THREE.Mesh(cactusGeometry, cactusMaterial);
        cactus.position.set(
            (Math.random() - 0.5) * MAP_SIZE * 0.8,
            2,
            (Math.random() - 0.5) * MAP_SIZE * 0.8
        );
        cactus.castShadow = true;
        cactus.receiveShadow = true;
        cactus.userData.isCollidable = false;
        cactus.userData.type = 'cactus';

        this.scene.add(cactus);
    }
}



   getHeightAtPosition(x, z) {
    return 0; // 항상 높이 0 반환
}

    findValidSpawnPosition() {
        const margin = 50;
        let position;
        let attempts = 0;
        const maxAttempts = 50;
        const maxSlope = 0.3; // 최대 허용 경사

        while (attempts < maxAttempts) {
            position = new THREE.Vector3(
                (Math.random() - 0.5) * (MAP_SIZE - margin * 2),
                0,
                (Math.random() - 0.5) * (MAP_SIZE - margin * 2)
            );

            // 현재 위치의 높이 가져오기
            const height = this.getHeightAtPosition(position.x, position.z);
            position.y = height + TANK_HEIGHT;

            // 주변 지형의 경사 체크
            const checkPoints = [
                { x: position.x + 2, z: position.z },
                { x: position.x - 2, z: position.z },
                { x: position.x, z: position.z + 2 },
                { x: position.x, z: position.z - 2 }
            ];

            const slopes = checkPoints.map(point => {
                const pointHeight = this.getHeightAtPosition(point.x, point.z);
                return Math.abs(pointHeight - height) / 2;
            });

            const maxCurrentSlope = Math.max(...slopes);

            if (maxCurrentSlope <= maxSlope) {
                return position;
            }

            attempts++;
        }

        // 실패 시 기본 위치 반환
        return new THREE.Vector3(0, TANK_HEIGHT, 0);
    }

   setupEventListeners() {
       document.addEventListener('keydown', (event) => {
           if (this.isLoading || this.isGameOver) return;
           switch(event.code) {
               case 'KeyW': this.keys.forward = true; break;
               case 'KeyS': this.keys.backward = true; break;
               case 'KeyA': this.keys.left = true; break;
               case 'KeyD': this.keys.right = true; break;
           }
       });

       document.addEventListener('keyup', (event) => {
           if (this.isLoading || this.isGameOver) return;
           switch(event.code) {
               case 'KeyW': this.keys.forward = false; break;
               case 'KeyS': this.keys.backward = false; break;
               case 'KeyA': this.keys.left = false; break;
               case 'KeyD': this.keys.right = false; break;
           }
       });

       document.addEventListener('mousemove', (event) => {
           if (this.isLoading || this.isGameOver || !document.pointerLockElement) return;

           const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
           this.mouse.x += movementX * 0.002;
           this.mouse.y = 0;

           while (this.mouse.x > Math.PI) this.mouse.x -= Math.PI * 2;
           while (this.mouse.x < -Math.PI) this.mouse.x += Math.PI * 2;
       });

       document.addEventListener('click', () => {
    if (!document.pointerLockElement) {
        document.body.requestPointerLock();
    } else if (!this.isGameOver && this.tank && this.tank.isLoaded) {
        const bullet = this.tank.shoot(this.scene);
        if (bullet) {
            // Shooting effects...
        }
    }
});

       document.addEventListener('pointerlockchange', () => {
           if (!document.pointerLockElement) {
               this.mouse.x = 0;
               this.mouse.y = 0;
           }
       });

       window.addEventListener('resize', () => {
           this.camera.aspect = window.innerWidth / window.innerHeight;
           this.camera.updateProjectionMatrix();
           this.renderer.setSize(window.innerWidth, window.innerHeight);
       });
   }
  handleMovement() {
       if (!this.tank.isLoaded || this.isGameOver) return;

       const direction = new THREE.Vector3();
      const isMoving = this.keys.forward || this.keys.backward;
       // 이동 시작할 때 사운드 처리
    if (isMoving && !this.isEngineRunning) {
        this.isEngineRunning = true;
        
        // 이전 사운드 정지
        if (this.engineStopSound) {
            this.engineStopSound.pause();
        }
        if (this.engineSound) {
            this.engineSound.pause();
        }
        
        // 엔진 정지 사운드 재생
        this.engineStopSound = new Audio('sounds/engine.ogg');
        this.engineStopSound.play();
        
        // 엔진 정지 사운드 종료 후 엔진 사운드 시작
        this.engineStopSound.onended = () => {
            this.engineSound = new Audio('sounds/engine.ogg');
            this.engineSound.loop = true;
            this.engineSound.play();
        };
    }
    // 이동 멈출 때 사운드 처리
    else if (!isMoving && this.isEngineRunning) {
        this.isEngineRunning = false;
        if (this.engineSound) {
            this.engineSound.pause();
            this.engineSound = null;
        }
        if (this.engineStopSound) {
            this.engineStopSound.pause();
            this.engineStopSound = null;
        }
        const stopSound = new Audio('sounds/enginestop.ogg');
        stopSound.play();
    }


       // 차체 이동과 회전은 유지
       if (this.keys.forward) direction.z += 1;
       if (this.keys.backward) direction.z -= 1;
       if (this.keys.left) this.tank.rotate(-1);
       if (this.keys.right) this.tank.rotate(1);

       if (direction.length() > 0) {
           direction.normalize();
           direction.applyEuler(this.tank.body.rotation);
           this.tank.move(direction);
       }

       // 탱크 위치 가져오기
       const tankPos = this.tank.getPosition();
       
       // 카메라는 마우스 X 회전에만 따라감
       const cameraDistance = 15;
       const cameraHeight = 8;
       const cameraAngle = this.mouse.x + Math.PI; // 항상 포탑의 뒤쪽에 위치
       
       const cameraX = tankPos.x + Math.sin(cameraAngle) * cameraDistance;
       const cameraZ = tankPos.z + Math.cos(cameraAngle) * cameraDistance;

       this.camera.position.set(
           cameraX,
           tankPos.y + cameraHeight,
           cameraZ
       );

       // 카메라가 탱크를 바라보도록 설정
       const lookAtPoint = new THREE.Vector3(
           tankPos.x,
           tankPos.y + 1,
           tankPos.z
       );
       this.camera.lookAt(lookAtPoint);
   }

   createBuildings() {
       const buildingTypes = [
           { width: 10, height: 30, depth: 10, color: 0x808080 },
           { width: 15, height: 40, depth: 15, color: 0x606060 },
           { width: 20, height: 50, depth: 20, color: 0x404040 }
       ];

       for (let i = 0; i < BUILDING_COUNT; i++) {
           const type = buildingTypes[Math.floor(Math.random() * buildingTypes.length)];
           const building = this.createBuilding(type);
           
           let position;
           let attempts = 0;
           do {
               position = new THREE.Vector3(
                   (Math.random() - 0.5) * (MAP_SIZE - type.width),
                   type.height / 2,
                   (Math.random() - 0.5) * (MAP_SIZE - type.depth)
               );
               attempts++;
           } while (this.checkBuildingCollision(position, type) && attempts < 50);

           if (attempts < 50) {
               building.position.copy(position);
               this.buildings.push(building);
               this.scene.add(building);
           }
       }
       return Promise.resolve();
   }

   createBuilding(type) {
       const geometry = new THREE.BoxGeometry(type.width, type.height, type.depth);
       const material = new THREE.MeshPhongMaterial({ 
           color: type.color,
           emissive: 0x222222,
           specular: 0x111111,
           shininess: 30
       });
       const building = new THREE.Mesh(geometry, material);
       building.castShadow = true;
       building.receiveShadow = true;
       return building;
   }
  checkBuildingCollision(position, type) {
       const margin = 5;
       const bbox = new THREE.Box3(
           new THREE.Vector3(
               position.x - (type.width / 2 + margin),
               0,
               position.z - (type.depth / 2 + margin)
           ),
           new THREE.Vector3(
               position.x + (type.width / 2 + margin),
               type.height,
               position.z + (type.depth / 2 + margin)
           )
       );

       return this.buildings.some(building => {
           const buildingBox = new THREE.Box3().setFromObject(building);
           return bbox.intersectsBox(buildingBox);
       });
   }

   handleLoadingError() {
       this.isLoading = false;
       const loadingElement = document.getElementById('loading');
       if (loadingElement) {
           loadingElement.innerHTML = `
               <div class="loading-text" style="color: red;">
                   Loading failed. Please refresh the page.
               </div>
           `;
       }
   }

   startGameTimer() {
    if (this.gameTimer) {
        clearInterval(this.gameTimer);
    }
    
    this.gameTimer = setInterval(() => {
        if (this.isLoading || this.isGameOver) {
            clearInterval(this.gameTimer);
            return;
        }
        
        this.gameTime--;
        document.getElementById('time').textContent = `Time: ${this.gameTime}s`;
        
        if (this.gameTime <= 0) {
            clearInterval(this.gameTimer);
            this.endGame(true); // 승리 조건으로 endGame 호출
        }
    }, 1000);
}


   spawnEnemies() {
       const spawnEnemy = () => {
           if (this.enemies.length < 3 && !this.isGameOver) {  // 최대 3대로 제한
               const position = this.getValidEnemySpawnPosition();
               if (position) {
                   const type = Math.random() < 0.7 ? 'tank' : 'heavy';
                   const enemy = new Enemy(this.scene, position, type);
                   enemy.initialize(this.loader);
                   this.enemies.push(enemy);
               }
           }
           if (!this.isGameOver) {
               setTimeout(spawnEnemy, 10000);  // 10초마다 스폰
           }
       };
       
       spawnEnemy();
   }

   getValidEnemySpawnPosition() {
    const margin = 50;
    let position;
    let attempts = 0;
    const maxAttempts = 50;
    const maxSlope = 0.3;

    do {
        position = new THREE.Vector3(
            (Math.random() - 0.5) * (MAP_SIZE - margin * 2),
            0,
            (Math.random() - 0.5) * (MAP_SIZE - margin * 2)
        );

        const height = this.getHeightAtPosition(position.x, position.z);
        position.y = height + TANK_HEIGHT;

        // 주변 경사 체크
        const checkPoints = [
            { x: position.x + 2, z: position.z },
            { x: position.x - 2, z: position.z },
            { x: position.x, z: position.z + 2 },
            { x: position.x, z: position.z - 2 }
        ];

        const slopes = checkPoints.map(point => {
            const pointHeight = this.getHeightAtPosition(point.x, point.z);
            return Math.abs(pointHeight - height) / 2;
        });

        const maxCurrentSlope = Math.max(...slopes);

        // 플레이어와의 거리 체크
        const distanceToPlayer = position.distanceTo(this.tank.getPosition());
        if (distanceToPlayer > 100 && maxCurrentSlope <= maxSlope) {
            return position;
        }

        attempts++;
    } while (attempts < maxAttempts);

    return null;
}
  updateParticles() {
    for (let i = this.particles.length - 1; i >= 0; i--) {
        const particle = this.particles[i];
        
        // 중력 적용
        particle.velocity.y += particle.gravity;
        particle.mesh.position.add(particle.velocity);
        
        // 투명도 감소
        particle.mesh.material.opacity -= particle.fadeRate;
        particle.life--;

        // 파티클 제거
        if (particle.life <= 0 || particle.mesh.material.opacity <= 0) {
            this.scene.remove(particle.mesh);
            this.particles.splice(i, 1);
        }
    }
}

   createExplosion(position) {
       for (let i = 0; i < PARTICLE_COUNT; i++) {
           this.particles.push(new Particle(this.scene, position));
       }
   }

   checkCollisions() {
    if (this.isLoading || !this.tank.isLoaded) return;
     
    // 명중 사운드 배열 정의
    const hitSounds = [
        'sounds/hit1.ogg', 'sounds/hit2.ogg', 'sounds/hit3.ogg',
        'sounds/hit4.ogg', 'sounds/hit5.ogg', 'sounds/hit6.ogg', 'sounds/hit7.ogg'
    ];
    
    // 피격 사운드 배열 정의
    const beatSounds = ['sounds/beat1.ogg', 'sounds/beat2.ogg', 'sounds/beat3.ogg'];

    const tankPosition = this.tank.getPosition();
    const tankBoundingBox = new THREE.Box3().setFromObject(this.tank.body);
     // 이전 위치를 저장
    const previousPosition = this.tank.body.position.clone();

    // 충돌 검사
    this.obstacles.forEach(obstacle => {
        if (obstacle.userData.isCollidable) {
            const obstacleBoundingBox = new THREE.Box3().setFromObject(obstacle);
            const tankBoundingBox = new THREE.Box3().setFromObject(this.tank.body);

            if (tankBoundingBox.intersectsBox(obstacleBoundingBox)) {
                // 충돌한 방향으로의 이동만 차단
                const collisionNormal = new THREE.Vector3()
                    .subVectors(this.tank.body.position, obstacle.position)
                    .normalize();

                const correctionVector = collisionNormal.multiplyScalar(0.5); // 충돌 방향으로 밀기
                this.tank.body.position.add(correctionVector);

                // 이전 위치 저장
                this.previousTankPosition.copy(previousPosition);
            }
        }
    });
//}
        // 적 탱크와 장애물 충돌 체크 (추가)
    this.enemies.forEach(enemy => {
        if (!enemy.mesh || !enemy.isLoaded) return;
        
        const enemyBoundingBox = new THREE.Box3().setFromObject(enemy.mesh);
        const enemyPreviousPosition = enemy.mesh.position.clone();
        
        this.obstacles.forEach(obstacle => {
            const obstacleBoundingBox = new THREE.Box3().setFromObject(obstacle);
            if (enemyBoundingBox.intersectsBox(obstacleBoundingBox)) {
                enemy.mesh.position.copy(enemyPreviousPosition);
            }
        });
    });

    // 적 총알과 플레이어 탱크 충돌 체크
    this.enemies.forEach(enemy => {
    if (!enemy.mesh || !enemy.isLoaded) return;

    enemy.bullets.forEach((bullet, bulletIndex) => {
        // 플레이어 탱크의 바운딩 박스 생성
        const tankBox = new THREE.Box3().setFromObject(this.tank.body);
       // 바운딩 박스 크기 조정 (1.5배로 수정)
        tankBox.min.x -= 0.75;
        tankBox.max.x += 0.75;
        
        // 총알의 바운딩 박스 생성
        const bulletBox = new THREE.Box3().setFromObject(bullet);

        if (bulletBox.intersectsBox(tankBox)) {
            const randomBeatSound = beatSounds[Math.floor(Math.random() * beatSounds.length)];
            const beatAudio = new Audio(randomBeatSound);
            beatAudio.play();

            if (this.tank.takeDamage(250)) {
                this.endGame();
            }
            
            this.tank.createExplosionEffect(this.scene, bullet.position);
            this.scene.remove(bullet);
            enemy.bullets.splice(bulletIndex, 1);
            
            document.getElementById('health').style.width = 
                `${(this.tank.health / MAX_HEALTH) * 100}%`;
        }
    });
});
    // 플레이어 포탄
    // 포탄과 장애물 충돌 체크
for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
    const bullet = this.tank.bullets[i];
    const bulletBox = new THREE.Box3().setFromObject(bullet);

    for (const obstacle of this.obstacles) {
        if (obstacle.userData.isCollidable) { // 충돌 가능한 객체만 검사
            const obstacleBox = new THREE.Box3().setFromObject(obstacle);
            if (bulletBox.intersectsBox(obstacleBox)) {
                // 폭발 이펙트 생성
                this.tank.createExplosionEffect(this.scene, bullet.position);
                
                // 포탄 제거
                this.scene.remove(bullet);
                this.tank.bullets.splice(i, 1);
                break;
            }
        }
    }
}

    // 적 탱크와 장애물 충돌 체크
this.enemies.forEach(enemy => {
    if (!enemy.mesh || !enemy.isLoaded) return;

    enemy.bullets.forEach((bullet, bulletIndex) => {
        const distance = bullet.position.distanceTo(tankPosition);
        if (distance < 1) {
            // 피격 사운드 재생
            const randomBeatSound = beatSounds[Math.floor(Math.random() * beatSounds.length)];
            const beatAudio = new Audio(randomBeatSound);
            beatAudio.play();

            if (this.tank.takeDamage(250)) {
                this.endGame();
            }
            
            // 기존의 createExplosion 대신 createExplosionEffect 사용
            this.tank.createExplosionEffect(this.scene, bullet.position);
            
            this.scene.remove(bullet);
            enemy.bullets.splice(bulletIndex, 1);
            
            document.getElementById('health').style.width = 
                `${(this.tank.health / MAX_HEALTH) * 100}%`;
        }
    });
});


    // 플레이어 총알과 적 충돌 체크
    for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
    const bullet = this.tank.bullets[i];
    for (let j = this.enemies.length - 1; j >= 0; j--) {
        const enemy = this.enemies[j];
        if (!enemy.mesh || !enemy.isLoaded) continue;

        // 적 전차의 바운딩 박스 생성
        const enemyBox = new THREE.Box3().setFromObject(enemy.mesh);
        // 바운딩 박스 크기 조정 (폭을 2배로)
        enemyBox.min.x -= 0.75; // 2에서 1.5로 수정
        enemyBox.max.x += 0.75;
        
        // 총알의 바운딩 박스 생성
        const bulletBox = new THREE.Box3().setFromObject(bullet);

        // 박스 충돌 검사
        if (bulletBox.intersectsBox(enemyBox)) {
            const randomHitSound = hitSounds[Math.floor(Math.random() * hitSounds.length)];
            const hitAudio = new Audio(randomHitSound);
            hitAudio.play();

            if (enemy.takeDamage(50)) {
                enemy.createMassiveExplosion(); // 추가
                enemy.destroy();
                this.enemies.splice(j, 1);
                this.score += 100;
                document.getElementById('score').textContent = `Score: ${this.score}`;
            }
            
            this.tank.createExplosionEffect(this.scene, bullet.position);
            this.scene.remove(bullet);
            this.tank.bullets.splice(i, 1);
            break;
        }
    }
}

    // 플레이어 탱크와 적 전차 충돌 체크
    this.enemies.forEach(enemy => {
        if (!enemy.mesh || !enemy.isLoaded) return;
        
        const enemyBoundingBox = new THREE.Box3().setFromObject(enemy.mesh);
        if (tankBoundingBox.intersectsBox(enemyBoundingBox)) {
            this.tank.body.position.copy(this.previousTankPosition);
        }
    });

    // 이전 위치 저장
    this.previousTankPosition.copy(this.tank.body.position);
}
  endGame(isVictory = false) {
    if (this.isGameOver) return;

    this.isGameOver = true;

    // 모든 소리 정지
    if (this.bgm) {
        this.bgm.pause();
        this.bgm = null;
        this.bgmPlaying = false;
    }
    if (this.engineSound) {
        this.engineSound.pause();
        this.engineSound = null;
    }
    if (this.engineStopSound) {
        this.engineStopSound.pause();
        this.engineStopSound = null;
    }

    // 승리/패배 사운드 재생
    if (isVictory) {
        const victoryAudio = new Audio('sounds/victory.ogg');
        victoryAudio.volume = 0.5;
        victoryAudio.play();
    } else {
        const deathSounds = ['sounds/death1.ogg', 'sounds/death2.ogg'];
        const randomDeathSound = deathSounds[Math.floor(Math.random() * deathSounds.length)];
        const deathAudio = new Audio(randomDeathSound);
        deathAudio.play();
    }

    // 게임 타이머 및 애니메이션 정지
    if (this.gameTimer) {
        clearInterval(this.gameTimer);
    }
    if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
    }

    document.exitPointerLock();

    // 결과 화면 표시
    const gameOverDiv = document.createElement('div');
    gameOverDiv.style.position = 'absolute';
    gameOverDiv.style.top = '50%';
    gameOverDiv.style.left = '50%';
    gameOverDiv.style.transform = 'translate(-50%, -50%)';
    gameOverDiv.style.color = '#0f0';
    gameOverDiv.style.fontSize = '48px';
    gameOverDiv.style.backgroundColor = 'rgba(0, 20, 0, 0.7)';
    gameOverDiv.style.padding = '20px';
    gameOverDiv.style.borderRadius = '10px';
    gameOverDiv.style.textAlign = 'center';
    gameOverDiv.innerHTML = `
        ${isVictory ? 'Victory!' : 'Game Over'}<br>
        Score: ${this.score}<br>
        Time Survived: ${GAME_DURATION - this.gameTime}s<br>
        <button onclick="location.reload()" 
                style="font-size: 24px; padding: 10px; margin-top: 20px; 
                       cursor: pointer; background: #0f0; border: none; 
                       color: black; border-radius: 5px;">
            Play Again
        </button>
    `;
    document.body.appendChild(gameOverDiv);
}


   updateUI() {
       if (!this.isGameOver) {
           const healthBar = document.getElementById('health');
           if (healthBar) {
               healthBar.style.width = `${(this.tank.health / MAX_HEALTH) * 100}%`;
           }

           const timeElement = document.getElementById('time');
           if (timeElement) {
               timeElement.textContent = `Time: ${this.gameTime}s`;
           }

           const scoreElement = document.getElementById('score');
           if (scoreElement) {
               scoreElement.textContent = `Score: ${this.score}`;
           }
       }
   }
    // 크로스헤어 업데이트 메서드 추가
updateCrosshair() {
    // 화면 중앙에서 약간의 여유를 두고 레이캐스팅
    const raycasterDirection = new THREE.Vector2();
    this.raycaster.setFromCamera(raycasterDirection, this.camera);
    
    // detected 요소 가져오기
    const detectedText = document.getElementById('detected');
    
    // 적 전차의 바운딩 박스도 포함하여 검사
    const detectEnemy = this.enemies.some(enemy => {
        if (!enemy.mesh || !enemy.isLoaded) return false;
        
        // 적 전차의 바운딩 박스 생성
        const boundingBox = new THREE.Box3().setFromObject(enemy.mesh);
        const intersects = this.raycaster.ray.intersectsBox(boundingBox);

        // 공격 범위 내에 있는지 확인
        const inRange = enemy.mesh.position.distanceTo(this.tank.getPosition()) <= ENEMY_CONFIG.ATTACK_RANGE;
        
        // 바운딩 박스와의 교차 여부와 공격 범위 내 여부를 모두 확인
        return intersects && inRange;
    });
    
    if (detectEnemy) {
        this.crosshair.classList.add('target-detected');
        detectedText.style.display = 'block'; // DETECTED 텍스트 표시
    } else {
        this.crosshair.classList.remove('target-detected');
        detectedText.style.display = 'none'; // DETECTED 텍스트 숨기기
    }
}
  updateEnemyLabels() {
        const labelsContainer = document.getElementById('enemyLabels');
        
        // 기존 라벨 모두 제거
        labelsContainer.innerHTML = '';
        
        this.enemies.forEach((enemy, index) => {
            if (!enemy.mesh || !enemy.isLoaded) return;

            // 적 위치를 화면 좌표로 변환
            const enemyPosition = enemy.mesh.position.clone();
            enemyPosition.y += 5; // 적 머리 위에 표시하기 위해 높이 조정
            
            const screenPosition = enemyPosition.project(this.camera);
            
            // 화면에 보이는지 확인
            if (screenPosition.z > 1) return; // 카메라 뒤에 있는 경우
            
            // 적과 플레이어 사이의 거리 계산
            const distance = enemy.mesh.position.distanceTo(this.tank.getPosition());
            
            // 레이더 범위 내에 있는 경우에만 표시
            if (distance <= this.radarRange) {
                const x = (screenPosition.x + 1) / 2 * window.innerWidth;
                const y = (-screenPosition.y + 1) / 2 * window.innerHeight;
                
                // 라벨 생성
                const label = document.createElement('div');
                label.className = 'enemy-label';
                label.textContent = 'T-90';
                label.style.left = `${x}px`;
                label.style.top = `${y}px`;
                
                // 거리에 따른 투명도 조정
                const opacity = Math.max(0.2, 1 - (distance / this.radarRange));
                label.style.opacity = opacity;
                
                labelsContainer.appendChild(label);
            }
        });
    }

   animate() {
       if (this.isGameOver) {
           if (this.animationFrameId) {
               cancelAnimationFrame(this.animationFrameId);
           }
           return;
       }

       this.animationFrameId = requestAnimationFrame(() => this.animate());
           // 게임이 시작되지 않았으면 렌더링만 수행
        if (!this.isStarted) {
            this.renderer.render(this.scene, this.camera);
            return;
        }

       const currentTime = performance.now();
       const deltaTime = (currentTime - this.lastTime) / 1000;
       this.lastTime = currentTime;

       if (!this.isLoading) {
           this.handleMovement();
           this.tank.update(this.mouse.x, this.mouse.y, this.scene);
           
           const tankPosition = this.tank.getPosition();
           this.enemies.forEach(enemy => {
               enemy.update(tankPosition);
               
               if (enemy.isLoaded && enemy.mesh.position.distanceTo(tankPosition) < ENEMY_CONFIG.ATTACK_RANGE) {
                   enemy.shoot(tankPosition);
               }
           });
            this.updateEnemyLabels(); // 적 라벨 업데이트 추가
           this.updateParticles();
           this.checkCollisions();
           this.updateUI();
           this.updateRadar(); // 레이더 업데이트 추가
           // 크로스헤어 업데이트 추가
          this.updateCrosshair();
       }
       
       this.renderer.render(this.scene, this.camera);
   }
}

// Start game
window.startGame = function() {
    document.getElementById('startScreen').style.display = 'none';
    document.body.requestPointerLock();
    
    if (!window.gameInstance) {
        window.gameInstance = new Game();
    }
    
    // 게임 시작 설정
    window.gameInstance.isStarted = true;
    window.gameInstance.initialize();
};

// Initialize game
document.addEventListener('DOMContentLoaded', () => {
    // 게임 인스턴스만 생성하고 초기화는 하지 않음
    window.gameInstance = new Game();
    
    // 기본적인 씬 설정만 수행
    window.gameInstance.setupScene();
    window.gameInstance.animate();  // 렌더링 시작
    
    // 시작 화면 표시
    document.getElementById('startScreen').style.display = 'block';
});