m4a1edit icon

作者:
邓朝元
Fork(复制)
下载
嵌入
BUG反馈
index.html
现在支持上传本地图片了!
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>枪械开镜模拟器 - 触控版</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            touch-action: none;
        }
        
        body {
            font-family: 'Arial', sans-serif;
            background: #000;
            color: #fff;
            overflow: hidden;
            user-select: none;
            height: 100vh;
            width: 100vw;
        }
        
        #gameContainer {
            width: 100%;
            height: 100%;
            position: relative;
            background: linear-gradient(to bottom, #87CEEB 0%, #98D8E8 100%);
        }
        
        /* 准星 */
        #crosshair {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 30px;
            height: 30px;
            pointer-events: none;
            z-index: 10;
            transition: all 0.1s ease;
        }
        
        .crosshair-dot {
            position: absolute;
            width: 4px;
            height: 4px;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 50%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        
        .crosshair-line {
            position: absolute;
            background: rgba(255, 255, 255, 0.8);
        }
        
        .line-h {
            width: 20px;
            height: 2px;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        
        .line-v {
            width: 2px;
            height: 20px;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        
        /* M4A1枪械模型 */
        #weaponModel {
            position: absolute;
            bottom: 100px;
            right: 100px;
            width: 200px;
            height: 80px;
            z-index: 15;
            pointer-events: none;
        }
        
        .weapon-body {
            position: absolute;
            width: 160px;
            height: 20px;
            background: linear-gradient(to right, #4a4a4a, #666, #4a4a4a);
            border-radius: 3px;
            bottom: 0;
            right: 0;
            box-shadow: 0 2px 5px rgba(0,0,0,0.5);
        }
        
        .weapon-handguard {
            position: absolute;
            width: 100px;
            height: 15px;
            background: linear-gradient(to right, #555, #777, #555);
            border-radius: 2px;
            bottom: 25px;
            right: 30px;
        }
        
        .weapon-barrel {
            position: absolute;
            width: 120px;
            height: 8px;
            background: linear-gradient(to right, #333, #555, #333);
            border-radius: 2px;
            bottom: 30px;
            right: 0;
        }
        
        .weapon-sight {
            position: absolute;
            width: 20px;
            height: 10px;
            background: #222;
            border-radius: 2px;
            bottom: 35px;
            right: 100px;
        }
        
        .weapon-magazine {
            position: absolute;
            width: 25px;
            height: 40px;
            background: linear-gradient(to bottom, #444, #666, #444);
            border-radius: 2px;
            bottom: -40px;
            right: 60px;
        }
        
        .weapon-stock {
            position: absolute;
            width: 60px;
            height: 15px;
            background: linear-gradient(to right, #444, #666, #444);
            border-radius: 2px;
            bottom: 5px;
            right: 160px;
            transform: rotate(-5deg);
        }
        
        /* 瞄准时镜 */
        #scopeOverlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: none;
            pointer-events: none;
            z-index: 20;
        }
        
        #scopeReticle {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 300px;
            height: 300px;
        }
        
        .reticle-center {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 2px;
            height: 2px;
            background: rgba(0, 255, 0, 0.9);
            transform: translate(-50%, -50%);
        }
        
        .reticle-line-h {
            position: absolute;
            top: 50%;
            left: 0;
            width: 100%;
            height: 1px;
            background: linear-gradient(to right, 
                transparent 0%, 
                rgba(0, 255, 0, 0.7) 45%, 
                rgba(0, 255, 0, 0.9) 50%, 
                rgba(0, 255, 0, 0.7) 55%, 
                transparent 100%);
        }
        
        .reticle-line-v {
            position: absolute;
            left: 50%;
            top: 0;
            width: 1px;
            height: 100%;
            background: linear-gradient(to bottom, 
                transparent 0%, 
                rgba(0, 255, 0, 0.7) 45%, 
                rgba(0, 255, 0, 0.9) 50%, 
                rgba(0, 255, 0, 0.7) 55%, 
                transparent 100%);
        }
        
        .distance-mark {
            position: absolute;
            color: rgba(0, 255, 0, 0.8);
            font-size: 12px;
            font-family: monospace;
            text-shadow: 0 0 2px #000;
        }
        
        /* UI面板 */
        #uiPanel {
            position: absolute;
            top: 20px;
            left: 20px;
            z-index: 30;
            background: rgba(0, 0, 0, 0.5);
            padding: 15px;
            border-radius: 10px;
            font-family: monospace;
        }
        
        #ammoDisplay {
            font-size: 18px;
            margin-bottom: 10px;
        }
        
        #weaponName {
            font-size: 16px;
            color: #00ff00;
        }
        
        #fireModeDisplay {
            font-size: 14px;
            color: #ffff00;
            margin-top: 5px;
        }
        
        /* 操作说明 */
        #instructions {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            text-align: center;
            background: rgba(0, 0, 0, 0.7);
            padding: 10px 20px;
            border-radius: 5px;
            font-size: 14px;
            z-index: 30;
        }
        
        /* 目标 */
        #targetPractice {
            position: absolute;
            width: 40px;
            height: 40px;
            background: rgba(255, 0, 0, 0.7);
            border-radius: 50%;
            border: 2px solid white;
            cursor: crosshair;
            z-index: 5;
        }
        
        /* 枪口闪光 */
        .muzzleFlash {
            position: absolute;
            width: 20px;
            height: 20px;
            background: radial-gradient(circle, #ffff00, #ff8800, transparent);
            border-radius: 50%;
            pointer-events: none;
            z-index: 15;
            display: none;
        }
        
        /* 后坐力效果 */
        .recoilEffect {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 25;
            opacity: 0;
        }
        
        /* --- 触控按钮 --- */
        .touch-controls {
            position: absolute;
            bottom: 0;
            width: 100%;
            height: 40%;
            pointer-events: none;
            z-index: 40;
        }

        #joystick-area {
            position: absolute;
            left: 0;
            bottom: 0;
            width: 30%;
            height: 100%;
            pointer-events: auto;
        }

        #joystick-base {
            position: absolute;
            width: 80px;
            height: 80px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 50%;
            bottom: 50px;
            left: 50px;
            backdrop-filter: blur(5px);
            border: 2px solid rgba(255, 255, 255, 0.3);
        }

        #joystick-thumb {
            position: absolute;
            width: 40px;
            height: 40px;
            background: rgba(255, 255, 255, 0.5);
            border-radius: 50%;
            top: 20px;
            left: 20px;
            transition: transform 0.1s;
        }

        #buttons-area {
            position: absolute;
            right: 0;
            bottom: 0;
            width: 70%;
            height: 100%;
            pointer-events: none;
        }

        .touch-button {
            position: absolute;
            width: 70px;
            height: 70px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 50%;
            backdrop-filter: blur(5px);
            border: 2px solid rgba(255, 255, 255, 0.3);
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 12px;
            color: white;
            pointer-events: auto;
            user-select: none;
            touch-action: manipulation;
            text-align: center;
            line-height: 1.2;
        }

        #shoot-btn {
            bottom: 50px;
            right: 100px;
            background: rgba(255, 0, 0, 0.3);
        }

        #aim-btn {
            bottom: 150px;
            right: 50px;
            background: rgba(0, 255, 0, 0.3);
        }

        #reload-btn {
            bottom: 250px;
            right: 100px;
            background: rgba(255, 255, 0, 0.3);
            font-size: 10px;
        }
        
        #firemode-btn {
            bottom: 50px;
            right: 200px;
            background: rgba(0, 100, 255, 0.3);
            font-size: 10px;
        }
        
        .touch-button:active {
            background: rgba(255, 255, 255, 0.5);
            transform: scale(0.95);
        }
        
        /* 固定文字标识 */
        .button-label {
            position: absolute;
            font-size: 12px;
            color: rgba(255, 255, 255, 0.8);
            text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
            pointer-events: none;
            z-index: 41;
            font-family: Arial, sans-serif;
        }
        
        #shoot-label {
            bottom: 30px;
            right: 115px;
        }
        
        #aim-label {
            bottom: 130px;
            right: 65px;
        }
        
        #reload-label {
            bottom: 230px;
            right: 115px;
        }
        
        #firemode-label {
            bottom: 30px;
            right: 215px;
        }
        
        #joystick-label {
            bottom: 30px;
            left: 65px;
        }
        
        @media (hover: hover) and (pointer: fine) {
            .touch-controls {
                display: none;
            }
            #instructions {
                display: block;
            }
        }
        
        @media (hover: none) and (pointer: coarse) {
            .touch-controls {
                display: block;
            }
            #instructions {
                display: none;
            }
        }
        
    </style>
