2026/2/16 16:14:27
网站建设
项目流程
网站注销备案查询系统,开发公司工程队营销的支持,商丘网站制作案例,海南北京网站建设基于Canvas的射击游戏#xff0c;包含灵活移动的敌人和可升级的枪械系统。
游戏功能说明 核心玩法#xff1a; 使用WASD或方向键控制玩家移动 鼠标点击射击#xff08;无限弹药#xff09; 击败敌人获得金币和分数 每波敌人数量会增加#xff0c;难度提升 敌人AI系统…基于Canvas的射击游戏包含灵活移动的敌人和可升级的枪械系统。游戏功能说明核心玩法使用WASD或方向键控制玩家移动鼠标点击射击无限弹药击败敌人获得金币和分数每波敌人数量会增加难度提升敌人AI系统敌人有三种类型普通、快速和坦克型敌人具有智能行为巡逻、追逐玩家、躲避子弹不同类型的敌人有不同的速度、生命值和奖励枪械升级系统伤害升级增加子弹伤害射速升级减少射击间隔子弹速度升级增加子弹飞行速度散射升级一次发射多颗子弹移动设备支持触摸拖动控制玩家移动屏幕按钮进行射击和升级自适应不同屏幕尺寸视觉效果粒子效果射击、爆炸、击中敌人血条显示背景网格增强空间感枪械发光效果游戏已完全实现可以直接复制上面的代码到一个HTML文件中然后在浏览器中打开即可开始游戏!DOCTYPE html html langzh head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title无限弹药升级枪械 - 射击游戏/title style * { margin: 0; padding: 0; box-sizing: border-box; font-family: Arial, sans-serif; } body { background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); color: #fff; min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 20px; overflow-x: hidden; } .header { text-align: center; margin-bottom: 20px; width: 100%; max-width: 800px; } h1 { color: #ffcc00; font-size: 2.8rem; margin-bottom: 10px; text-shadow: 0 0 10px rgba(255, 204, 0, 0.5); } .subtitle { color: #4dabf7; font-size: 1.2rem; margin-bottom: 25px; } .game-container { display: flex; flex-direction: column; align-items: center; gap: 20px; max-width: 1200px; width: 100%; } .stats-panel { display: flex; justify-content: space-between; width: 100%; max-width: 800px; background: rgba(0, 20, 40, 0.8); padding: 15px; border-radius: 12px; border: 2px solid #4dabf7; margin-bottom: 10px; } .stat-item { display: flex; flex-direction: column; align-items: center; } .stat-label { font-size: 0.9rem; color: #a5d8ff; margin-bottom: 5px; } .stat-value { font-size: 1.5rem; font-weight: bold; color: #ffcc00; } .main-area { display: flex; gap: 20px; width: 100%; justify-content: center; flex-wrap: wrap; } .game-canvas-container { position: relative; border-radius: 12px; overflow: hidden; box-shadow: 0 0 25px rgba(0, 100, 255, 0.3); border: 3px solid #4dabf7; } canvas { display: block; background-color: #0a1929; } .controls-panel { background: rgba(0, 20, 40, 0.8); padding: 20px; border-radius: 12px; border: 2px solid #4dabf7; width: 300px; min-height: 500px; } .controls-title { color: #ffcc00; font-size: 1.5rem; margin-bottom: 20px; text-align: center; border-bottom: 1px solid #4dabf7; padding-bottom: 10px; } .control-section { margin-bottom: 25px; } .section-title { color: #4dabf7; font-size: 1.2rem; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; } .section-title i { color: #ffcc00; } .upgrade-item { background: rgba(255, 255, 255, 0.1); border-radius: 8px; padding: 12px; margin-bottom: 12px; border-left: 4px solid #4dabf7; transition: all 0.3s; } .upgrade-item:hover { background: rgba(255, 255, 255, 0.15); transform: translateY(-2px); } .upgrade-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .upgrade-name { font-weight: bold; color: #fff; } .upgrade-level { color: #ffcc00; font-weight: bold; background: rgba(255, 204, 0, 0.2); padding: 2px 8px; border-radius: 10px; font-size: 0.9rem; } .upgrade-cost { color: #a5d8ff; font-size: 0.9rem; margin-bottom: 10px; } .upgrade-btn { background: linear-gradient(to right, #4dabf7, #339af0); color: white; border: none; border-radius: 6px; padding: 8px 12px; width: 100%; cursor: pointer; font-weight: bold; transition: all 0.3s; } .upgrade-btn:hover { background: linear-gradient(to right, #339af0, #228be6); transform: scale(1.05); } .upgrade-btn:disabled { background: #6c757d; cursor: not-allowed; transform: none; } .instructions { background: rgba(0, 20, 40, 0.8); padding: 20px; border-radius: 12px; border: 2px solid #4dabf7; width: 100%; max-width: 800px; margin-top: 10px; } .instructions h3 { color: #ffcc00; margin-bottom: 15px; font-size: 1.4rem; } .instructions ul { list-style-type: none; padding-left: 10px; } .instructions li { margin-bottom: 10px; padding-left: 25px; position: relative; } .instructions li:before { content: •; color: #4dabf7; font-size: 1.5rem; position: absolute; left: 0; top: -5px; } .key { display: inline-block; background: rgba(255, 255, 255, 0.1); border: 1px solid #4dabf7; border-radius: 4px; padding: 2px 8px; margin: 0 5px; font-family: monospace; } .mobile-controls { display: none; margin-top: 20px; flex-direction: column; align-items: center; gap: 10px; } .mobile-buttons { display: flex; gap: 20px; } .mobile-btn { background: rgba(77, 171, 247, 0.7); color: white; border: none; border-radius: 50%; width: 70px; height: 70px; font-size: 24px; display: flex; align-items: center; justify-content: center; cursor: pointer; user-select: none; } media (max-width: 768px) { .main-area { flex-direction: column; align-items: center; } .controls-panel { width: 100%; max-width: 800px; } .mobile-controls { display: flex; } } media (max-width: 480px) { h1 { font-size: 2rem; } .stats-panel { flex-wrap: wrap; justify-content: center; gap: 15px; } .game-canvas-container { width: 95vw; height: 60vh; } canvas { width: 100%; height: 100%; } } /style link relstylesheet hrefhttps://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css /head body div classheader h1i classfas fa-crosshairs/i 无限弹药射击游戏/h1 p classsubtitle击败敌人收集金币升级你的枪械/p /div div classgame-container div classstats-panel div classstat-item div classstat-label分数/div div classstat-value idscore0/div /div div classstat-item div classstat-label金币/div div classstat-value idcoins100/div /div div classstat-item div classstat-label枪械等级/div div classstat-value idgun-level1/div /div div classstat-item div classstat-label击杀数/div div classstat-value idkills0/div /div div classstat-item div classstat-label敌人数量/div div classstat-value idenemies5/div /div /div div classmain-area div classgame-canvas-container canvas idgameCanvas width800 height500/canvas /div div classcontrols-panel h2 classcontrols-titlei classfas fa-tools/i 枪械升级系统/h2 div classcontrol-section h3 classsection-titlei classfas fa-gun/i 当前枪械属性/h3 div classupgrade-item div classupgrade-header span classupgrade-name伤害/span span classupgrade-level iddamage-level1级/span /div div classupgrade-cost下一级: span iddamage-cost50/span 金币/div button classupgrade-btn idupgrade-damage升级伤害/button /div div classupgrade-item div classupgrade-header span classupgrade-name射速/span span classupgrade-level idfire-rate-level1级/span /div div classupgrade-cost下一级: span idfire-rate-cost50/span 金币/div button classupgrade-btn idupgrade-fire-rate升级射速/button /div div classupgrade-item div classupgrade-header span classupgrade-name子弹速度/span span classupgrade-level idbullet-speed-level1级/span /div div classupgrade-cost下一级: span idbullet-speed-cost50/span 金币/div button classupgrade-btn idupgrade-bullet-speed升级子弹速度/button /div /div div classcontrol-section h3 classsection-titlei classfas fa-bolt/i 特殊能力/h3 div classupgrade-item div classupgrade-header span classupgrade-name散射/span span classupgrade-level idspread-level0级/span /div div classupgrade-cost解锁/升级: span idspread-cost200/span 金币/div button classupgrade-btn idupgrade-spread升级散射/button /div /div /div /div div classmobile-controls div classmobile-buttons div classmobile-btn idmobile-shooti classfas fa-fire/i/div div classmobile-btn idmobile-upgradei classfas fa-arrow-up/i/div /div p在手机上使用手指拖动控制玩家移动/p /div div classinstructions h3i classfas fa-info-circle/i 游戏指南/h3 ul listrong移动控制/strong: 使用 span classkeyWASD/span 或 span classkey方向键/span 移动玩家在手机上用手指拖动屏幕/li listrong射击/strong: 使用 span classkey鼠标左键/span 或 span classkey触摸/span 射击鼠标/触摸指向射击方向/li listrong敌人AI/strong: 敌人会智能追踪玩家并躲避子弹具有不同移动模式/li listrong升级系统/strong: 击败敌人获得金币用于升级枪械属性/li listrong游戏目标/strong: 获得尽可能高的分数每波敌人会增加难度/li /ul /div /div script // 游戏主逻辑 document.addEventListener(DOMContentLoaded, () { const canvas document.getElementById(gameCanvas); const ctx canvas.getContext(2d); // 游戏状态 let gameRunning true; let score 0; let coins 100; let kills 0; let wave 1; let enemiesRemaining 5; // 枪械属性 let gunLevel 1; let damage 1; let fireRate 500; // 毫秒 let bulletSpeed 8; let bulletSpread 0; // 散射等级 let lastShot 0; // 升级成本 const upgradeCosts { damage: 50, fireRate: 50, bulletSpeed: 50, spread: 200 }; // 升级等级 const upgradeLevels { damage: 1, fireRate: 1, bulletSpeed: 1, spread: 0 }; // 玩家对象 const player { x: canvas.width / 2, y: canvas.height / 2, radius: 20, speed: 5, color: #4dabf7, borderColor: #339af0, isMoving: false, moveDirection: { x: 0, y: 0 } }; // 子弹数组 let bullets []; // 敌人数组 let enemies []; // 粒子效果数组用于爆炸等 let particles []; // 初始化敌人 function initEnemies(count) { enemies []; for (let i 0; i count; i) { // 随机生成敌人位置确保不在玩家附近 let x, y; do { x Math.random() * (canvas.width - 60) 30; y Math.random() * (canvas.height - 60) 30; } while (Math.hypot(x - player.x, y - player.y) 150); // 随机选择敌人类型 const enemyType Math.random() 0.7 ? fast : Math.random() 0.5 ? tank : normal; let enemy { x, y, radius: enemyType tank ? 25 : enemyType fast ? 15 : 20, speed: enemyType fast ? 2.5 : enemyType tank ? 1.2 : 1.8, color: enemyType tank ? #ff6b6b : enemyType fast ? #51cf66 : #ffa94d, borderColor: enemyType tank ? #ff5252 : enemyType fast ? #40c057 : #ff922b, health: enemyType tank ? 3 : 1, maxHealth: enemyType tank ? 3 : 1, type: enemyType, // 敌人AI状态 aiState: patrol, // patrol, chase, evade patrolTarget: { x: Math.random() * canvas.width, y: Math.random() * canvas.height }, patrolChangeTime: 0, evadeTime: 0 }; enemies.push(enemy); } enemiesRemaining enemies.length; updateEnemiesCount(); } // 绘制玩家 function drawPlayer() { // 绘制玩家主体 ctx.beginPath(); ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2); ctx.fillStyle player.color; ctx.fill(); // 绘制玩家边框 ctx.lineWidth 3; ctx.strokeStyle player.borderColor; ctx.stroke(); // 绘制玩家方向指示器 ctx.beginPath(); ctx.moveTo(player.x, player.y); ctx.lineTo(player.x player.radius * 1.5, player.y); ctx.lineWidth 3; ctx.strokeStyle #ffcc00; ctx.stroke(); // 绘制玩家枪械 ctx.beginPath(); ctx.rect(player.x player.radius - 5, player.y - 5, 15, 10); ctx.fillStyle #868e96; ctx.fill(); ctx.strokeStyle #495057; ctx.lineWidth 2; ctx.stroke(); } // 绘制子弹 function drawBullets() { bullets.forEach((bullet, index) { // 移除超出画布的子弹 if (bullet.x 0 || bullet.x canvas.width || bullet.y 0 || bullet.y canvas.height) { bullets.splice(index, 1); return; } // 更新子弹位置 bullet.x bullet.vx; bullet.y bullet.vy; // 绘制子弹 ctx.beginPath(); ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2); ctx.fillStyle bullet.color; ctx.fill(); // 子弹发光效果 ctx.beginPath(); ctx.arc(bullet.x, bullet.y, bullet.radius 2, 0, Math.PI * 2); ctx.fillStyle rgba(255, 204, 0, 0.3); ctx.fill(); }); } // 绘制敌人 function drawEnemies() { enemies.forEach((enemy, index) { // 更新敌人位置AI逻辑 updateEnemyAI(enemy); // 绘制敌人主体 ctx.beginPath(); ctx.arc(enemy.x, enemy.y, enemy.radius, 0, Math.PI * 2); ctx.fillStyle enemy.color; ctx.fill(); // 绘制敌人边框 ctx.lineWidth 2; ctx.strokeStyle enemy.borderColor; ctx.stroke(); // 绘制敌人眼睛使其看起来更有敌意 ctx.beginPath(); ctx.arc(enemy.x - enemy.radius/3, enemy.y - enemy.radius/4, enemy.radius/4, 0, Math.PI * 2); ctx.arc(enemy.x enemy.radius/3, enemy.y - enemy.radius/4, enemy.radius/4, 0, Math.PI * 2); ctx.fillStyle #ffffff; ctx.fill(); // 绘制血条如果敌人有多个生命值 if (enemy.maxHealth 1) { const barWidth enemy.radius * 2; const barHeight 5; const barX enemy.x - enemy.radius; const barY enemy.y - enemy.radius - 10; // 血条背景 ctx.fillStyle rgba(0, 0, 0, 0.5); ctx.fillRect(barX, barY, barWidth, barHeight); // 当前血量 const healthPercent enemy.health / enemy.maxHealth; ctx.fillStyle healthPercent 0.5 ? #51cf66 : healthPercent 0.25 ? #ff922b : #ff6b6b; ctx.fillRect(barX, barY, barWidth * healthPercent, barHeight); } }); } // 更新敌人AI function updateEnemyAI(enemy) { const distanceToPlayer Math.hypot(player.x - enemy.x, player.y - enemy.y); // 检查是否有子弹接近 let bulletTooClose false; bullets.forEach(bullet { const distanceToBullet Math.hypot(bullet.x - enemy.x, bullet.y - enemy.y); if (distanceToBullet 80) { bulletTooClose true; } }); // 状态转换逻辑 if (bulletTooClose enemy.aiState ! evade) { enemy.aiState evade; enemy.evadeTime Date.now() 1000; // 躲避1秒 } else if (distanceToPlayer 150 enemy.aiState ! chase !bulletTooClose) { enemy.aiState chase; } else if (enemy.aiState patrol Date.now() enemy.patrolChangeTime) { // 定期更改巡逻目标 enemy.patrolTarget { x: Math.random() * canvas.width, y: Math.random() * canvas.height }; enemy.patrolChangeTime Date.now() 2000 Math.random() * 2000; } else if (enemy.aiState evade Date.now() enemy.evadeTime) { enemy.aiState patrol; enemy.patrolChangeTime Date.now() 1000; } // 根据状态行动 let targetX, targetY; switch(enemy.aiState) { case chase: // 追逐玩家 targetX player.x; targetY player.y; break; case evade: // 躲避玩家和子弹 targetX enemy.x (enemy.x - player.x); targetY enemy.y (enemy.y - player.y); break; case patrol: default: // 巡逻到目标点 targetX enemy.patrolTarget.x; targetY enemy.patrolTarget.y; break; } // 计算移动方向 const angle Math.atan2(targetY - enemy.y, targetX - enemy.x); let moveX Math.cos(angle) * enemy.speed; let moveY Math.sin(angle) * enemy.speed; // 躲避模式会更快移动 if (enemy.aiState evade) { moveX * 1.5; moveY * 1.5; } // 应用移动确保不超出边界 enemy.x moveX; enemy.y moveY; // 边界检查 enemy.x Math.max(enemy.radius, Math.min(canvas.width - enemy.radius, enemy.x)); enemy.y Math.max(enemy.radius, Math.min(canvas.height - enemy.radius, enemy.y)); } // 绘制粒子效果 function drawParticles() { particles.forEach((particle, index) { // 更新粒子 particle.x particle.vx; particle.y particle.vy; particle.alpha - 0.02; // 绘制粒子 ctx.globalAlpha particle.alpha; ctx.beginPath(); ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2); ctx.fillStyle particle.color; ctx.fill(); ctx.globalAlpha 1.0; // 移除消失的粒子 if (particle.alpha 0) { particles.splice(index, 1); } }); } // 碰撞检测 function checkCollisions() { // 检测子弹和敌人的碰撞 bullets.forEach((bullet, bulletIndex) { enemies.forEach((enemy, enemyIndex) { const distance Math.hypot(bullet.x - enemy.x, bullet.y - enemy.y); if (distance bullet.radius enemy.radius) { // 击中敌人 enemy.health - damage; // 创建击中效果粒子 for (let i 0; i 8; i) { particles.push({ x: enemy.x, y: enemy.y, radius: Math.random() * 3 2, color: enemy.color, vx: (Math.random() - 0.5) * 5, vy: (Math.random() - 0.5) * 5, alpha: 1.0 }); } // 移除子弹 bullets.splice(bulletIndex, 1); // 检查敌人是否被击败 if (enemy.health 0) { // 增加分数和金币 score enemy.type tank ? 30 : enemy.type fast ? 20 : 10; coins enemy.type tank ? 15 : enemy.type fast ? 10 : 5; kills; // 创建爆炸效果粒子 for (let i 0; i 15; i) { particles.push({ x: enemy.x, y: enemy.y, radius: Math.random() * 4 2, color: [#ffcc00, #ff922b, #ff6b6b][Math.floor(Math.random() * 3)], vx: (Math.random() - 0.5) * 8, vy: (Math.random() - 0.5) * 8, alpha: 1.0 }); } // 移除敌人 enemies.splice(enemyIndex, 1); enemiesRemaining enemies.length; updateEnemiesCount(); // 更新UI updateStats(); // 检查是否所有敌人都被击败 if (enemies.length 0) { wave; initEnemies(5 wave * 2); } } return; } }); }); // 检测敌人和玩家的碰撞 enemies.forEach(enemy { const distance Math.hypot(player.x - enemy.x, player.y - enemy.y); if (distance player.radius enemy.radius) { // 玩家受到伤害 score Math.max(0, score - 10); updateStats(); // 击退玩家 const angle Math.atan2(player.y - enemy.y, player.x - enemy.x); player.x Math.cos(angle) * 20; player.y Math.sin(angle) * 20; // 创建碰撞效果粒子 for (let i 0; i 10; i) { particles.push({ x: player.x, y: player.y, radius: Math.random() * 3 2, color: #4dabf7, vx: (Math.random() - 0.5) * 6, vy: (Math.random() - 0.5) * 6, alpha: 1.0 }); } } }); } // 射击函数 function shoot(targetX, targetY) { const currentTime Date.now(); if (currentTime - lastShot fireRate) return; lastShot currentTime; // 计算射击方向 const angle Math.atan2(targetY - player.y, targetX - player.x); // 根据散射等级创建子弹 const bulletCount bulletSpread 0 ? bulletSpread 1 : 1; for (let i 0; i bulletCount; i) { // 计算散射角度 const spreadAngle bulletSpread 0 ? angle (Math.random() - 0.5) * (bulletSpread * 0.2) : angle; // 创建子弹 bullets.push({ x: player.x Math.cos(angle) * player.radius, y: player.y Math.sin(angle) * player.radius, radius: 5, color: #ffcc00, vx: Math.cos(spreadAngle) * bulletSpeed, vy: Math.sin(spreadAngle) * bulletSpeed }); } // 创建枪口闪光粒子 for (let i 0; i 5; i) { particles.push({ x: player.x Math.cos(angle) * player.radius, y: player.y Math.sin(angle) * player.radius, radius: Math.random() * 3 2, color: #ffcc00, vx: Math.cos(angle) * (Math.random() * 3 2) (Math.random() - 0.5), vy: Math.sin(angle) * (Math.random() * 3 2) (Math.random() - 0.5), alpha: 1.0 }); } } // 更新游戏统计信息 function updateStats() { document.getElementById(score).textContent score; document.getElementById(coins).textContent coins; document.getElementById(kills).textContent kills; document.getElementById(gun-level).textContent gunLevel; // 更新升级按钮状态 document.getElementById(upgrade-damage).disabled coins upgradeCosts.damage; document.getElementById(upgrade-fire-rate).disabled coins upgradeCosts.fireRate; document.getElementById(upgrade-bullet-speed).disabled coins upgradeCosts.bulletSpeed; document.getElementById(upgrade-spread).disabled coins upgradeCosts.spread; } // 更新敌人数量显示 function updateEnemiesCount() { document.getElementById(enemies).textContent enemiesRemaining; } // 升级枪械属性 function upgradeGun(attribute) { if (coins upgradeCosts[attribute]) return; // 扣除金币 coins - upgradeCosts[attribute]; // 升级属性 switch(attribute) { case damage: damage 0.5; upgradeLevels.damage; document.getElementById(damage-level).textContent ${upgradeLevels.damage}级; upgradeCosts.damage Math.round(upgradeCosts.damage * 1.5); document.getElementById(damage-cost).textContent upgradeCosts.damage; break; case fireRate: fireRate Math.max(100, fireRate - 50); upgradeLevels.fireRate; document.getElementById(fire-rate-level).textContent ${upgradeLevels.fireRate}级; upgradeCosts.fireRate Math.round(upgradeCosts.fireRate * 1.5); document.getElementById(fire-rate-cost).textContent upgradeCosts.fireRate; break; case bulletSpeed: bulletSpeed 1; upgradeLevels.bulletSpeed; document.getElementById(bullet-speed-level).textContent ${upgradeLevels.bulletSpeed}级; upgradeCosts.bulletSpeed Math.round(upgradeCosts.bulletSpeed * 1.5); document.getElementById(bullet-speed-cost).textContent upgradeCosts.bulletSpeed; break; case spread: bulletSpread; upgradeLevels.spread; document.getElementById(spread-level).textContent ${upgradeLevels.spread}级; upgradeCosts.spread Math.round(upgradeCosts.spread * 2); document.getElementById(spread-cost).textContent upgradeCosts.spread; break; } // 更新枪械等级 gunLevel upgradeLevels.damage upgradeLevels.fireRate upgradeLevels.bulletSpeed upgradeLevels.spread; // 更新UI updateStats(); } // 设置升级按钮事件 document.getElementById(upgrade-damage).addEventListener(click, () upgradeGun(damage)); document.getElementById(upgrade-fire-rate).addEventListener(click, () upgradeGun(fireRate)); document.getElementById(upgrade-bullet-speed).addEventListener(click, () upgradeGun(bulletSpeed)); document.getElementById(upgrade-spread).addEventListener(click, () upgradeGun(spread)); // 移动控制 const keys {}; window.addEventListener(keydown, (e) { keys[e.key.toLowerCase()] true; player.isMoving true; // 更新移动方向 player.moveDirection.x 0; player.moveDirection.y 0; if (keys[w] || keys[arrowup]) player.moveDirection.y -1; if (keys[s] || keys[arrowdown]) player.moveDirection.y 1; if (keys[a] || keys[arrowleft]) player.moveDirection.x -1; if (keys[d] || keys[arrowright]) player.moveDirection.x 1; }); window.addEventListener(keyup, (e) { keys[e.key.toLowerCase()] false; // 检查是否还有移动键被按下 const movingKeys [w, a, s, d, arrowup, arrowdown, arrowleft, arrowright]; player.isMoving movingKeys.some(key keys[key]); // 更新移动方向 if (!player.isMoving) { player.moveDirection.x 0; player.moveDirection.y 0; } else { player.moveDirection.x 0; player.moveDirection.y 0; if (keys[w] || keys[arrowup]) player.moveDirection.y -1; if (keys[s] || keys[arrowdown]) player.moveDirection.y 1; if (keys[a] || keys[arrowleft]) player.moveDirection.x -1; if (keys[d] || keys[arrowright]) player.moveDirection.x 1; } }); // 鼠标控制射击 canvas.addEventListener(click, (e) { const rect canvas.getBoundingClientRect(); const targetX e.clientX - rect.left; const targetY e.clientY - rect.top; shoot(targetX, targetY); }); // 触摸控制移动设备 let touchX 0; let touchY 0; canvas.addEventListener(touchstart, (e) { e.preventDefault(); const rect canvas.getBoundingClientRect(); touchX e.touches[0].clientX - rect.left; touchY e.touches[0].clientY - rect.top; // 如果是右上角区域则视为射击否则视为移动 if (touchX canvas.width * 0.7 touchY canvas.height * 0.3) { shoot(touchX, touchY); } }); canvas.addEventListener(touchmove, (e) { e.preventDefault(); const rect canvas.getBoundingClientRect(); const newTouchX e.touches[0].clientX - rect.left; const newTouchY e.touches[0].clientY - rect.top; // 移动玩家 player.x newTouchX - touchX; player.y newTouchY - touchY; // 确保玩家在画布内 player.x Math.max(player.radius, Math.min(canvas.width - player.radius, player.x)); player.y Math.max(player.radius, Math.min(canvas.height - player.radius, player.y)); touchX newTouchX; touchY newTouchY; }); // 移动设备射击按钮 document.getElementById(mobile-shoot).addEventListener(touchstart, (e) { e.preventDefault(); // 射击朝向鼠标位置或屏幕中心 shoot(canvas.width / 2, canvas.height / 2); }); // 移动设备升级按钮 document.getElementById(mobile-upgrade).addEventListener(touchstart, (e) { e.preventDefault(); // 随机升级一个属性 const attributes [damage, fireRate, bulletSpeed, spread]; const randomAttr attributes[Math.floor(Math.random() * attributes.length)]; upgradeGun(randomAttr); }); // 游戏主循环 function gameLoop() { // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 绘制背景网格 drawGrid(); // 更新玩家位置 if (player.isMoving) { player.x player.moveDirection.x * player.speed; player.y player.moveDirection.y * player.speed; // 确保玩家在画布内 player.x Math.max(player.radius, Math.min(canvas.width - player.radius, player.x)); player.y Math.max(player.radius, Math.min(canvas.height - player.radius, player.y)); } // 绘制游戏对象 drawParticles(); drawBullets(); drawEnemies(); drawPlayer(); // 碰撞检测 checkCollisions(); // 继续游戏循环 if (gameRunning) { requestAnimationFrame(gameLoop); } } // 绘制背景网格 function drawGrid() { ctx.strokeStyle rgba(255, 255, 255, 0.05); ctx.lineWidth 1; // 垂直线 for (let x 0; x canvas.width; x 50) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } // 水平线 for (let y 0; y canvas.height; y 50) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } } // 初始化游戏 function initGame() { // 初始化敌人 initEnemies(5); // 更新UI updateStats(); // 启动游戏循环 gameLoop(); } // 开始游戏 initGame(); }); /script /body /html