Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Mattel Handheld Football - Built with anycoder</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: white; | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| padding: 20px; | |
| overflow-x: hidden; | |
| } | |
| .header { | |
| width: 100%; | |
| max-width: 1200px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 30px; | |
| } | |
| .logo { | |
| font-size: 24px; | |
| font-weight: bold; | |
| color: #ff4444; | |
| text-shadow: 0 0 10px rgba(255, 68, 68, 0.5); | |
| } | |
| .anycoder-link { | |
| color: #4a90e2; | |
| text-decoration: none; | |
| font-size: 14px; | |
| transition: all 0.3s ease; | |
| } | |
| .anycoder-link:hover { | |
| color: #6bb6ff; | |
| text-decoration: underline; | |
| } | |
| .container { | |
| width: 100%; | |
| max-width: 800px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 20px; | |
| } | |
| .game-container { | |
| width: 100%; | |
| height: 500px; | |
| position: relative; | |
| background: rgba(0, 0, 0, 0.3); | |
| border-radius: 10px; | |
| overflow: hidden; | |
| box-shadow: 0 0 30px rgba(0, 0, 0, 0.5); | |
| } | |
| .controls { | |
| width: 100%; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 15px; | |
| align-items: center; | |
| } | |
| .control-row { | |
| width: 100%; | |
| display: flex; | |
| justify-content: center; | |
| gap: 20px; | |
| } | |
| .btn { | |
| padding: 12px 24px; | |
| background: #ff4444; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| font-size: 16px; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| box-shadow: 0 4px 0 #cc0000; | |
| } | |
| .btn:hover { | |
| background: #ff6666; | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 0 #cc0000; | |
| } | |
| .btn:active { | |
| transform: translateY(2px); | |
| box-shadow: 0 2px 0 #cc0000; | |
| } | |
| .btn-secondary { | |
| background: #4a90e2; | |
| box-shadow: 0 4px 0 #1a5fb4; | |
| } | |
| .btn-secondary:hover { | |
| background: #6bb6ff; | |
| } | |
| .game-info { | |
| width: 100%; | |
| background: rgba(0, 0, 0, 0.5); | |
| padding: 15px; | |
| border-radius: 10px; | |
| text-align: center; | |
| } | |
| .instructions { | |
| margin-top: 20px; | |
| background: rgba(0, 0, 0, 0.5); | |
| padding: 20px; | |
| border-radius: 10px; | |
| max-width: 600px; | |
| } | |
| .instructions h3 { | |
| margin-bottom: 10px; | |
| color: #ff4444; | |
| } | |
| .instructions p { | |
| margin-bottom: 8px; | |
| line-height: 1.5; | |
| } | |
| @media (max-width: 768px) { | |
| .game-container { | |
| height: 400px; | |
| } | |
| .control-row { | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .btn { | |
| width: 100%; | |
| max-width: 300px; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| body { | |
| padding: 10px; | |
| } | |
| .game-container { | |
| height: 300px; | |
| } | |
| .btn { | |
| padding: 10px 18px; | |
| font-size: 14px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <div class="logo">MATTEL FOOTBALL</div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link">Built with anycoder</a> | |
| </div> | |
| <div class="container"> | |
| <div class="game-container" id="game-container"></div> | |
| <div class="controls"> | |
| <div class="control-row"> | |
| <button class="btn" id="start-btn">START GAME</button> | |
| <button class="btn btn-secondary" id="reset-btn">RESET</button> | |
| </div> | |
| <div class="control-row"> | |
| <button class="btn" id="pass-btn">PASS</button> | |
| <button class="btn" id="run-btn">RUN</button> | |
| <button class="btn" id="kick-btn">KICK</button> | |
| </div> | |
| </div> | |
| <div class="game-info"> | |
| <h3>Game Status: <span id="game-status">Ready</span></h3> | |
| <p>Score: <span id="score">0 - 0</span></p> | |
| <p>Quarter: <span id="quarter">1</span></p> | |
| <p>Time: <span id="time">15:00</span></p> | |
| </div> | |
| <div class="instructions"> | |
| <h3>How to Play:</h3> | |
| <p>1. Press START GAME to begin</p> | |
| <p>2. Use PASS, RUN, or KICK buttons to control your plays</p> | |
| <p>3. Try to score touchdowns (6 points) or field goals (3 points)</p> | |
| <p>4. The game simulates the classic Mattel handheld football experience</p> | |
| <p>5. First to score wins (just like the original!)</p> | |
| </div> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.182.0/examples/js/controls/OrbitControls.js"></script> | |
| <script> | |
| // Game state | |
| let gameState = { | |
| started: false, | |
| score: [0, 0], | |
| quarter: 1, | |
| time: 900, // 15 minutes in seconds | |
| possession: 0, // 0 for player, 1 for CPU | |
| yardsToGo: 10, | |
| down: 1, | |
| yardLine: 20, | |
| gameOver: false, | |
| lastPlay: null, | |
| playTimer: 0, | |
| playInProgress: false | |
| }; | |
| // Three.js setup | |
| let scene, camera, renderer, controls; | |
| let footballCase, screenMesh, buttons = []; | |
| let clock = new THREE.Clock(); | |
| // Initialize the game | |
| function init() { | |
| // Create scene | |
| scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0x1a1a2e); | |
| // Create camera | |
| camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
| camera.position.set(0, 5, 15); | |
| // Create renderer | |
| renderer = new THREE.WebGLRenderer({ antialias: true }); | |
| renderer.setSize(window.innerWidth * 0.8, 500); | |
| renderer.shadowMap.enabled = true; | |
| document.getElementById('game-container').appendChild(renderer.domElement); | |
| // Add orbit controls | |
| controls = new THREE.OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.05; | |
| controls.screenSpacePanning = false; | |
| controls.minDistance = 5; | |
| controls.maxDistance = 30; | |
| controls.maxPolarAngle = Math.PI / 2; | |
| // Add lights | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); | |
| scene.add(ambientLight); | |
| const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); | |
| directionalLight.position.set(5, 10, 7); | |
| directionalLight.castShadow = true; | |
| directionalLight.shadow.mapSize.width = 1024; | |
| directionalLight.shadow.mapSize.height = 1024; | |
| scene.add(directionalLight); | |
| // Create the football case | |
| createFootballCase(); | |
| // Add event listeners | |
| setupEventListeners(); | |
| // Start animation loop | |
| animate(); | |
| // Handle window resize | |
| window.addEventListener('resize', onWindowResize); | |
| } | |
| // Create the football case | |
| function createFootballCase() { | |
| // Main case (red plastic) | |
| const caseGeometry = new THREE.BoxGeometry(8, 4, 1); | |
| const caseMaterial = new THREE.MeshPhongMaterial({ | |
| color: 0xff0000, | |
| shininess: 30, | |
| specular: 0x111111 | |
| }); | |
| footballCase = new THREE.Mesh(caseGeometry, caseMaterial); | |
| footballCase.position.y = 2; | |
| footballCase.castShadow = true; | |
| footballCase.receiveShadow = true; | |
| scene.add(footballCase); | |
| // Screen area (black with green LED effect) | |
| const screenGeometry = new THREE.PlaneGeometry(5, 2.5); | |
| const screenMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0x000000, | |
| transparent: true, | |
| opacity: 0.8 | |
| }); | |
| screenMesh = new THREE.Mesh(screenGeometry, screenMaterial); | |
| screenMesh.position.set(0, 2.1, 0.51); | |
| scene.add(screenMesh); | |
| // Create screen content (simulated LED display) | |
| createScreenContent(); | |
| // Buttons | |
| createButtons(); | |
| // Add some branding | |
| const logoGeometry = new THREE.PlaneGeometry(1.5, 0.5); | |
| const logoMaterial = new THREE.MeshBasicMaterial({ | |
| color: 0xffffff, | |
| transparent: true, | |
| opacity: 0.9 | |
| }); | |
| const logo = new THREE.Mesh(logoGeometry, logoMaterial); | |
| logo.position.set(0, 3.5, 0.51); | |
| scene.add(logo); | |
| // Add some texture to the case | |
| const edgeGeometry = new THREE.BoxGeometry(8.2, 4.2, 0.2); | |
| const edgeMaterial = new THREE.MeshPhongMaterial({ | |
| color: 0x330000, | |
| shininess: 10 | |
| }); | |
| const edge = new THREE.Mesh(edgeGeometry, edgeMaterial); | |
| edge.position.y = 2; | |
| scene.add(edge); | |
| } | |
| // Create screen content | |
| function createScreenContent() { | |
| // Create a canvas for the LED display | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = 256; | |
| canvas.height = 128; | |
| const ctx = canvas.getContext('2d'); | |
| // Draw the initial screen | |
| updateScreenDisplay(ctx); | |
| // Create texture from canvas | |
| const texture = new THREE.CanvasTexture(canvas); | |
| // Update the screen mesh material | |
| screenMesh.material.map = texture; | |
| screenMesh.material.needsUpdate = true; | |
| } | |
| // Update the screen display | |
| function updateScreenDisplay(ctx) { | |
| // Clear the canvas | |
| ctx.fillStyle = '#000000'; | |
| ctx.fillRect(0, 0, 256, 128); | |
| // Draw the "field" | |
| ctx.fillStyle = '#003300'; | |
| ctx.fillRect(20, 20, 216, 88); | |
| // Draw yard lines | |
| ctx.strokeStyle = '#006600'; | |
| ctx.lineWidth = 1; | |
| for (let i = 0; i < 10; i++) { | |
| const x = 20 + i * 21.6; | |
| ctx.beginPath(); | |
| ctx.moveTo(x, 20); | |
| ctx.lineTo(x, 108); | |
| ctx.stroke(); | |
| } | |
| // Draw the ball position | |
| const ballX = 20 + (gameState.yardLine / 100) * 216; | |
| ctx.fillStyle = '#ffcc00'; | |
| ctx.beginPath(); | |
| ctx.arc(ballX, 64, 8, 0, Math.PI * 2); | |
| ctx.fill(); | |
| // Draw score and info | |
| ctx.fillStyle = '#ff0000'; | |
| ctx.font = '16px Arial'; | |
| ctx.textAlign = 'left'; | |
| ctx.fillText(`SCORE: ${gameState.score[0]} - ${gameState.score[1]}`, 20, 16); | |
| ctx.textAlign = 'right'; | |
| ctx.fillText(`QTR: ${gameState.quarter}`, 236, 16); | |
| ctx.textAlign = 'center'; | |
| ctx.fillText(`${gameState.down} & ${gameState.yardsToGo}`, 128, 16); | |
| // Draw time | |
| const minutes = Math.floor(gameState.time / 60); | |
| const seconds = gameState.time % 60; | |
| const timeStr = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; | |
| ctx.fillText(timeStr, 128, 118); | |
| // Draw last play | |
| if (gameState.lastPlay) { | |
| ctx.fillStyle = '#00ff00'; | |
| ctx.font = '12px Arial'; | |
| ctx.textAlign = 'center'; | |
| ctx.fillText(gameState.lastPlay, 128, 108); | |
| } | |
| } | |
| // Create buttons | |
| function createButtons() { | |
| // Button positions and labels | |
| const buttonData = [ | |
| { x: -2.5, y: 0.5, z: 0.51, label: 'START', color: 0x00ff00 }, | |
| { x: 2.5, y: 0.5, z: 0.51, label: 'RESET', color: 0xffff00 }, | |
| { x: -2.5, y: -0.5, z: 0.51, label: 'PASS', color: 0x00ffff }, | |
| { x: 0, y: -0.5, z: 0.51, label: 'RUN', color: 0xff00ff }, | |
| { x: 2.5, y: -0.5, z: 0.51, label: 'KICK', color: 0xff8800 } | |
| ]; | |
| buttonData.forEach(data => { | |
| const buttonGeometry = new THREE.CylinderGeometry(0.4, 0.4, 0.2, 32); | |
| const buttonMaterial = new THREE.MeshPhongMaterial({ | |
| color: data.color, | |
| shininess: 50 | |
| }); | |
| const button = new THREE.Mesh(buttonGeometry, buttonMaterial); | |
| button.position.set(data.x, data.y, data.z); | |
| button.userData = { label: data.label }; | |
| scene.add(button); | |
| buttons.push(button); | |
| // Add button label | |
| const labelCanvas = document.createElement('canvas'); | |
| labelCanvas.width = 128; | |
| labelCanvas.height = 32; | |
| const labelCtx = labelCanvas.getContext('2d'); | |
| labelCtx.fillStyle = '#000000'; | |
| labelCtx.fillRect(0, 0, 128, 32); | |
| labelCtx.fillStyle = '#ffffff'; | |
| labelCtx.font = '16px Arial'; | |
| labelCtx.textAlign = 'center'; | |
| labelCtx.textBaseline = 'middle'; | |
| labelCtx.fillText(data.label, 64, 16); | |
| const labelTexture = new THREE.CanvasTexture(labelCanvas); | |
| const labelMaterial = new THREE.MeshBasicMaterial({ | |
| map: labelTexture, | |
| transparent: true | |
| }); | |
| const labelMesh = new THREE.Mesh( | |
| new THREE.PlaneGeometry(0.8, 0.2), | |
| labelMaterial | |
| ); | |
| labelMesh.position.set(data.x, data.y, 0.52); | |
| scene.add(labelMesh); | |
| }); | |
| } | |
| // Setup event listeners | |
| function setupEventListeners() { | |
| document.getElementById('start-btn').addEventListener('click', startGame); | |
| document.getElementById('reset-btn').addEventListener('click', resetGame); | |
| document.getElementById('pass-btn').addEventListener('click', () => makePlay('PASS')); | |
| document.getElementById('run-btn').addEventListener('click', () => makePlay('RUN')); | |
| document.getElementById('kick-btn').addEventListener('click', () => makePlay('KICK')); | |
| } | |
| // Start the game | |
| function startGame() { | |
| if (gameState.gameOver) { | |
| resetGame(); | |
| } | |
| gameState.started = true; | |
| gameState.gameOver = false; | |
| gameState.possession = 0; | |
| gameState.yardsToGo = 10; | |
| gameState.down = 1; | |
| gameState.yardLine = 20; | |
| gameState.lastPlay = null; | |
| document.getElementById('game-status').textContent = 'In Progress'; | |
| updateGameInfo(); | |
| // Start game timer | |
| if (!gameState.playInProgress) { | |
| gameState.playInProgress = true; | |
| } | |
| } | |
| // Reset the game | |
| function resetGame() { | |
| gameState = { | |
| started: false, | |
| score: [0, 0], | |
| quarter: 1, | |
| time: 900, | |
| possession: 0, | |
| yardsToGo: 10, | |
| down: 1, | |
| yardLine: 20, | |
| gameOver: false, | |
| lastPlay: null, | |
| playTimer: 0, | |
| playInProgress: false | |
| }; | |
| document.getElementById('game-status').textContent = 'Ready'; | |
| updateGameInfo(); | |
| updateScreenDisplay(screenMesh.material.map.image.getContext('2d')); | |
| } | |
| // Make a play | |
| function makePlay(playType) { | |
| if (!gameState.started || gameState.gameOver || gameState.playInProgress) return; | |
| gameState.playInProgress = true; | |
| gameState.lastPlay = `YOU: ${playType}`; | |
| // Simulate the play with some randomness | |
| setTimeout(() => { | |
| let yardsGained = 0; | |
| let playResult = ''; | |
| // Determine yards gained based on play type | |
| switch(playType) { | |
| case 'PASS': | |
| yardsGained = Math.floor(Math.random() * 20) - 5; | |
| playResult = yardsGained > 0 ? | |
| `Pass complete for ${yardsGained} yards!` : | |
| `Incomplete pass!`; | |
| break; | |
| case 'RUN': | |
| yardsGained = Math.floor(Math.random() * 8) - 2; | |
| playResult = yardsGained > 0 ? | |
| `Run for ${yardsGained} yards!` : | |
| `Tackled for ${yardsGained} yard loss!`; | |
| break; | |
| case 'KICK': | |
| if (gameState.down === 4) { | |
| // Field goal attempt | |
| const distance = 100 - gameState.yardLine; | |
| const success = Math.random() > (distance / 100); | |
| if (success) { | |
| gameState.score[gameState.possession] += 3; | |
| playResult = `Field goal GOOD! 3 points!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 20; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| playResult = `Field goal NO GOOD!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - gameState.yardLine; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| } else { | |
| // Punt | |
| yardsGained = 30 + Math.floor(Math.random() * 20); | |
| playResult = `Punt for ${yardsGained} yards!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - (gameState.yardLine + yardsGained); | |
| if (gameState.yardLine < 0) gameState.yardLine = 0; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| break; | |
| } | |
| // Update yard line for non-kick plays | |
| if (playType !== 'KICK' || gameState.down !== 4) { | |
| gameState.yardLine += yardsGained; | |
| // Check for touchdown | |
| if (gameState.yardLine >= 100) { | |
| gameState.score[gameState.possession] += 6; | |
| playResult = `TOUCHDOWN! 6 points!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 20; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| // Update down and yards to go | |
| gameState.yardsToGo -= yardsGained; | |
| if (gameState.yardsToGo <= 0) { | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| gameState.down++; | |
| if (gameState.down > 4) { | |
| playResult += ` Turnover on downs!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - gameState.yardLine; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| } | |
| } | |
| } | |
| gameState.lastPlay = playResult; | |
| updateGameInfo(); | |
| // CPU turn | |
| if (gameState.possession === 1 && !gameState.gameOver) { | |
| setTimeout(cpuPlay, 2000); | |
| } else { | |
| gameState.playInProgress = false; | |
| } | |
| }, 1000); | |
| } | |
| // CPU makes a play | |
| function cpuPlay() { | |
| const plays = ['PASS', 'RUN', 'KICK']; | |
| const playType = plays[Math.floor(Math.random() * plays.length)]; | |
| gameState.lastPlay = `CPU: ${playType}`; | |
| setTimeout(() => { | |
| let yardsGained = 0; | |
| let playResult = ''; | |
| switch(playType) { | |
| case 'PASS': | |
| yardsGained = Math.floor(Math.random() * 15) - 3; | |
| playResult = yardsGained > 0 ? | |
| `CPU pass complete for ${yardsGained} yards!` : | |
| `CPU pass incomplete!`; | |
| break; | |
| case 'RUN': | |
| yardsGained = Math.floor(Math.random() * 6); | |
| playResult = `CPU run for ${yardsGained} yards!`; | |
| break; | |
| case 'KICK': | |
| if (gameState.down === 4) { | |
| const distance = 100 - gameState.yardLine; | |
| const success = Math.random() > (distance / 80); | |
| if (success) { | |
| gameState.score[gameState.possession] += 3; | |
| playResult = `CPU field goal GOOD! 3 points!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 20; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| playResult = `CPU field goal NO GOOD!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - gameState.yardLine; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| } else { | |
| yardsGained = 35 + Math.floor(Math.random() * 15); | |
| playResult = `CPU punt for ${yardsGained} yards!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - (gameState.yardLine + yardsGained); | |
| if (gameState.yardLine < 0) gameState.yardLine = 0; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| break; | |
| } | |
| if (playType !== 'KICK' || gameState.down !== 4) { | |
| gameState.yardLine -= yardsGained; | |
| if (gameState.yardLine <= 0) { | |
| gameState.score[gameState.possession] += 6; | |
| playResult = `CPU TOUCHDOWN! 6 points!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 80; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| gameState.yardsToGo -= yardsGained; | |
| if (gameState.yardsToGo <= 0) { | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } else { | |
| gameState.down++; | |
| if (gameState.down > 4) { | |
| playResult += ` CPU turnover on downs!`; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 100 - gameState.yardLine; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| } | |
| } | |
| } | |
| gameState.lastPlay = playResult; | |
| updateGameInfo(); | |
| gameState.playInProgress = false; | |
| }, 1000); | |
| } | |
| // Update game info display | |
| function updateGameInfo() { | |
| document.getElementById('score').textContent = `${gameState.score[0]} - ${gameState.score[1]}`; | |
| document.getElementById('quarter').textContent = gameState.quarter; | |
| document.getElementById('time').textContent = | |
| `${Math.floor(gameState.time / 60)}:${gameState.time % 60 < 10 ? '0' : ''}${gameState.time % 60}`; | |
| // Update screen display | |
| updateScreenDisplay(screenMesh.material.map.image.getContext('2d')); | |
| screenMesh.material.needsUpdate = true; | |
| } | |
| // Animation loop | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Update game timer if game is in progress | |
| if (gameState.started && !gameState.gameOver && gameState.time > 0) { | |
| gameState.playTimer += clock.getDelta(); | |
| if (gameState.playTimer >= 1) { | |
| gameState.time--; | |
| gameState.playTimer = 0; | |
| // Check for quarter change | |
| if (gameState.time <= 0) { | |
| gameState.quarter++; | |
| if (gameState.quarter > 4) { | |
| gameState.gameOver = true; | |
| document.getElementById('game-status').textContent = 'Game Over'; | |
| // Determine winner | |
| if (gameState.score[0] > gameState.score[1]) { | |
| gameState.lastPlay = 'YOU WIN!'; | |
| } else if (gameState.score[1] > gameState.score[0]) { | |
| gameState.lastPlay = 'CPU WINS!'; | |
| } else { | |
| gameState.lastPlay = 'TIE GAME!'; | |
| } | |
| } else { | |
| gameState.time = 900; | |
| gameState.possession = 1 - gameState.possession; | |
| gameState.yardLine = 20; | |
| gameState.down = 1; | |
| gameState.yardsToGo = 10; | |
| } | |
| } | |
| updateGameInfo(); | |
| } | |
| } | |
| // Rotate the football case slightly for visual interest | |
| if (footballCase) { | |
| footballCase.rotation.y += 0.005; | |
| } | |
| controls.update(); | |
| renderer.render(scene, camera); | |
| } | |
| // Handle window resize | |
| function onWindowResize() { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth * 0.8, 500); | |
| } | |
| // Initialize the game when the page loads | |
| window.onload = init; | |
| </script> | |
| </body> | |
| </html> |