</head>
<body>
    <div id="gameContainer">
        <!-- 准星 -->
        <div id="crosshair">
            <div class="crosshair-dot"></div>
            <div class="crosshair-line line-h"></div>
            <div class="crosshair-line line-v"></div>
        </div>
        
        <!-- M4A1枪械模型 -->
        <div id="weaponModel">
            <div class="weapon-stock"></div>
            <div class="weapon-body"></div>
            <div class="weapon-handguard"></div>
            <div class="weapon-barrel"></div>
            <div class="weapon-sight"></div>
            <div class="weapon-magazine"></div>
        </div>
        
        <!-- 瞄准时镜 -->
        <div id="scopeOverlay">
            <div id="scopeReticle">
                <div class="reticle-center"></div>
                <div class="reticle-line-h"></div>
                <div class="reticle-line-v"></div>
                <div class="distance-mark" style="top: 30%; left: 50%; transform: translate(-50%, -50%);">100M</div>
                <div class="distance-mark" style="top: 20%; left: 50%; transform: translate(-50%, -50%);">200M</div>
                <div class="distance-mark" style="top: 10%; left: 50%; transform: translate(-50%, -50%);">300M</div>
            </div>
        </div>
        
        <!-- 枪口闪光 -->
        <div id="muzzleFlash" class="muzzleFlash"></div>
        
        <!-- 后坐力效果 -->
        <div id="recoilEffect" class="recoilEffect"></div>
        
        <!-- UI面板 -->
        <div id="uiPanel">
            <div id="ammoDisplay">弹药: 30/90</div>
            <div id="weaponName">M4A1 突击步枪</div>
            <div id="fireModeDisplay">射击模式: 单发</div>
            <div>倍镜: 4倍瞄准镜</div>
        </div>
        
        <!-- 操作说明 -->
        <div id="instructions">
            <div>鼠标右键: 开镜瞄准 | 鼠标左键: 射击 | R键: 装弹 | B键: 切换射击模式 | ESC: 退出</div>
        </div>
        
        <!-- 固定文字标识 -->
        <div class="button-label" id="shoot-label">射击</div>
        <div class="button-label" id="aim-label">瞄准</div>
        <div class="button-label" id="reload-label">装弹</div>
        <div class="button-label" id="firemode-label">模式</div>
        <div class="button-label" id="joystick-label">移动</div>
        
        <!-- 触控按钮 -->
        <div class="touch-controls">
            <div id="joystick-area">
                <div id="joystick-base">
                    <div id="joystick-thumb"></div>
                </div>
            </div>
            <div id="buttons-area">
                <div id="shoot-btn" class="touch-button">射击</div>
                <div id="aim-btn" class="touch-button">瞄准</div>
                <div id="reload-btn" class="touch-button">装弹(R)</div>
                <div id="firemode-btn" class="touch-button">模式(B)</div>
            </div>
        </div>
    </div>

    <script>
        class ScopeSimulator {
            constructor() {
                this.isAiming = false;
                this.ammo = 30;
                this.totalAmmo = 90;
                this.recoilAmount = 0;
                this.scopeFOV = 15;
                this.normalFOV = 60;
                
                // 射击模式: 0-单发, 1-三连发, 2-全自动
                this.fireMode = 0;
                this.fireModeNames = ['单发', '三连发', '全自动'];
                this.burstCount = 0;
                this.burstTimer = null;
                
                this.isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
                this.joystickData = { active: false, x: 0, y: 0 };
                
                this.init();
            }
            
            init() {
                this.setupEventListeners();
                this.setupTouchControls();
                this.createTargets();
                this.gameLoop();
            }
            
            setupEventListeners() {
                // 鼠标控制
                document.addEventListener('mousedown', (e) => {
                    if (e.button === 2) {
                        this.aim(true);
                    } else if (e.button === 0) {
                        this.handleMouseShoot();
                    }
                });
                
                document.addEventListener('mouseup', (e) => {
                    if (e.button === 2) {
                        this.aim(false);
                    } else if (e.button === 0) {
                        this.stopShooting();
                    }
                });
                
                document.addEventListener('contextmenu', (e) => {
                    e.preventDefault();
                });
                
                // 键盘控制
                document.addEventListener('keydown', (e) => {
                    if (e.key.toLowerCase() === 'r') {
                        this.reload();
                    } else if (e.key.toLowerCase() === 'b') {
                        this.switchFireMode();
                    } else if (e.key === 'Escape') {
                        this.exitGame();
                    }
                });
                
                document.addEventListener('keyup', (e) => {
                    if (e.key === ' ') {
                        this.stopShooting();
                    }
                });
            }
            
            handleMouseShoot() {
                switch(this.fireMode) {
                    case 0: // 单发
                        this.shoot();
                        break;
                    case 1: // 三连发
                        this.startBurstFire();
                        break;
                    case 2: // 全自动
                        this.startAutoFire();
                        break;
                }
            }
            
            setupTouchControls() {
                if (!this.isTouchDevice) return;
                
                const aimBtn = document.getElementById('aim-btn');
                const shootBtn = document.getElementById('shoot-btn');
                const reloadBtn = document.getElementById('reload-btn');
                const firemodeBtn = document.getElementById('firemode-btn');
                const joystickBase = document.getElementById('joystick-base');
                const joystickThumb = document.getElementById('joystick-thumb');
                
                // 瞄准按钮
                let aimTouchId = null;
                aimBtn.addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    if (aimTouchId === null) {
                        aimTouchId = e.changedTouches[0].identifier;
                        this.aim(true);
                        aimBtn.style.background = 'rgba(0, 255, 0, 0.6)';
                    }
                });
                
                aimBtn.addEventListener('touchend', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === aimTouchId) {
                            aimTouchId = null;
                            this.aim(false);
                            aimBtn.style.background = 'rgba(0, 255, 0, 0.3)';
                            break;
                        }
                    }
                });
                
                aimBtn.addEventListener('touchcancel', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === aimTouchId) {
                            aimTouchId = null;
                            this.aim(false);
                            aimBtn.style.background = 'rgba(0, 255, 0, 0.3)';
                            break;
                        }
                    }
                });
                
                // 射击按钮
                let shootTouchId = null;
                shootBtn.addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    if (shootTouchId === null) {
                        shootTouchId = e.changedTouches[0].identifier;
                        this.handleTouchShoot();
                        shootBtn.style.background = 'rgba(255, 0, 0, 0.6)';
                    }
                });
                
                const endShoot = () => {
                    shootTouchId = null;
                    this.stopShooting();
                    shootBtn.style.background = 'rgba(255, 0, 0, 0.3)';
                };

                shootBtn.addEventListener('touchend', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === shootTouchId) {
                            endShoot();
                            break;
                        }
                    }
                });
                
                shootBtn.addEventListener('touchcancel', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === shootTouchId) {
                            endShoot();
                            break;
                        }
                    }
                });
                
                // 装弹按钮
                reloadBtn.addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    this.reload();
                    reloadBtn.style.background = 'rgba(255, 255, 0, 0.6)';
                    setTimeout(() => {
                        reloadBtn.style.background = 'rgba(255, 255, 0, 0.3)';
                    }, 100);
                });
                
                // 射击模式切换按钮
                firemodeBtn.addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    this.switchFireMode();
                    firemodeBtn.style.background = 'rgba(0, 100, 255, 0.6)';
                    setTimeout(() => {
                        firemodeBtn.style.background = 'rgba(0, 100, 255, 0.3)';
                    }, 100);
                });
                
                // 虚拟摇杆
                const baseRect = joystickBase.getBoundingClientRect();
                const baseCenterX = baseRect.left + baseRect.width / 2;
                const baseCenterY = baseRect.top + baseRect.height / 2;
                const baseRadius = baseRect.width / 2;
                let joystickTouchId = null;
                
                joystickBase.addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    if (joystickTouchId === null) {
                        const touch = e.changedTouches[0];
                        joystickTouchId = touch.identifier;
                        this.handleJoystickMove(touch);
                    }
                });
                
                document.addEventListener('touchmove', (e) => {
                    e.preventDefault();
                    if (joystickTouchId !== null) {
                        for (let touch of e.changedTouches) {
                            if (touch.identifier === joystickTouchId) {
                                this.handleJoystickMove(touch);
                                break;
                            }
                        }
                    }
                });
                
                const endJoystick = () => {
                    joystickTouchId = null;
                    this.joystickData.active = false;
                    this.joystickData.x = 0;
                    this.joystickData.y = 0;
                    joystickThumb.style.transform = 'translate(0px, 0px)';
                };
                
                document.addEventListener('touchend', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === joystickTouchId) {
                            endJoystick();
                            break;
                        }
                    }
                });
                
                document.addEventListener('touchcancel', (e) => {
                    e.preventDefault();
                    for (let touch of e.changedTouches) {
                        if (touch.identifier === joystickTouchId) {
                            endJoystick();
                            break;
                        }
                    }
                });
                
                document.getElementById('joystick-area').addEventListener('touchstart', (e) => {
                    e.preventDefault();
                    if (joystickTouchId === null && e.target === joystickBase) {
                        const touch = e.changedTouches[0];
                        joystickTouchId = touch.identifier;
                        this.handleJoystickMove(touch);
                    }
                });
            }
            
            handleJoystickMove(touch) {
                const joystickBase = document.getElementById('joystick-base');
                const joystickThumb = document.getElementById('joystick-thumb');
                const baseRect = joystickBase.getBoundingClientRect();
                const baseCenterX = baseRect.left + baseRect.width / 2;
                const baseCenterY = baseRect.top + baseRect.height / 2;
                const baseRadius = baseRect.width / 2;
                
                let deltaX = touch.clientX - baseCenterX;
                let deltaY = touch.clientY - baseCenterY;
                const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
                
                if (distance > baseRadius) {
                    const angle = Math.atan2(deltaY, deltaX);
                    deltaX = Math.cos(angle) * baseRadius;
                    deltaY = Math.sin(angle) * baseRadius;
                }
                
                joystickThumb.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
                
                this.joystickData.active = true;
                this.joystickData.x = deltaX / baseRadius;
                this.joystickData.y = deltaY / baseRadius;
            }
            
            handleTouchShoot() {
                switch(this.fireMode) {
                    case 0: // 单发
                        this.shoot();
                        break;
                    case 1: // 三连发
                        this.startBurstFire();
                        break;
                    case 2: // 全自动
                        this.startAutoFire();
                        break;
                }
            }
            
            startBurstFire() {
                if (this.burstCount < 3 && this.ammo > 0) {
                    this.shoot();
                    this.burstCount++;
                    if (this.burstCount < 3) {
                        this.burstTimer = setTimeout(() => {
                            this.startBurstFire();
                        }, 100);
                    }
                }
            }
            
            startAutoFire() {
                this.autoFireTimer = setInterval(() => {
                    if (this.ammo > 0) {
                        this.shoot();
                    } else {
                        this.stopShooting();
                    }
                }, 100);
            }
            
            stopShooting() {
                if (this.burstTimer) {
                    clearTimeout(this.burstTimer);
                    this.burstTimer = null;
                }
                if (this.autoFireTimer) {
                    clearInterval(this.autoFireTimer);
                    this.autoFireTimer = null;
                }
                this.burstCount = 0;
            }
            
            switchFireMode() {
                this.fireMode = (this.fireMode + 1) % 3;
                document.getElementById('fireModeDisplay').textContent = `射击模式: ${this.fireModeNames[this.fireMode]}`;
                this.stopShooting();
            }
            
            aim(aiming) {
                this.isAiming = aiming;
                const scopeOverlay = document.getElementById('scopeOverlay');
                const crosshair = document.getElementById('crosshair');
                const gameContainer = document.getElementById('gameContainer');
                
                if (aiming) {
                    scopeOverlay.style.display = 'block';
                    crosshair.style.display = 'none';
                    gameContainer.style.transform = 'scale(1.2)';
                    gameContainer.style.transformOrigin = 'center center';
                    this.addBreathEffect();
                } else {
                    scopeOverlay.style.display = 'none';
                    crosshair.style.display = 'block';
                    gameContainer.style.transform = 'scale(1)';
                    this.clearBreathEffect();
                }
            }
            
            addBreathEffect() {
                let breathIntensity = 0;
                const scopeReticle = document.getElementById('scopeReticle');
                
                const breathInterval = setInterval(() => {
                    if (!this.isAiming) {
                        clearInterval(breathInterval);
                        return;
                    }
                    
                    breathIntensity += 0.1;
                    const offsetX = Math.sin(breathIntensity) * 2;
                    const offsetY = Math.cos(breathIntensity * 0.7) * 1;
                    
                    scopeReticle.style.transform = `translate(calc(-50% + ${offsetX}px), calc(-50% + ${offsetY}px))`;
                }, 50);
                
                this.breathInterval = breathInterval;
            }
            
            clearBreathEffect() {
                if (this.breathInterval) {
                    clearInterval(this.breathInterval);
                    const scopeReticle = document.getElementById('scopeReticle');
                    scopeReticle.style.transform = 'translate(-50%, -50%)';
                }
            }
            
            shoot() {
                if (this.ammo <= 0) {
                    this.playDryFire();
                    return;
                }
                
                this.ammo--;
                this.updateAmmoDisplay();
                this.muzzleFlash();
                this.recoil();
                
                if (this.isAiming) {
                    this.highAccuracyShot();
                } else {
                    this.normalShot();
                }
            }
            
            muzzleFlash() {
                const flash = document.getElementById('muzzleFlash');
                const crosshair = document.getElementById('crosshair');
                
                if (this.isAiming) {
                    flash.style.left = '50%';
                    flash.style.top = '50%';
                } else {
                    const rect = crosshair.getBoundingClientRect();
                    flash.style.left = rect.left + rect.width/2 + 'px';
                    flash.style.top = rect.top + rect.height/2 + 'px';
                }
                
                flash.style.display = 'block';
                setTimeout(() => {
                    flash.style.display = 'none';
                }, 30);
            }
            
            recoil() {
                const recoilEffect = document.getElementById('recoilEffect');
                const scopeReticle = document.getElementById('scopeReticle');
                
                recoilEffect.style.opacity = '0.3';
                recoilEffect.style.backgroundColor = 'rgba(255, 255, 255, 0.3)';
                
                setTimeout(() => {
                    recoilEffect.style.opacity = '0';
                    recoilEffect.style.backgroundColor = 'transparent';
                }, 50);
                
                if (this.isAiming) {
                    const currentTransform = scopeReticle.style.transform || 'translate(-50%, -50%)';
                    scopeReticle.style.transform = currentTransform + ' translateY(-10px)';
                    
                    setTimeout(() => {
                        scopeReticle.style.transform = currentTransform;
                    }, 100);
                } else {
                    const crosshair = document.getElementById('crosshair');
                    crosshair.style.transform = 'translate(-50%, -60%)';
                    
                    setTimeout(() => {
                        crosshair.style.transform = 'translate(-50%, -50%)';
                    }, 150);
                }
            }
            
            highAccuracyShot() {
                console.log('高精度射击 - 瞄准状态下');
                this.checkHit(true);
            }
            
            normalShot() {
                console.log('正常射击');
                this.checkHit(false);
            }
            
            checkHit(isAimed) {
                const targets = document.querySelectorAll('#targetPractice');
                const crosshair = document.getElementById('crosshair');
                const crosshairRect = crosshair.getBoundingClientRect();
                
                targets.forEach(target => {
                    const targetRect = target.getBoundingClientRect();
                    const distance = Math.sqrt(
                        Math.pow(targetRect.left + targetRect.width/2 - (crosshairRect.left + crosshairRect.width/2), 2) +
                        Math.pow(targetRect.top + targetRect.height/2 - (crosshairRect.top + crosshairRect.height/2), 2)
                    );
                    
                    const maxDistance = isAimed ? 50 : 100;
                    
                    if (distance < maxDistance) {
                        target.style.backgroundColor = '#00ff00';
                        setTimeout(() => {
                            if (target.parentNode) {
                                target.remove();
                                this.createTarget();
                            }
                        }, 200);
                    }
                });
            }
            
            createTargets() {
                for (let i = 0; i < 5; i++) {
                    this.createTarget();
                }
            }
            
            createTarget() {
                const target = document.createElement('div');
                target.id = 'targetPractice';
                target.style.left = Math.random() * (window.innerWidth - 100) + 50 + 'px';
                target.style.top = Math.random() * (window.innerHeight - 200) + 100 + 'px';
                
                target.addEventListener('click', () => {
                    target.style.backgroundColor = '#00ff00';
                    setTimeout(() => {
                        if (target.parentNode) {
                            target.remove();
                            this.createTarget();
                        }
                    }, 200);
                });
                
                document.getElementById('gameContainer').appendChild(target);
            }
            
            reload() {
                if (this.totalAmmo <= 0) return;
                
                const reloadAmount = Math.min(30 - this.ammo, this.totalAmmo);
                this.ammo += reloadAmount;
                this.totalAmmo -= reloadAmount;
                
                this.updateAmmoDisplay();
                
                const weaponName = document.getElementById('weaponName');
                const originalText = weaponName.textContent;
                weaponName.textContent = '装弹中...';
                weaponName.style.color = '#ffff00';
                
                setTimeout(() => {
                    weaponName.textContent = originalText;
                    weaponName.style.color = '#00ff00';
                }, 1000);
            }
            
            playDryFire() {
                console.log('咔嚓! 子弹用完了');
            }
            
            updateAmmoDisplay() {
                document.getElementById('ammoDisplay').textContent = `弹药: ${this.ammo}/${this.totalAmmo}`;
            }
            
            exitGame() {
                if (confirm('确定要退出游戏吗?')) {
                    alert('游戏已退出');
                }
            }
            
            gameLoop() {
                requestAnimationFrame(() => this.gameLoop());
                this.updateScopeStability();
            }
            
            updateScopeStability() {
                if (this.isAiming) {
                }
            }
        }
        
        window.addEventListener('load', () => {
            const simulator = new ScopeSimulator();
            
            window.addEventListener('resize', () => {
            });
        });
    </script>
</body>
</html>
        
编辑器加载中
预览
控制台