Skip to main content

Team21Ai Game 2

import React, { useState, useEffect, useRef, useCallback } from 'react'; import { ObstacleType } from '../types'; import Plane from './Plane'; import Obstacle from './Obstacle'; import { GAME_WIDTH, GAME_HEIGHT, GRAVITY, LIFT, PLANE_WIDTH, PLANE_HEIGHT, OBSTACLE_WIDTH, OBSTACLE_GAP, OBSTACLE_SPEED, OBSTACLE_INTERVAL, HORIZONTAL_SPEED, DIVE_FORCE, MAX_ROTATION, ROTATION_VELOCITY_SCALAR, } from '../constants'; interface GameProps { onGameOver: (score: number) => void; } const Game: React.FC = ({ onGameOver }) => { const [planeY, setPlaneY] = useState(GAME_HEIGHT / 2); const [planeX, setPlaneX] = useState(GAME_WIDTH / 2 - PLANE_WIDTH / 2); const [planeVelocity, setPlaneVelocity] = useState(0); const [planeRotation, setPlaneRotation] = useState(0); const [obstacles, setObstacles] = useState([]); const [score, setScore] = useState(0); const [keysPressed, setKeysPressed] = useState>(new Set()); const gameLoopRef = useRef(); const obstacleTimerRef = useRef(); const gameContainerRef = useRef(null); const audioContextRef = useRef(null); const playSound = useCallback((type: 'jump' | 'score' | 'crash') => { // FIX: Refactored audio context handling to be clearer and avoid potential linter confusion. // The original complex logic was likely causing the reported errors. if (!audioContextRef.current) { return; } if (audioContextRef.current.state === 'suspended') { audioContextRef.current.resume(); } const ctx = audioContextRef.current; const oscillator = ctx.createOscillator(); const gainNode = ctx.createGain(); gainNode.connect(ctx.destination); oscillator.connect(gainNode); switch (type) { case 'jump': oscillator.type = 'triangle'; oscillator.frequency.setValueAtTime(600, ctx.currentTime); gainNode.gain.setValueAtTime(0.08, ctx.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.00001, ctx.currentTime + 0.2); oscillator.start(ctx.currentTime); oscillator.stop(ctx.currentTime + 0.2); break; case 'score': oscillator.type = 'sine'; oscillator.frequency.setValueAtTime(880, ctx.currentTime); gainNode.gain.setValueAtTime(0.1, ctx.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.00001, ctx.currentTime + 0.15); oscillator.start(ctx.currentTime); oscillator.stop(ctx.currentTime + 0.15); break; case 'crash': oscillator.type = 'sawtooth'; oscillator.frequency.setValueAtTime(220, ctx.currentTime); oscillator.frequency.exponentialRampToValueAtTime(50, ctx.currentTime + 0.5); gainNode.gain.setValueAtTime(0.15, ctx.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.00001, ctx.currentTime + 0.5); oscillator.start(ctx.currentTime); oscillator.stop(ctx.currentTime + 0.5); break; } }, []); const jump = useCallback(() => { if (!audioContextRef.current) { audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)(); } playSound('jump'); setPlaneVelocity(LIFT); }, [playSound]); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === ' ' || e.key === 'ArrowUp') { e.preventDefault(); jump(); } else { setKeysPressed(prev => new Set(prev).add(e.key)); } }; const handleKeyUp = (e: KeyboardEvent) => { setKeysPressed(prev => { const newKeys = new Set(prev); newKeys.delete(e.key); return newKeys; }); }; const handlePointerDown = (e: Event) => { e.preventDefault(); jump(); }; window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); window.addEventListener('mousedown', handlePointerDown); window.addEventListener('touchstart', handlePointerDown); return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); window.removeEventListener('mousedown', handlePointerDown); window.removeEventListener('touchstart', handlePointerDown); }; }, [jump]); const runGameLoop = useCallback(() => { // --- Physics and Movement --- let newVelocity = planeVelocity + GRAVITY; if (keysPressed.has('ArrowDown')) newVelocity += DIVE_FORCE; let newPlaneY = planeY + newVelocity; newPlaneY = Math.max(0, Math.min(GAME_HEIGHT - PLANE_HEIGHT, newPlaneY)); let newPlaneX = planeX; if (keysPressed.has('ArrowLeft')) newPlaneX -= HORIZONTAL_SPEED; if (keysPressed.has('ArrowRight')) newPlaneX += HORIZONTAL_SPEED; newPlaneX = Math.max(0, Math.min(GAME_WIDTH - PLANE_WIDTH, newPlaneX)); const newRotation = Math.min(MAX_ROTATION, Math.max(-MAX_ROTATION, newVelocity * ROTATION_VELOCITY_SCALAR)); // --- Obstacles and Score --- let newScore = score; const updatedObstacles = obstacles .map(obstacle => ({ ...obstacle, pos: { ...obstacle.pos, x: obstacle.pos.x - OBSTACLE_SPEED } })) .filter(obstacle => obstacle.pos.x > -OBSTACLE_WIDTH); updatedObstacles.forEach(obstacle => { if (!obstacle.passed && obstacle.pos.x + OBSTACLE_WIDTH < newPlaneX) { obstacle.passed = true; newScore += 1; playSound('score'); } }); // --- Collision Detection --- const planeRect = { left: newPlaneX, right: newPlaneX + PLANE_WIDTH, top: newPlaneY, bottom: newPlaneY + PLANE_HEIGHT }; if (planeRect.bottom >= GAME_HEIGHT) { playSound('crash'); onGameOver(newScore); return; } for (const obstacle of updatedObstacles) { const obstacleLeft = obstacle.pos.x; const obstacleRight = obstacle.pos.x + obstacle.width; const topObstacleBottom = obstacle.pos.y + obstacle.height; const bottomObstacleTop = obstacle.pos.y + obstacle.height + OBSTACLE_GAP; const collidesWithTop = planeRect.right > obstacleLeft && planeRect.left < obstacleRight && planeRect.top < topObstacleBottom; const collidesWithBottom = planeRect.right > obstacleLeft && planeRect.left < obstacleRight && planeRect.bottom > bottomObstacleTop; if (collidesWithTop || collidesWithBottom) { playSound('crash'); onGameOver(newScore); return; } } // --- State Updates --- setPlaneVelocity(newVelocity); setPlaneY(newPlaneY); setPlaneX(newPlaneX); setPlaneRotation(newRotation); setObstacles(updatedObstacles); if(newScore !== score) setScore(newScore); gameLoopRef.current = requestAnimationFrame(runGameLoop); }, [planeY, planeX, planeVelocity, obstacles, score, keysPressed, onGameOver, playSound]); useEffect(() => { gameLoopRef.current = requestAnimationFrame(runGameLoop); return () => { if (gameLoopRef.current) { cancelAnimationFrame(gameLoopRef.current); } }; }, [runGameLoop]); useEffect(() => { const generateObstacle = () => { const topHeight = Math.random() * (GAME_HEIGHT - OBSTACLE_GAP - 100) + 50; setObstacles(prev => [ ...prev, { pos: { x: GAME_WIDTH, y: 0 }, width: OBSTACLE_WIDTH, height: topHeight, passed: false, } ]); }; generateObstacle(); obstacleTimerRef.current = window.setInterval(generateObstacle, OBSTACLE_INTERVAL); return () => { if (obstacleTimerRef.current) { clearInterval(obstacleTimerRef.current); } }; }, []); return (
{score}
{obstacles.map((obstacle, index) => ( ))}
); }; export default Game;

Comments

Popular posts from this blog

Semaine 4 : Mission, vision et objectifs

Mission, visions et objectifs Proverbes 21:5 : "Les projets du diligent mènent à l'abondance, mais celui qui agit précipitamment court à la pauvreté." Étapes pratiques pour atteindre et maintenir la croissance [DRAFTED].                                                              M ission, vision et objectifs {D} Rêver à nouveau Chaque innovation, découverte scientifique, conception et toute autre chose qui a été créée a commencé par un rêve. Je suis certain que vous avez eu de nombreux rêves en grandissant, sans être encombré par les limitations qui vous entouraient, comme la situation financière de vos parents et les distractions quotidiennes auxquelles vous faisiez face. Vous avez peut-être eu de grands rêves au début de l'année dernière, mais en y repensant maintenant, vous vous rendez compte que vous n'êtes plus aussi exc...

Week 2 :-: Stoppers

Our first lesson focused on defining and understanding what servant leadership is. Personally, I was reminded that everyone is a leader since we were all created by the same God and in His image. It follows naturally from this conclusion that everyone therefore has both the capacity and responsibility of working to become a better leader! Potential is great but it is better and more useful when converted to action. Having leadership potential is awesome but useless if not developed and put into use. God created you to meet a need and for that purpose you have to collaborate with Him to develop and exercise your leadership in your calling. This is a proactive choice that can only be sustained by intrinsic motivation. Are you motivated to become better at leading both yourself and others? Per John C. Maxwell, "Leadership Ability Determines a Person’s Level of Effectiveness".   In Team21 we understand this implies that you can only take yourself, family, organization ...

Week 5 :-: Stewardship and Conceptualization

Stewardship and Conceptualization: The Servant Leader’s Responsibility "Your most important work is always ahead of you, never behind you." – Stephen Covey "Servant leaders are brokers of resources, for which they are stewards." – Forteh Introduction In our previous lesson, we explored the importance of taking small, consistent steps toward fulfilling our, goals, visions and hence life mission. We learned that a servant leader is not just someone with grand visions but someone who actively works toward accomplishing them daily. However, a leader’s success doesn’t come from having ideas alone —it comes from intentionally  managing people and resources wisely to bring those ideas to life . This is where stewardship and conceptualization come in. This lesson will help you: ✅ Understand stewardship and your role as a servant leader. ✅ Learn how to conceptualize ideas and turn them into actionable plans. ✅ Develop practical skills to manage resources, guide people, ...