3d小游戏edit icon

创建者:
用户d3dcLPzN
Fork(复制)
下载
嵌入
BUG反馈
index.html
style.css
index.js
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>AREMM - 升级版</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            touch-action: none;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
            font-family: 'Arial', sans-serif;
        }

        body {
            overflow: hidden;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: white;
        }

        #game-container {
            position: relative;
            width: 100%;
            height: 100vh;
        }

        #splash-screen {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: radial-gradient(circle, #0c1445 0%, #020617 100%);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 100;
            transition: opacity 1s ease-in-out;
        }

        .splash-logo {
            font-size: 6rem;
            font-weight: bold;
            color: #ff9900;
            text-shadow: 0 0 20px rgba(255, 153, 0, 0.7);
            margin-bottom: 1rem;
            animation: pulse 2s infinite;
        }

        .studio-logo {
            font-size: 2rem;
            color: #4dc3ff;
            margin-bottom: 3rem;
        }

        .start-button {
            padding: 15px 40px;
            font-size: 1.5rem;
            background: linear-gradient(45deg, #ff512f, #f09819);
            border: none;
            border-radius: 50px;
            color: white;
            cursor: pointer;
            transition: all 0.3s;
            box-shadow: 0 5px 15px rgba(240, 152, 25, 0.4);
        }

        .start-button:hover {
            transform: scale(1.05);
            box-shadow: 0 8px 20px rgba(240, 152, 25, 0.6);
        }

        #game-canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }

        #ui-container {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .ui-panel {
            background: rgba(0, 0, 0, 0.6);
            border: 2px solid rgba(255, 153, 0, 0.5);
            border-radius: 10px;
            padding: 15px;
            margin: 15px;
            backdrop-filter: blur(5px);
        }

        #top-left-panel {
            position: absolute;
            top: 20px;
            left: 20px;
            width: 250px;
        }

        #bottom-right-panel {
            position: absolute;
            bottom: 20px;
            right: 20px;
            width: 200px;
        }

        #center-panel {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
            display: none;
        }

        .stats-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 10px;
            padding-bottom: 10px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.2);
        }

        .stats-label {
            color: #4dc3ff;
        }

        .stats-value {
            color: #ff9900;
            font-weight: bold;
        }

        .button {
            background: linear-gradient(45deg, #4dc3ff, #1a75ff);
            border: none;
            border-radius: 5px;
            color: white;
            padding: 8px 15px;
            margin: 5px;
            cursor: pointer;
            pointer-events: auto;
            transition: all 0.2s;
        }

        .button:hover {
            background: linear-gradient(45deg, #1a75ff, #4dc3ff);
            transform: translateY(-2px);
        }

        #exit-vehicle-btn {
            background: linear-gradient(45deg, #ff512f, #f09819);
            display: none;
        }

        #shop-btn {
            background: linear-gradient(45deg, #8E2DE2, #4A00E0);
        }

        .shop-item {
            background: rgba(50, 50, 100, 0.7);
            border-radius: 8px;
            padding: 10px;
            margin: 10px 0;
            cursor: pointer;
            pointer-events: auto;
            transition: all 0.2s;
        }

        .shop-item:hover {
            background: rgba(70, 70, 150, 0.8);
            transform: scale(1.02);
        }

        .item-name {
            color: #ff9900;
            font-weight: bold;
        }

        .item-price {
            color: #4dc3ff;
            font-size: 0.9rem;
        }

        .item-desc {
            color: #ccc;
            font-size: 0.85rem;
            margin-top: 5px;
        }

        .weapon-slot {
            display: inline-block;
            width: 40px;
            height: 40px;
            background: rgba(100, 100, 100, 0.6);
            border: 2px solid #4dc3ff;
            border-radius: 5px;
            margin: 5px;
            text-align: center;
            line-height: 40px;
            font-size: 1.2rem;
            pointer-events: auto;
            cursor: pointer;
        }

        .active-slot {
            border-color: #ff9900;
            background: rgba(255, 153, 0, 0.2);
        }

        .zombie-indicator {
            position: absolute;
            width: 10px;
            height: 10px;
            background: #ff0000;
            border-radius: 50%;
            box-shadow: 0 0 10px rgba(255, 0, 0, 0.7);
        }

        .teammate-indicator {
            position: absolute;
            width: 8px;
            height: 8px;
            background: #4dc3ff;
            border-radius: 50%;
            box-shadow: 0 0 10px rgba(77, 195, 255, 0.7);
        }

        .health-bar {
            width: 100%;
            height: 15px;
            background: rgba(100, 0, 0, 0.5);
            border-radius: 5px;
            margin-top: 10px;
            overflow: hidden;
        }

        .health-fill {
            height: 100%;
            background: linear-gradient(90deg, #ff0000, #ff9900);
            width: 100%;
            transition: width 0.3s;
        }

        .message {
            position: absolute;
            top: 20%;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.7);
            padding: 15px 30px;
            border-radius: 10px;
            border-left: 5px solid #ff9900;
            display: none;
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .fade-in {
            animation: fadeIn 0.5s ease-in;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <div id="splash-screen" class="fade-in">
            <div class="splash-logo">AREMM</div>
            <div class="studio-logo">鼠神工作室</div>
            <button class="start-button" id="start-btn">开始游戏</button>
        </div>
        
        <canvas id="game-canvas"></canvas>
        
        <div id="ui-container">
            <div id="top-left-panel" class="ui-panel">
                <div class="stats-row">
                    <span class="stats-label">生命值:</span>
                    <span class="stats-value" id="health-value">100</span>
                </div>
                <div class="health-bar">
                    <div class="health-fill" id="health-bar"></div>
                </div>
                <div class="stats-row">
                    <span class="stats-label">速度:</span>
                    <span class="stats-value" id="speed-value">0 km/h</span>
                </div>
                <div class="stats-row">
                    <span class="stats-label">弹药:</span>
                    <span class="stats-value" id="ammo-value">30</span>
                </div>
                <div class="stats-row">
                    <span class="stats-label">积分:</span>
                    <span class="stats-value" id="points-value">500</span>
                </div>
                
                <div style="margin-top: 15px;">
                    <div>武器槽:</div>
                    <div>
                        <div class="weapon-slot active-slot" data-weapon="pistol">P</div>
                        <div class="weapon-slot" data-weapon="shotgun">S</div>
                        <div class="weapon-slot" data-weapon="rifle">R</div>
                    </div>
                </div>
            </div>
            
            <div id="bottom-right-panel" class="ui-panel">
                <button class="button" id="exit-vehicle-btn">下车</button>
                <button class="button" id="shop-btn">商店</button>
                
                <div id="shop-panel" style="display: none; margin-top: 15px;">
                    <div class="shop-item">
                        <div class="item-name">医疗包</div>
                        <div class="item-price">100 积分</div>
                        <div class="item-desc">恢复 50 点生命值</div>
                    </div>
                    <div class="shop-item">
                        <div class="item-name">弹药包</div>
                        <div class="item-price">80 积分</div>
                        <div class="item-desc">补充所有武器弹药</div>
                    </div>
                    <div class="shop-item">
                        <div class="item-name">霰弹枪</div>
                        <div class="item-price">300 积分</div>
                        <div class="item-desc">近距离高伤害武器</div>
                    </div>
                    <div class="shop-item">
                        <div class="item-name">防御塔</div>
                        <div class="item-price">500 积分</div>
                        <div class="item-desc">自动攻击附近僵尸</div>
                    </div>
                </div>
            </div>
            
            <div id="center-panel" class="ui-panel">
                <h2>游戏结束</h2>
                <p>你的分数: <span id="final-score">0</span></p>
                <button class="button" id="restart-btn">重新开始</button>
            </div>
            
            <div class="message" id="game-message"></div>
        </div>
    </div>

    <script>
        // 游戏状态管理
        const GameState = {
            SPLASH: 0,
            PLAYING: 1,
            IN_VEHICLE: 2,
            SHOPPING: 3,
            GAME_OVER: 4
        };

        // 游戏配置
        const GameConfig = {
            playerSpeed: 0.2,
            vehicleSpeed: 0.5,
            playerHealth: 100,
            zombieDamage: 10,
            zombieSpawnRate: 2000, // 每2秒生成一个僵尸
            teammateCount: 3,
            bulletSpeed: 1,
            bulletDamage: 25
        };

        // 游戏主类
        class AREMMGame {
            constructor() {
                this.state = GameState.SPLASH;
                this.clock = new THREE.Clock();
                this.scene = new THREE.Scene();
                this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
                this.renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('game-canvas'), antialias: true });
                this.renderer.setSize(window.innerWidth, window.innerHeight);
                this.renderer.setClearColor(0x87CEEB);
                
                this.player = null;
                this.vehicle = null;
                this.zombies = [];
                this.teammates = [];
                this.bullets = [];
                this.controls = {
                    forward: false,
                    backward: false,
                    left: false,
                    right: false,
                    shoot: false
                };
                
                this.stats = {
                    health: GameConfig.playerHealth,
                    ammo: 30,
                    points: 500,
                    kills: 0
                };
                
                this.init();
                this.setupEventListeners();
            }
            
            init() {
                // 设置相机位置
                this.camera.position.set(0, 10, 15);
                this.camera.lookAt(0, 0, 0);
                
                // 添加光源
                const ambientLight = new THREE.AmbientLight(0x606060);
                this.scene.add(ambientLight);
                
                const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
                directionalLight.position.set(1, 1, 0.5).normalize();
                this.scene.add(directionalLight);
                
                // 创建地面
                const groundGeometry = new THREE.PlaneGeometry(100, 100);
                const groundMaterial = new THREE.MeshStandardMaterial({ 
                    color: 0x2E8B57,
                    roughness: 0.8
                });
                const ground = new THREE.Mesh(groundGeometry, groundMaterial);
                ground.rotation.x = -Math.PI / 2;
                this.scene.add(ground);
                
                // 添加一些随机障碍物
                for (let i = 0; i < 20; i++) {
                    const size = Math.random() * 3 + 1;
                    const geometry = new THREE.BoxGeometry(size, size, size);
                    const material = new THREE.MeshStandardMaterial({ 
                        color: Math.random() * 0xffffff,
                        roughness: 0.7
                    });
                    const obstacle = new THREE.Mesh(geometry, material);
                    obstacle.position.set(
                        Math.random() * 80 - 40,
                        size / 2,
                        Math.random() * 80 - 40
                    );
                    this.scene.add(obstacle);
                }
                
                // 创建玩家
                this.createPlayer();
                
                // 创建车辆
                this.createVehicle();
                
                // 创建队友
                this.createTeammates();
                
                // 开始游戏循环
                this.animate();
            }
            
            createPlayer() {
                const geometry = new THREE.CapsuleGeometry(0.5, 1, 4, 8);
                const material = new THREE.MeshStandardMaterial({ color: 0x4169E1 });
                this.player = new THREE.Mesh(geometry, material);
                this.player.position.set(0, 1.5, 0);
                this.scene.add(this.player);
                
                // 添加玩家武器
                const weaponGeometry = new THREE.BoxGeometry(0.3, 0.1, 1);
                const weaponMaterial = new THREE.MeshStandardMaterial({ color: 0x333333 });
                this.playerWeapon = new THREE.Mesh(weaponGeometry, weaponMaterial);
                this.playerWeapon.position.set(0.5, 0.2, 0.5);
                this.player.add(this.playerWeapon);
            }
            
            createVehicle() {
                // 创建车体
                const bodyGeometry = new THREE.BoxGeometry(3, 1, 5);
                const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0xFF4500 });
                const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
                
                // 创建车轮
                const wheelGeometry = new THREE.CylinderGeometry(0.5, 0.5, 0.3, 16);
                wheelGeometry.rotateZ(Math.PI / 2);
                const wheelMaterial = new THREE.MeshStandardMaterial({ color: 0x222222 });
                
                const wheelPositions = [
                    { x: 1.2, y: -0.5, z: 1.8 },
                    { x: -1.2, y: -0.5, z: 1.8 },
                    { x: 1.2, y: -0.5, z: -1.8 },
                    { x: -1.2, y: -0.5, z: -1.8 }
                ];
                
                this.vehicle = new THREE.Group();
                this.vehicle.add(body);
                
                wheelPositions.forEach(pos => {
                    const wheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
                    wheel.position.set(pos.x, pos.y, pos.z);
                    this.vehicle.add(wheel);
                });
                
                this.vehicle.position.set(10, 1, 0);
                this.vehicle.rotation.y = Math.PI / 2;
                this.scene.add(this.vehicle);
                
                this.vehicleSpeed = 0;
                this.vehicleDirection = new THREE.Vector3();
            }
            
            createTeammates() {
                for (let i = 0; i < GameConfig.teammateCount; i++) {
                    const geometry = new THREE.CapsuleGeometry(0.4, 0.8, 4, 8);
                    const material = new THREE.MeshStandardMaterial({ color: 0x32CD32 });
                    const teammate = new THREE.Mesh(geometry, material);
                    
                    // 随机位置
                    const angle = (i / GameConfig.teammateCount) * Math.PI * 2;
                    const radius = 10;
                    teammate.position.set(
                        Math.cos(angle) * radius,
                        0.8,
                        Math.sin(angle) * radius
                    );
                    
                    this.scene.add(teammate);
                    this.teammates.push({
                        mesh: teammate,
                        target: new THREE.Vector3(),
                        state: 'patrol', // patrol, attack, follow
                        reloadTime: 0
                    });
                }
            }
            
            spawnZombie() {
                const geometry = new THREE.CapsuleGeometry(0.5, 1, 4, 8);
                const material = new THREE.MeshStandardMaterial({ color: 0x8B0000 });
                const zombie = new THREE.Mesh(geometry, material);
                
                // 在玩家一定距离外生成僵尸
                const angle = Math.random() * Math.PI * 2;
                const distance = 30 + Math.random() * 20;
                zombie.position.set(
                    Math.cos(angle) * distance,
                    1,
                    Math.sin(angle) * distance
                );
                
                this.scene.add(zombie);
                this.zombies.push({
                    mesh: zombie,
                    health: 100
                });
            }
            
            enterVehicle() {
                if (this.state === GameState.PLAYING) {
                    // 检查玩家是否在车辆附近
                    const distance = this.player.position.distanceTo(this.vehicle.position);
                    if (distance < 5) {
                        this.state = GameState.IN_VEHICLE;
                        document.getElementById('exit-vehicle-btn').style.display = 'block';
                        
                        // 隐藏玩家
                        this.player.visible = false;
                        
                        // 将相机附加到车辆
                        this.camera.position.set(0, 3, -7);
                        this.camera.lookAt(0, 0, 10);
                        this.vehicle.add(this.camera);
                        
                        this.showMessage("已进入车辆,使用WASD控制");
                    }
                }
            }
            
            exitVehicle() {
                if (this.state === GameState.IN_VEHICLE) {
                    this.state = GameState.PLAYING;
                    document.getElementById('exit-vehicle-btn').style.display = 'none';
                    
                    // 显示玩家
                    this.player.visible = true;
                    
                    // 将玩家放在车辆旁边
                    this.scene.add(this.camera);
                    const vehicleDirection = new THREE.Vector3();
                    this.vehicle.getWorldDirection(vehicleDirection);
                    vehicleDirection.multiplyScalar(3);
                    
                    this.player.position.copy(this.vehicle.position).add(vehicleDirection);
                    this.player.position.y = 1.5;
                    
                    // 重置相机位置
                    this.camera.position.set(0, 10, 15);
                    this.camera.lookAt(this.player.position);
                }
            }
            
            toggleShop() {
                if (this.state === GameState.PLAYING || this.state === GameState.IN_VEHICLE) {
                    const shopPanel = document.getElementById('shop-panel');
                    if (this.state === GameState.SHOPPING) {
                        this.state = this.previousState;
                        shopPanel.style.display = 'none';
                    } else {
                        this.previousState = this.state;
                        this.state = GameState.SHOPPING;
                        shopPanel.style.display = 'block';
                    }
                }
            }
            
            buyItem(itemName) {
                let cost = 0;
                switch(itemName) {
                    case '医疗包':
                        cost = 100;
                        if (this.stats.points >= cost) {
                            this.stats.points -= cost;
                            this.stats.health = Math.min(100, this.stats.health + 50);
                            this.updateUI();
                            this.showMessage("已购买医疗包,生命值恢复50点");
                        } else {
                            this.showMessage("积分不足!");
                        }
                        break;
                    case '弹药包':
                        cost = 80;
                        if (this.stats.points >= cost) {
                            this.stats.points -= cost;
                            this.stats.ammo = 30;
                            this.updateUI();
                            this.showMessage("已购买弹药包,弹药已补充");
                        } else {
                            this.showMessage("积分不足!");
                        }
                        break;
                    case '霰弹枪':
                        cost = 300;
                        if (this.stats.points >= cost) {
                            this.stats.points -= cost;
                            this.showMessage("已购买霰弹枪,按2键切换");
                        } else {
                            this.showMessage("积分不足!");
                        }
                        break;
                    case '防御塔':
                        cost = 500;
                        if (this.stats.points >= cost) {
                            this.stats.points -= cost;
                            this.showMessage("已购买防御塔,将在基地部署");
                        } else {
                            this.showMessage("积分不足!");
                        }
                        break;
                }
            }
            
            shoot() {
                if (this.state !== GameState.PLAYING || this.stats.ammo <= 0) return;
                
                this.stats.ammo--;
                this.updateUI();
                
                // 创建子弹
                const geometry = new THREE.SphereGeometry(0.1, 8, 8);
                const material = new THREE.MeshBasicMaterial({ color: 0xFFFF00 });
                const bullet = new THREE.Mesh(geometry, material);
                
                // 设置子弹位置和方向
                bullet.position.copy(this.player.position);
                bullet.position.y += 1;
                
                const direction = new THREE.Vector3();
                this.camera.getWorldDirection(direction);
                direction.multiplyScalar(GameConfig.bulletSpeed);
                
                this.scene.add(bullet);
                this.bullets.push({
                    mesh: bullet,
                    velocity: direction,
                    damage: GameConfig.bulletDamage
                });
                
                // 添加射击效果
                this.createMuzzleFlash();
            }
            
            createMuzzleFlash() {
                const flashGeometry = new THREE.SphereGeometry(0.2, 8, 8);
                const flashMaterial = new THREE.MeshBasicMaterial({ 
                    color: 0xFF9900,
                    transparent: true,
                    opacity: 0.8
                });
                const flash = new THREE.Mesh(flashGeometry, flashMaterial);
                
                flash.position.copy(this.player.position);
                flash.position.y += 1;
                flash.position.add(this.playerWeapon.getWorldPosition(new THREE.Vector3()));
                
                this.scene.add(flash);
                
                // 短暂显示后移除
                setTimeout(() => {
                    this.scene.remove(flash);
                }, 50);
            }
            
            updatePlayer(delta) {
                if (this.state !== GameState.PLAYING) return;
                
                const speed = GameConfig.playerSpeed * delta * 60;
                const direction = new THREE.Vector3();
                
                if (this.controls.forward) direction.z -= speed;
                if (this.controls.backward) direction.z += speed;
                if (this.controls.left) direction.x -= speed;
                if (this.controls.right) direction.x += speed;
                
                // 应用移动
                direction.applyQuaternion(this.camera.quaternion);
                direction.y = 0;
                this.player.position.add(direction);
                
                // 更新相机位置
                const targetPosition = this.player.position.clone();
                targetPosition.y += 10;
                targetPosition.z += 15;
                this.camera.position.lerp(targetPosition, 0.1);
                this.camera.lookAt(this.player.position);
            }
            
            updateVehicle(delta) {
                if (this.state !== GameState.IN_VEHICLE) return;
                
                const speed = GameConfig.vehicleSpeed * delta * 60;
                this.vehicleDirection.set(0, 0, 0);
                
                if (this.controls.forward) this.vehicleDirection.z -= speed;
                if (this.controls.backward) this.vehicleDirection.z += speed;
                if (this.controls.left) this.vehicle.rotation.y += 0.03;
                if (this.controls.right) this.vehicle.rotation.y -= 0.03;
                
                // 应用移动方向
                this.vehicleDirection.applyQuaternion(this.vehicle.quaternion);
                this.vehicle.position.add(this.vehicleDirection);
                
                // 更新速度显示
                this.vehicleSpeed = this.vehicleDirection.length() * 20;
                document.getElementById('speed-value').textContent = 
                    Math.round(this.vehicleSpeed) + ' km/h';
            }
            
            updateTeammates(delta) {
                this.teammates.forEach(teammate => {
                    // 队友AI逻辑
                    switch(teammate.state) {
                        case 'patrol':
                            // 随机巡逻
                            if (Math.random() < 0.02) {
                                teammate.target.set(
                                    Math.random() * 80 - 40,
                                    0,
                                    Math.random() * 80 - 40
                                );
                            }
                            
                            // 寻找僵尸
                            for (const zombie of this.zombies) {
                                const distance = teammate.mesh.position.distanceTo(zombie.mesh.position);
                                if (distance < 15) {
                                    teammate.state = 'attack';
                                    teammate.target = zombie;
                                    break;
                                }
                            }
                            break;
                            
                        case 'attack':
                            if (!teammate.target || teammate.target.health <= 0) {
                                teammate.state = 'patrol';
                                break;
                            }
                            
                            // 朝僵尸移动
                            const direction = new THREE.Vector3();
                            direction.subVectors(teammate.target.mesh.position, teammate.mesh.position);
                            direction.y = 0;
                            direction.normalize().multiplyScalar(0.05 * delta * 60);
                            
                            if (teammate.mesh.position.distanceTo(teammate.target.mesh.position) > 5) {
                                teammate.mesh.position.add(direction);
                                teammate.mesh.lookAt(teammate.target.mesh.position);
                            } else {
                                // 攻击僵尸
                                if (teammate.reloadTime <= 0) {
                                    teammate.target.health -= 15;
                                    teammate.reloadTime = 1.0; // 1秒装弹时间
                                    
                                    if (teammate.target.health <= 0) {
                                        this.scene.remove(teammate.target.mesh);
                                        this.zombies = this.zombies.filter(z => z !== teammate.target);
                                        teammate.state = 'patrol';
                                        this.stats.points += 20;
                                        this.stats.kills++;
                                        this.updateUI();
                                    }
                                }
                            }
                            break;
                    }
                    
                    // 更新装弹时间
                    if (teammate.reloadTime > 0) {
                        teammate.reloadTime -= delta;
                    }
                    
                    // 朝向目标
                    if (teammate.state === 'patrol') {
                        const lookDirection = new THREE.Vector3();
                        lookDirection.subVectors(teammate.target, teammate.mesh.position);
                        lookDirection.y = 0;
                        
                        if (lookDirection.length() > 0.1) {
                            teammate.mesh.lookAt(teammate.target);
                        }
                    }
                });
            }
            
            updateZombies(delta) {
                // 生成新僵尸
                if (this.zombieSpawnTimer <= 0) {
                    this.spawnZombie();
                    this.zombieSpawnTimer = GameConfig.zombieSpawnRate / 1000;
                } else {
                    this.zombieSpawnTimer -= delta;
                }
                
                // 更新僵尸行为
                this.zombies.forEach(zombie => {
                    // 寻找最近的目标(玩家或队友)
                    let target = this.player;
                    let minDistance = zombie.mesh.position.distanceTo(this.player.position);
                    
                    for (const teammate of this.teammates) {
                        const distance = zombie.mesh.position.distanceTo(teammate.mesh.position);
                        if (distance < minDistance) {
                            minDistance = distance;
                            target = teammate.mesh;
                        }
                    }
                    
                    // 朝目标移动
                    const direction = new THREE.Vector3();
                    direction.subVectors(target.position, zombie.mesh.position);
                    direction.y = 0;
                    direction.normalize().multiplyScalar(0.03 * delta * 60);
                    zombie.mesh.position.add(direction);
                    
                    // 朝向目标
                    zombie.mesh.lookAt(target.position);
                    
                    // 攻击逻辑
                    if (minDistance < 1.5) {
                        if (target === this.player) {
                            this.stats.health -= GameConfig.zombieDamage * delta;
                            this.updateUI();
                            
                            if (this.stats.health <= 0) {
                                this.gameOver();
                            }
                        } else {
                            // 攻击队友(简化处理)
                            if (Math.random() < 0.1) {
                                const teammate = this.teammates.find(t => t.mesh === target);
                                if (teammate) {
                                    // 队友被攻击(简化处理)
                                }
                            }
                        }
                    }
                });
            }
            
            updateBullets(delta) {
                for (let i = this.bullets.length - 1; i >= 0; i--) {
                    const bullet = this.bullets[i];
                    bullet.mesh.position.add(bullet.velocity);
                    
                    // 检查碰撞
                    let hit = false;
                    
                    // 检查与僵尸的碰撞
                    for (const zombie of this.zombies) {
                        if (bullet.mesh.position.distanceTo(zombie.mesh.position) < 1) {
                            zombie.health -= bullet.damage;
                            
                            if (zombie.health <= 0) {
                                this.scene.remove(zombie.mesh);
                                this.zombies.splice(this.zombies.indexOf(zombie), 1);
                                this.stats.points += 50;
                                this.stats.kills++;
                                this.updateUI();
                            }
                            
                            hit = true;
                            break;
                        }
                    }
                    
                    // 检查超出边界
                    if (bullet.mesh.position.length() > 100 || hit) {
                        this.scene.remove(bullet.mesh);
                        this.bullets.splice(i, 1);
                    }
                }
            }
            
            updateUI() {
                document.getElementById('health-value').textContent = Math.floor(this.stats.health);
                document.getElementById('health-bar').style.width = this.stats.health + '%';
                document.getElementById('ammo-value').textContent = this.stats.ammo;
                document.getElementById('points-value').textContent = this.stats.points;
            }
            
            showMessage(text) {
                const message = document.getElementById('game-message');
                message.textContent = text;
                message.style.display = 'block';
                
                setTimeout(() => {
                    message.style.display = 'none';
                }, 3000);
            }
            
            gameOver() {
                this.state = GameState.GAME_OVER;
                document.getElementById('final-score').textContent = this.stats.kills * 100 + this.stats.points;
                document.getElementById('center-panel').style.display = 'block';
            }
            
            restartGame() {
                // 重置游戏状态
                this.state = GameState.PLAYING;
                this.stats = {
                    health: GameConfig.playerHealth,
                    ammo: 30,
                    points: 500,
                    kills: 0
                };
                
                // 移除所有僵尸
                this.zombies.forEach(zombie => this.scene.remove(zombie.mesh));
                this.zombies = [];
                
                // 移除所有子弹
                this.bullets.forEach(bullet => this.scene.remove(bullet.mesh));
                this.bullets = [];
                
                // 重置玩家位置
                this.player.position.set(0, 1.5, 0);
                this.player.visible = true;
                
                // 重置车辆位置
                this.vehicle.position.set(10, 1, 0);
                this.vehicle.rotation.y = Math.PI / 2;
                
                // 重置相机
                this.scene.add(this.camera);
                this.camera.position.set(0, 10, 15);
                this.camera.lookAt(0, 0, 0);
                
                // 更新UI
                this.updateUI();
                document.getElementById('center-panel').style.display = 'none';
                document.getElementById('exit-vehicle-btn').style.display = 'none';
            }
            
            setupEventListeners() {
                // 键盘控制
                window.addEventListener('keydown', (e) => {
                    switch(e.key.toLowerCase()) {
                        case 'w': this.controls.forward = true; break;
                        case 's': this.controls.backward = true; break;
                        case 'a': this.controls.left = true; break;
                        case 'd': this.controls.right = true; break;
                        case 'e': this.enterVehicle(); break;
                        case ' ': 
                            if (this.state === GameState.PLAYING) this.shoot(); 
                            break;
                        case '1': 
                        case '2': 
                        case '3': 
                            this.selectWeapon(parseInt(e.key) - 1); 
                            break;
                    }
                });
                
                window.addEventListener('keyup', (e) => {
                    switch(e.key.toLowerCase()) {
                        case 'w': this.controls.forward = false; break;
                        case 's': this.controls.backward = false; break;
                        case 'a': this.controls.left = false; break;
                        case 'd': this.controls.right = false; break;
                    }
                });
                
                // 鼠标控制
                window.addEventListener('mousedown', () => {
                    if (this.state === GameState.PLAYING) this.controls.shoot = true;
                });
                
                window.addEventListener('mouseup', () => {
                    this.controls.shoot = false;
                });
                
                // 按钮事件
                document.getElementById('start-btn').addEventListener('click', () => {
                    document.getElementById('splash-screen').style.opacity = 0;
                    setTimeout(() => {
                        document.getElementById('splash-screen').style.display = 'none';
                        this.state = GameState.PLAYING;
                    }, 1000);
                });
                
                document.getElementById('exit-vehicle-btn').addEventListener('click', () => {
                    this.exitVehicle();
                });
                
                document.getElementById('shop-btn').addEventListener('click', () => {
                    this.toggleShop();
                });
                
                document.getElementById('restart-btn').addEventListener('click', () => {
                    this.restartGame();
                });
                
                // 商店购买
                document.querySelectorAll('.shop-item').forEach(item => {
                    item.addEventListener('click', () => {
                        const itemName = item.querySelector('.item-name').textContent;
                        this.buyItem(itemName);
                    });
                });
                
                // 武器选择
                document.querySelectorAll('.weapon-slot').forEach((slot, index) => {
                    slot.addEventListener('click', () => {
                        this.selectWeapon(index);
                    });
                });
                
                // 窗口大小调整
                window.addEventListener('resize', () => {
                    this.camera.aspect = window.innerWidth / window.innerHeight;
                    this.camera.updateProjectionMatrix();
                    this.renderer.setSize(window.innerWidth, window.innerHeight);
                });
            }
            
            selectWeapon(index) {
                document.querySelectorAll('.weapon-slot').forEach((slot, i) => {
                    if (i === index) {
                        slot.classList.add('active-slot');
                    } else {
                        slot.classList.remove('active-slot');
                    }
                });
                
                // 在实际游戏中这里会切换武器模型和属性
                this.showMessage(`已切换武器: ${['手枪', '霰弹枪', '步枪'][index]}`);
            }
            
            animate() {
                requestAnimationFrame(() => this.animate());
                
                const delta = Math.min(0.1, this.clock.getDelta());
                
                // 根据游戏状态更新
                switch(this.state) {
                    case GameState.PLAYING:
                        this.updatePlayer(delta);
                        this.updateTeammates(delta);
                        this.updateZombies(delta);
                        this.updateBullets(delta);
                        break;
                        
                    case GameState.IN_VEHICLE:
                        this.updateVehicle(delta);
                        this.updateTeammates(delta);
                        this.updateZombies(delta);
                        break;
                }
                
                // 渲染场景
                this.renderer.render(this.scene, this.camera);
            }
        }

        // 初始化游戏
        window.addEventListener('load', () => {
            const game = new AREMMGame();
        });
    </script>
</body>
</html>
        
编辑器加载中
预览
控制台