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;
            
            // 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;
    
        // 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);
        
        // 적 전차의 바운딩 박스도 포함하여 검사
        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);
            
            // 바운딩 박스와의 교차 여부로 판단
            return intersects;
        });
        
        if (detectEnemy) {
            this.crosshair.classList.add('target-detected');
        } else {
            this.crosshair.classList.remove('target-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';
      
    });