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 1: Introduction

Bienvenue à la formation #Team21 sur le leadership serviteur. Nous sommes ravis de vous voir embarquer dans ce voyage transformateur. Tout au long de cette formation, vous bénéficierez du soutien d’un mentor dédié qui vous guidera, examinera vos soumissions et vous accompagnera à chaque étape du processus. Pour tirer le meilleur parti de cette expérience, nous vous encourageons fortement à tenir un journal ou un cahier physique afin de documenter vos pensées, questions et apprentissages. De plus, vous serez tenu(e) de publier des réflexions hebdomadaires sur votre blog et sur LinkedIn. Encore une fois, bienvenue ! Nous prions pour que ce voyage mène à une transformation spirituelle, personnelle et professionnelle profonde, comme cela a été le cas pour tant d’autres avant vous. Quelle est votre définition du leadership ? Écrivez-la avant de regarder la vidéo ci-dessous. Regardez maintenant la vidéo et répondez aux questions suivantes. Veuillez signer tous vos posts afin q...

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 1:-: Introduction

Welcome to #Team21 s training on Servant Leadership .  We’re thrilled to have you embark on this transformative journey. Throughout this training, you’ll have the support of a dedicated mentor who will guide you, review your submissions, and walk alongside you every step of the way. To make the most of this experience, we strongly encourage you to keep a physical journal or notebook to document your thoughts, questions, and learnings. Additionally, you’ll be required to post weekly reflections on your blog and LinkedIn. Welcome again, and we pray that this journey leads to profound spiritual. personal and professional transformation as it has for so many others before you. What is your definition of leadership?  Write it down prior to watching the video below. Now watch the video and answer the questions that follow. Please do sign all your posts so we know who is commenting. 1. Who is/are the leaders in the video? Why? 2. How has this influenced your ...