anycoder-810ad0dc / index.html
crocro's picture
Upload folder using huggingface_hub
0bd1788 verified
Raw
History Blame Contribute Delete
28.8 kB
<!DOCTYPE html>
<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>