soccergame / index.html
akhaliq's picture
akhaliq HF Staff
Update index.html
f4028dc verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pro Penalty Shootout</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Arial', sans-serif;
background: #000;
}
#container { position: relative; }
#ui {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
}
#message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 72px;
font-weight: bold;
text-shadow: 0 0 20px #000;
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
}
#controls {
position: absolute;
bottom: 20px;
left: 20px;
color: white;
background: rgba(0,0,0,0.7);
padding: 15px;
border-radius: 10px;
font-size: 18px;
line-height: 1.6;
}
#start-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.9);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 100;
}
#start-screen h1 {
font-size: 48px;
color: #FFD700;
margin-bottom: 30px;
text-shadow: 0 0 10px #FFD700;
}
button {
padding: 15px 30px;
font-size: 18px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 10px;
transition: all 0.3s;
}
button:hover {
background: #45a049;
transform: scale(1.05);
}
#power-bar {
position: absolute;
bottom: 100px;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 20px;
background: rgba(255,255,255,0.2);
border-radius: 10px;
overflow: hidden;
display: none;
}
#power-level {
height: 100%;
width: 0%;
background: linear-gradient(to right, #4CAF50, #FFD700, #FF5722);
}
</style>
</head>
<body>
<div id="container">
<div id="ui">
<span id="goals">0</span> / <span id="shots">0</span>
</div>
<div id="message"></div>
<div id="power-bar"><div id="power-level"></div></div>
<div id="controls">
<strong>CONTROLS:</strong><br>
SPACE - Power up shot<br>
LEFT/RIGHT - Aim<br>
Release SPACE - Shoot
</div>
<div id="start-screen">
<h1>PRO PENALTY SHOOTOUT</h1>
<button id="start-btn">START GAME</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script>
// Setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0, 4, 12);
camera.lookAt(0, 1, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.getElementById('container').appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 7);
directionalLight.castShadow = true;
scene.add(directionalLight);
// Field
const field = new THREE.Mesh(
new THREE.PlaneGeometry(40, 60),
new THREE.MeshStandardMaterial({ color: 0x3CB371 })
);
field.rotation.x = -Math.PI/2;
field.receiveShadow = true;
scene.add(field);
// Goal (more visible)
const goalWidth = 7.32;
const goalHeight = 2.44;
const postMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0.5
});
// Posts
const leftPost = new THREE.Mesh(
new THREE.BoxGeometry(0.5, goalHeight, 0.5),
postMaterial
);
leftPost.position.set(-goalWidth/2, goalHeight/2, -30);
leftPost.castShadow = true;
scene.add(leftPost);
const rightPost = new THREE.Mesh(
new THREE.BoxGeometry(0.5, goalHeight, 0.5),
postMaterial
);
rightPost.position.set(goalWidth/2, goalHeight/2, -30);
rightPost.castShadow = true;
scene.add(rightPost);
const crossbar = new THREE.Mesh(
new THREE.BoxGeometry(goalWidth, 0.5, 0.5),
postMaterial
);
crossbar.position.set(0, goalHeight, -30);
crossbar.castShadow = true;
scene.add(crossbar);
// Net
const net = new THREE.Mesh(
new THREE.BoxGeometry(goalWidth, goalHeight, 2),
new THREE.MeshBasicMaterial({
wireframe: true,
color: 0xffffff,
transparent: true,
opacity: 0.7
})
);
net.position.set(0, goalHeight/2, -31);
scene.add(net);
// Ball
const ballGeometry = new THREE.SphereGeometry(0.4, 32, 32);
const ballMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff,
roughness: 0.2,
metalness: 0.5
});
const ball = new THREE.Mesh(ballGeometry, ballMaterial);
ball.position.set(0, 0.4, 0);
ball.castShadow = true;
scene.add(ball);
// Goalkeeper (more visible)
function createGoalkeeper() {
const group = new THREE.Group();
// Blue jersey
const body = new THREE.Mesh(
new THREE.BoxGeometry(1, 1.8, 0.4),
new THREE.MeshStandardMaterial({ color: 0x1E90FF })
);
body.position.y = 0.9;
group.add(body);
// Yellow head
const head = new THREE.Mesh(
new THREE.SphereGeometry(0.3),
new THREE.MeshStandardMaterial({ color: 0xFFD700 })
);
head.position.y = 1.6;
group.add(head);
// Arms (in save position)
const leftArm = new THREE.Mesh(
new THREE.BoxGeometry(0.2, 0.8, 0.2),
body.material
);
leftArm.position.set(-0.7, 1.3, 0);
leftArm.rotation.z = Math.PI/3;
group.add(leftArm);
const rightArm = new THREE.Mesh(
new THREE.BoxGeometry(0.2, 0.8, 0.2),
body.material
);
rightArm.position.set(0.7, 1.3, 0);
rightArm.rotation.z = -Math.PI/3;
group.add(rightArm);
group.position.z = -29;
return group;
}
const goalkeeper = createGoalkeeper();
scene.add(goalkeeper);
// Game state
let shots = 0, goals = 0;
const maxShots = 5;
let power = 0;
let isPowering = false;
let isShooting = false;
let aimDirection = 0;
const clock = new THREE.Clock();
// Controls
const keys = {
Space: false,
ArrowLeft: false,
ArrowRight: false
};
window.addEventListener('keydown', (e) => {
if (e.code in keys) {
keys[e.code] = true;
if (e.code === 'Space' && !isPowering && !isShooting && shots < maxShots) {
isPowering = true;
document.getElementById('power-bar').style.display = 'block';
}
}
});
window.addEventListener('keyup', (e) => {
if (e.code in keys) {
keys[e.code] = false;
if (e.code === 'Space' && isPowering && !isShooting) {
shootBall();
}
}
});
// Start game
document.getElementById('start-btn').addEventListener('click', () => {
document.getElementById('start-screen').style.display = 'none';
});
// Power meter
function updatePower() {
if (isPowering) {
power = Math.min(power + 2, 100);
document.getElementById('power-level').style.width = `${power}%`;
}
}
// Shooting
function shootBall() {
isPowering = false;
isShooting = true;
shots++;
document.getElementById('shots').textContent = shots;
document.getElementById('power-bar').style.display = 'none';
// Determine target based on aim
const targetX = aimDirection * 4;
const targetY = goalHeight/2;
const speed = 0.5 + (power/100) * 1.5; // Faster ball movement
let lastTime = performance.now();
function animateBall() {
const now = performance.now();
const delta = (now - lastTime) / 16; // Normalize to ~60fps
lastTime = now;
// Move ball forward and adjust curve
ball.position.z -= speed * delta;
ball.position.x += (targetX - ball.position.x) * 0.03 * delta;
ball.position.y = 0.4 + Math.sin(ball.position.z * 0.2) * 3 * (power/100);
// Collision with goalkeeper
const keeperX = goalkeeper.position.x;
if (Math.abs(ball.position.x - keeperX) < 1.2 && ball.position.z < -27) {
endShot(false);
return;
}
// Goal check
if (ball.position.z <= -30) {
const isGoal = Math.abs(ball.position.x) < goalWidth/2 && ball.position.y < goalHeight;
if (isGoal) {
goals++;
document.getElementById('goals').textContent = goals;
showMessage("GOAL!");
} else {
showMessage("MISSED!");
}
endShot(isGoal);
return;
}
requestAnimationFrame(animateBall);
}
animateBall();
power = 0;
}
function endShot(scored) {
isShooting = false;
setTimeout(() => {
ball.position.set(0, 0.4, 0);
if (shots >= maxShots) {
setTimeout(() => {
showMessage(`FINAL SCORE: ${goals}/${maxShots}`);
}, 500);
}
}, 1000);
}
function showMessage(text) {
const message = document.getElementById('message');
message.textContent = text;
message.style.opacity = 1;
setTimeout(() => message.style.opacity = 0, 1500);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Goalkeeper movement
const time = clock.getElapsedTime();
goalkeeper.position.x = Math.sin(time * 1.5) * 3;
// Handle aim input
if (isPowering) {
if (keys.ArrowLeft) aimDirection = Math.max(aimDirection - 0.05, -1);
if (keys.ArrowRight) aimDirection = Math.min(aimDirection + 0.05, 1);
updatePower();
}
renderer.render(scene, camera);
}
// Window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
</script>
</body>
</html>