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 = 1000;
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 = 30;
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/explosion.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;
        return this.health <= 0;
    }
    
    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.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
    }
    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);
}


    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;
        }
    }

    update(playerPosition) {
    if (!this.mesh || !this.isLoaded) return;

    const direction = new THREE.Vector3()
        .subVectors(playerPosition, this.mesh.position)
        .normalize();
    
    const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);
    const minDistance = 50;
    
    // 이전 위치 저장
    const previousPosition = this.mesh.position.clone();
    
    if (distanceToPlayer > minDistance) {
        const moveVector = direction.multiplyScalar(this.moveSpeed);
        const newPosition = this.mesh.position.clone().add(moveVector);
        
        // 지형 높이 가져오기
        const heightAtNewPos = window.gameInstance.getHeightAtPosition(
            newPosition.x,
            newPosition.z
        );
        newPosition.y = heightAtNewPos + TANK_HEIGHT;
        
        // 임시로 위치 이동하여 충돌 체크
        const originalPosition = this.mesh.position.clone();
        this.mesh.position.copy(newPosition);
        
        // 장애물과 충돌 체크
        const enemyBox = new THREE.Box3().setFromObject(this.mesh);
        let hasCollision = false;
        
        // 모든 장애물에 대해 충돌 검사
        for (const obstacle of window.gameInstance.obstacles) {
            const obstacleBox = new THREE.Box3().setFromObject(obstacle);
            if (enemyBox.intersectsBox(obstacleBox)) {
                hasCollision = true;
                break;
            }
        }
        
        // 다른 적 탱크와의 충돌 검사
        if (!hasCollision) {
            for (const otherEnemy of window.gameInstance.enemies) {
                if (otherEnemy !== this && otherEnemy.mesh) {
                    const otherEnemyBox = new THREE.Box3().setFromObject(otherEnemy.mesh);
                    if (enemyBox.intersectsBox(otherEnemyBox)) {
                        hasCollision = true;
                        break;
                    }
                }
            }
        }
        
        // 맵 경계 체크
        const mapBoundary = MAP_SIZE / 2;
        if (Math.abs(newPosition.x) > mapBoundary || 
            Math.abs(newPosition.z) > mapBoundary) {
            hasCollision = true;
        }
        
        // 충돌이 있으면 이전 위치로 복귀, 없으면 새 위치 유지
        if (hasCollision) {
            this.mesh.position.copy(previousPosition);
            
            // 충돌 시 우회 경로 시도
            const alternateDirections = [
                new THREE.Vector3(-direction.z, 0, direction.x), // 왼쪽으로 90도
                new THREE.Vector3(direction.z, 0, -direction.x), // 오른쪽으로 90도
                new THREE.Vector3(-direction.x, 0, -direction.z)  // 180도 회전
            ];
            
            for (const altDirection of alternateDirections) {
                const altMoveVector = altDirection.multiplyScalar(this.moveSpeed);
                const altNewPosition = previousPosition.clone().add(altMoveVector);
                
                this.mesh.position.copy(altNewPosition);
                const altEnemyBox = new THREE.Box3().setFromObject(this.mesh);
                
                let altHasCollision = false;
                
                // 새로운 방향에 대한 충돌 검사
                for (const obstacle of window.gameInstance.obstacles) {
                    const obstacleBox = new THREE.Box3().setFromObject(obstacle);
                    if (altEnemyBox.intersectsBox(obstacleBox)) {
                        altHasCollision = true;
                        break;
                    }
                }
                
                if (!altHasCollision) {
                    // 우회 경로가 가능하면 그 방향으로 이동
                    break;
                } else {
                    // 우회도 불가능하면 이전 위치로 복귀
                    this.mesh.position.copy(previousPosition);
                }
            }
        }
        
        // 지형에 따른 기울기 조정
        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);
    }
    
    // 플레이어를 향해 포탑 회전
    this.mesh.lookAt(playerPosition);
    
    // 총알 업데이트
    if (this.bullets) {
        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;
                }
            }
        }
    }
}


    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;

    // 발사 이펙트 생성
    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;
        return this.health <= 0;
    }

    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 = [];  // 배열이 없으면 초기화
        }
        // 바위 생성 개수를 70개로 줄임
    const ROCK_COUNT = 70;

        // 바위 지오메트리 정의
    const rockGeometries = [
        new THREE.DodecahedronGeometry(3),
        new THREE.DodecahedronGeometry(2),
        new THREE.DodecahedronGeometry(4)
    ];

    const rockMaterial = new THREE.MeshStandardMaterial({
        color: 0x8B4513,
        roughness: 0.9,
        metalness: 0.1
    });

    // 충돌 박스 시각화용 재질 (디버깅용)
    const collisionBoxMaterial = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: true,
        visible: false // 필요시 true로 변경하여 충돌 박스 확인
    });

    for (let i = 0; i < ROCK_COUNT; i++) {
        const rockGeometry = rockGeometries[Math.floor(Math.random() * rockGeometries.length)];
        const rock = new THREE.Mesh(rockGeometry, rockMaterial);
        
        // 바위 위치 설정 - 맵 가장자리에 더 많이 배치
        let x, z;
        const edgeSpawn = Math.random() < 0.7; // 70% 확률로 가장자리에 생성

        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;
        }

        rock.position.set(x, Math.random() * 2, z);
        
        rock.rotation.set(
            Math.random() * Math.PI,
            Math.random() * Math.PI,
            Math.random() * Math.PI
        );
        
        // 바위 크기를 좀 더 다양하게 설정
        const scale = 1 + Math.random() * 1.5; // 1.0 ~ 2.5 사이의 크기
        rock.scale.set(scale, scale, scale);
        
        // 충돌 박스 생성 및 설정
        const boundingBox = new THREE.Box3().setFromObject(rock);
        const boxSize = boundingBox.getSize(new THREE.Vector3());
        const collisionGeometry = new THREE.BoxGeometry(boxSize.x, boxSize.y, boxSize.z);
        const collisionMesh = new THREE.Mesh(collisionGeometry, collisionBoxMaterial);
        
        collisionMesh.position.copy(rock.position);
        collisionMesh.rotation.copy(rock.rotation);
        
        // 모든 바위를 충돌 가능하게 설정
        rock.userData.isCollidable = true;
        rock.userData.type = 'rock';
        rock.userData.collisionMesh = collisionMesh;
        
        rock.castShadow = true;
        rock.receiveShadow = true;
        
        // 다른 바위들과의 거리 체크
        let tooClose = false;
        for (const obstacle of this.obstacles) {
            const distance = rock.position.distanceTo(obstacle.position);
            if (distance < 15) { // 최소 거리 설정
                tooClose = true;
                break;
            }
        }

        if (!tooClose) {
            this.obstacles.push(rock);
            this.scene.add(rock);
            this.scene.add(collisionMesh);
        }
    }

    // 선인장 추가
    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);
        // 선인장은 obstacles 배열에 추가하지 않음
    }
}


   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();
           }
       }, 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);

    // 탱크와 장애물 충돌 체크 (개선)
    this.obstacles.forEach(obstacle => {
    if (obstacle.userData.isCollidable) { // 충돌 가능한 객체만 검사
        const obstacleBoundingBox = new THREE.Box3().setFromObject(obstacle);
        if (tankBoundingBox.intersectsBox(obstacleBoundingBox)) {
            this.tank.body.position.copy(this.previousTankPosition);
        }
    }
});
        // 적 탱크와 장애물 충돌 체크 (추가)
    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 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();
                }
                this.scene.remove(bullet);
                enemy.bullets.splice(bulletIndex, 1); // filter 대신 splice 사용
                
                this.createExplosion(bullet.position);
                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 distance = bullet.position.distanceTo(enemy.mesh.position);
        if (distance < 2) {
            const randomHitSound = hitSounds[Math.floor(Math.random() * hitSounds.length)];
            const hitAudio = new Audio(randomHitSound);
            hitAudio.play();

            if (enemy.takeDamage(50)) {
                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() {
    if (this.isGameOver) return;
    
    this.isGameOver = true;
     // BGM 정지
    if (this.bgm) {
        this.bgm.pause();
        this.bgm = null;
        this.bgmPlaying = false;
    }
    
    // 사망 사운드 재생
    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 = `
        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() {
    this.raycaster.setFromCamera(new THREE.Vector2(), this.camera);
    const intersects = this.raycaster.intersectObjects(this.scene.children, true);
    
    if (intersects.length > 0) {
        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';
});