import React, { useState, useEffect, useRef } from 'react'; import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Zap } from 'lucide-react'; export default function CarCombatGame() { const canvasRef = useRef(null); const [gameStarted, setGameStarted] = useState(false); const [score, setScore] = useState(0); const [health, setHealth] = useState(100); const [ammo, setAmmo] = useState(50); const [gameOver, setGameOver] = useState(false); const [touchControls, setTouchControls] = useState({ up: false, down: false, left: false, right: false, shoot: false }); // Game state const gameStateRef = useRef({ player: { x: 0, y: 0, width: 60, height: 30, speed: 5, color: '#ff5722' }, bullets: [], enemies: [], powerups: [], lastEnemySpawn: 0, lastPowerupSpawn: 0, keysPressed: {}, gameLoop: null, canvasWidth: 0, canvasHeight: 0 }); // Initialize game useEffect(() => { const handleKeyDown = (e) => { gameStateRef.current.keysPressed[e.key] = true; // Shoot with spacebar if (e.key === ' ' && ammo > 0 && gameStarted && !gameOver) { shootBullet(); } }; const handleKeyUp = (e) => { gameStateRef.current.keysPressed[e.key] = false; }; window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); if (gameStateRef.current.gameLoop) { cancelAnimationFrame(gameStateRef.current.gameLoop); } }; }, [ammo, gameStarted, gameOver]); // Effect to handle canvas resizing useEffect(() => { const handleResize = () => { if (canvasRef.current) { canvasRef.current.width = canvasRef.current.clientWidth; canvasRef.current.height = canvasRef.current.clientHeight; gameStateRef.current.canvasWidth = canvasRef.current.width; gameStateRef.current.canvasHeight = canvasRef.current.height; // Reposition player if game is active if (gameStarted && !gameOver) { gameStateRef.current.player.x = Math.min( gameStateRef.current.player.x, canvasRef.current.width - gameStateRef.current.player.width ); gameStateRef.current.player.y = Math.min( gameStateRef.current.player.y, canvasRef.current.height - gameStateRef.current.player.height ); } } }; window.addEventListener('resize', handleResize); handleResize(); // Initialize on mount return () => { window.removeEventListener('resize', handleResize); }; }, [gameStarted, gameOver]); // Effect to manage game loop when game state changes useEffect(() => { if (gameStarted && !gameOver) { // Initialize player position if not already set if (gameStateRef.current.player.x === 0 && gameStateRef.current.player.y === 0) { const canvas = canvasRef.current; if (canvas) { gameStateRef.current.player.x = canvas.width / 2 - gameStateRef.current.player.width / 2; gameStateRef.current.player.y = canvas.height - 100; } } // Start game loop if not already running if (!gameStateRef.current.gameLoop) { gameLoop(); } } else if (!gameStarted || gameOver) { // Cancel game loop if game is over or not started if (gameStateRef.current.gameLoop) { cancelAnimationFrame(gameStateRef.current.gameLoop); gameStateRef.current.gameLoop = null; } } }, [gameStarted, gameOver]); // Start game const startGame = () => { const canvas = canvasRef.current; if (!canvas) return; // Set canvas size canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gameStateRef.current.canvasWidth = canvas.width; gameStateRef.current.canvasHeight = canvas.height; // Initialize player position gameStateRef.current.player.x = canvas.width / 2 - gameStateRef.current.player.width / 2; gameStateRef.current.player.y = canvas.height - 100; // Reset game state gameStateRef.current.bullets = []; gameStateRef.current.enemies = []; gameStateRef.current.powerups = []; gameStateRef.current.lastEnemySpawn = Date.now(); gameStateRef.current.lastPowerupSpawn = Date.now(); gameStateRef.current.gameLoop = null; setScore(0); setHealth(100); setAmmo(50); setGameOver(false); setGameStarted(true); }; // Game loop const gameLoop = () => { if (!gameStarted || gameOver) return; updateGame(); renderGame(); gameStateRef.current.gameLoop = requestAnimationFrame(gameLoop); }; // Update game state const updateGame = () => { const { player, keysPressed, canvasWidth, canvasHeight } = gameStateRef.current; // Player movement with keyboard if (keysPressed['ArrowLeft'] || touchControls.left) { player.x = Math.max(0, player.x - player.speed); } if (keysPressed['ArrowRight'] || touchControls.right) { player.x = Math.min(canvasWidth - player.width, player.x + player.speed); } if (keysPressed['ArrowUp'] || touchControls.up) { player.y = Math.max(0, player.y - player.speed); } if (keysPressed['ArrowDown'] || touchControls.down) { player.y = Math.min(canvasHeight - player.height, player.y + player.speed); } // Auto-shoot with touch controls if (touchControls.shoot && ammo > 0) { shootBullet(); } // Update bullets updateBullets(); // Spawn enemies spawnEnemies(); // Update enemies updateEnemies(); // Spawn powerups spawnPowerups(); // Update powerups updatePowerups(); // Check collisions checkCollisions(); }; // Render game const renderGame = () => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); if (!ctx) return; const { player, bullets, enemies, powerups } = gameStateRef.current; // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw road background drawRoad(ctx, canvas.width, canvas.height); // Draw player car drawCar(ctx, player.x, player.y, player.width, player.height, player.color); // Draw bullets bullets.forEach(bullet => { ctx.fillStyle = '#ffeb3b'; ctx.beginPath(); ctx.arc(bullet.x, bullet.y, 3, 0, Math.PI * 2); ctx.fill(); }); // Draw enemies enemies.forEach(enemy => { drawCar(ctx, enemy.x, enemy.y, enemy.width, enemy.height, enemy.color); }); // Draw powerups powerups.forEach(powerup => { ctx.fillStyle = powerup.type === 'health' ? '#4caf50' : '#2196f3'; ctx.beginPath(); ctx.arc(powerup.x, powerup.y, 10, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#ffffff'; ctx.font = '12px Arial'; ctx.textAlign = 'center'; ctx.fillText(powerup.type === 'health' ? '+' : 'A', powerup.x, powerup.y + 4); }); }; // Draw road background const drawRoad = (ctx, width, height) => { // Road ctx.fillStyle = '#455a64'; ctx.fillRect(0, 0, width, height); // Road markings ctx.strokeStyle = '#ffffff'; ctx.setLineDash([20, 20]); ctx.beginPath(); ctx.moveTo(width / 2, 0); ctx.lineTo(width / 2, height); ctx.stroke(); // Side lines ctx.setLineDash([]); ctx.beginPath(); ctx.moveTo(50, 0); ctx.lineTo(50, height); ctx.stroke(); ctx.beginPath(); ctx.moveTo(width - 50, 0); ctx.lineTo(width - 50, height); ctx.stroke(); }; // Draw car const drawCar = (ctx, x, y, width, height, color) => { // Car body ctx.fillStyle = color; ctx.fillRect(x, y, width, height); // Windows ctx.fillStyle = '#1a237e'; ctx.fillRect(x + 10, y + 5, width - 20, height - 10); // Wheels ctx.fillStyle = '#000000'; ctx.fillRect(x - 3, y - 3, 8, 8); ctx.fillRect(x + width - 5, y - 3, 8, 8); ctx.fillRect(x - 3, y + height - 5, 8, 8); ctx.fillRect(x + width - 5, y + height - 5, 8, 8); }; // Shoot bullet const shootBullet = () => { if (ammo <= 0) return; const { player, bullets } = gameStateRef.current; // Limit bullet firing rate const now = Date.now(); const lastBullet = bullets[bullets.length - 1]; if (lastBullet && now - lastBullet.timestamp < 200) return; gameStateRef.current.bullets.push({ x: player.x + player.width / 2, y: player.y, speed: 10, timestamp: now }); setAmmo(prev => prev - 1); }; // Update bullets const updateBullets = () => { gameStateRef.current.bullets = gameStateRef.current.bullets.filter(bullet => { bullet.y -= bullet.speed; return bullet.y > 0; }); }; // Spawn enemies const spawnEnemies = () => { const now = Date.now(); const { lastEnemySpawn, canvasWidth } = gameStateRef.current; if (now - lastEnemySpawn > 1500) { const enemyWidth = 50; const enemyHeight = 25; gameStateRef.current.enemies.push({ x: Math.random() * (canvasWidth - enemyWidth), y: -enemyHeight, width: enemyWidth, height: enemyHeight, speed: 2 + Math.random() * 2, color: '#00796b' }); gameStateRef.current.lastEnemySpawn = now; } }; // Update enemies const updateEnemies = () => { const { canvasHeight } = gameStateRef.current; gameStateRef.current.enemies = gameStateRef.current.enemies.filter(enemy => { enemy.y += enemy.speed; return enemy.y < canvasHeight; }); }; // Spawn powerups const spawnPowerups = () => { const now = Date.now(); const { lastPowerupSpawn, canvasWidth } = gameStateRef.current; if (now - lastPowerupSpawn > 5000) { gameStateRef.current.powerups.push({ x: 50 + Math.random() * (canvasWidth - 100), y: -20, speed: 2, type: Math.random() > 0.5 ? 'health' : 'ammo' }); gameStateRef.current.lastPowerupSpawn = now; } }; // Update powerups const updatePowerups = () => { const { canvasHeight } = gameStateRef.current; gameStateRef.current.powerups = gameStateRef.current.powerups.filter(powerup => { powerup.y += powerup.speed; return powerup.y < canvasHeight; }); }; // Check collisions const checkCollisions = () => { const { player, bullets, enemies, powerups } = gameStateRef.current; // Bullet-enemy collisions for (let i = bullets.length - 1; i >= 0; i--) { const bullet = bullets[i]; for (let j = enemies.length - 1; j >= 0; j--) { const enemy = enemies[j]; if ( bullet.x > enemy.x && bullet.x < enemy.x + enemy.width && bullet.y > enemy.y && bullet.y < enemy.y + enemy.height ) { // Remove bullet and enemy bullets.splice(i, 1); enemies.splice(j, 1); // Increase score setScore(prev => prev + 10); // Break inner loop since bullet is gone break; } } } // Player-enemy collisions for (let i = enemies.length - 1; i >= 0; i--) { const enemy = enemies[i]; if ( player.x < enemy.x + enemy.width && player.x + player.width > enemy.x && player.y < enemy.y + enemy.height && player.y + player.height > enemy.y ) { // Remove enemy enemies.splice(i, 1); // Decrease health setHealth(prev => { const newHealth = prev - 20; if (newHealth <= 0) { setGameOver(true); } return Math.max(0, newHealth); }); } } // Player-powerup collisions for (let i = powerups.length - 1; i >= 0; i--) { const powerup = powerups[i]; if ( player.x < powerup.x + 20 && player.x + player.width > powerup.x - 20 && player.y < powerup.y + 20 && player.y + player.height > powerup.y - 20 ) { // Remove powerup powerups.splice(i, 1); // Apply powerup effect if (powerup.type === 'health') { setHealth(prev => Math.min(100, prev + 20)); } else { setAmmo(prev => prev + 20); } } } }; // Touch control handlers const handleTouchStart = (control) => { setTouchControls(prev => ({ ...prev, [control]: true })); }; const handleTouchEnd = (control) => { setTouchControls(prev => ({ ...prev, [control]: false })); }; return (
{!gameStarted ? (

Car Combat

Drive, shoot, and survive in this action-packed car combat game!

) : (
{/* Game HUD */}
{health}%
{score} pts
{ammo}
{/* Game Canvas */}
{/* Game Over Overlay */} {gameOver && (

Game Over

Your score: {score}

)} {/* Touch Controls (mobile) */}
)}
); }