body { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: #222; } #score { position: absolute; top: 20px; left: 20px; font-size: 24px; color: white; } #crosshair { position: absolute; width: 20px; height: 20px; background-color: red; border-radius: 50%; pointer-events: none; } スコア: 0 const canvas = document.getElementById("gameCanvas"); const ctx = canvas.getContext("2d"); const scoreText = document.getElementById("score"); const crosshair = document.getElementById("crosshair"); let score = 0; let bullets = []; let targets = []; let recoil = 0; let isShooting = false; let isScoped = false; let crosshairSize = 20; // プレイヤーの銃 const gun = { x: 400, y: 500, width: 50, height: 20, recoilSpeed: 10 }; // 弾のオブジェクト function Bullet(x, y, speedX, speedY) { this.x = x; this.y = y; this.speedX = speedX; this.speedY = speedY; this.radius = 5; this.active = true; } Bullet.prototype.update = function() { this.x += this.speedX; this.y += this.speedY; if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) { this.active = false; } } Bullet.prototype.draw = function() { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = "yellow"; ctx.fill(); ctx.closePath(); } // 的(ターゲット)のオブジェクト function Target(x, y) { this.x = x; this.y = y; this.width = 40; this.height = 60; this.active = true; this.headshotY = y + 20; // 頭部の位置 } Target.prototype.update = function() { this.x += Math.random() * 2 - 1; // 少し動く this.y += Math.random() * 2 - 1; } Target.prototype.draw = function() { ctx.fillStyle = "green"; ctx.fillRect(this.x, this.y, this.width, this.height); // 体 ctx.fillStyle = "red"; ctx.fillRect(this.x + 10, this.headshotY, 20, 20); // 頭部(ヘッドショットエリア) } // 衝突判定 function checkCollision(bullet, target) { const distX = Math.abs(bullet.x - target.x - target.width / 2); const distY = Math.abs(bullet.y - target.y - target.height / 2); if (distX > (target.width / 2 + bullet.radius) || distY > (target.height / 2 + bullet.radius)) { return false; } if (distX <= (target.width / 2) || distY <= (target.height / 2)) { return true; } const dx = distX - target.width / 2; const dy = distY - target.height / 2; return (dx * dx + dy * dy <= (bullet.radius * bullet.radius)); } // スコープ function toggleScope() { isScoped = !isScoped; crosshair.style.width = isScoped ? '10px' : '20px'; crosshair.style.height = isScoped ? '10px' : '20px'; } // ゲームループ function gameLoop() { ctx.clearRect(0, 0, canvas.width, canvas.height); recoil = recoil * 0.9; // 反動を減少させる // 銃の描画 ctx.fillStyle = "brown"; ctx.fillRect(gun.x - recoil, gun.y, gun.width, gun.height); // 弾の更新と描画 bullets = bullets.filter(bullet => bullet.active); bullets.forEach(bullet => { bullet.update(); bullet.draw(); }); // 的の更新と描画 targets.forEach(target => { target.update(); target.draw(); }); // 衝突判定 bullets.forEach(bullet => { targets.forEach(target => { if (checkCollision(bullet, target)) { if (bullet.y <= target.headshotY + 20 && bullet.y >= target.headshotY) { score += 50; // ヘッドショット } else { score += 10; // 体 } target.active = false; bullet.active = false; } }); }); // 無効になった的を削除 targets = targets.filter(target => target.active); // 的の追加 if (Math.random() < 0.02) { const x = Math.random() * (canvas.width - 60) + 30; const y = Math.random() * (canvas.height - 60) + 30; targets.push(new Target(x, y)); } // スコア表示 scoreText.innerText = `スコア: ${score}`; } // プレイヤーの視点移動 let mouseX = canvas.width / 2; let mouseY = canvas.height / 2; canvas.addEventListener("mousemove", function(event) { mouseX = event.clientX - canvas.getBoundingClientRect().left; mouseY = event.clientY - canvas.getBoundingClientRect().top; crosshair.style.left = mouseX - crosshair.offsetWidth / 2 + "px"; crosshair.style.top = mouseY - crosshair.offsetHeight / 2 + "px"; }); // 銃を撃つ canvas.addEventListener("click", function() { const angle = Math.atan2(mouseY - gun.y, mouseX - gun.x); const speed = 10; const speedX = Math.cos(angle) * speed; const speedY = Math.sin(angle) * speed; bullets.push(new Bullet(gun.x, gun.y, speedX, speedY)); recoil += 5; // 反動の増加 }); // スコープ機能 window.addEventListener("keydown", function(event) { if (event.key === " " && !isShooting) { // スペースでスコープ toggleScope(); } }); // ゲーム開始 setInterval(gameLoop, 1000 / 60);