100 lines
3.0 KiB
JavaScript
100 lines
3.0 KiB
JavaScript
import * as THREE from 'three';
|
|
|
|
// Basic Scene Setup
|
|
const scene = new THREE.Scene();
|
|
scene.background = new THREE.Color(0x87CEEB); // Sky blue background
|
|
|
|
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
|
camera.position.set(45, 25, 0);
|
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
renderer.shadowMap.enabled = true;
|
|
document.body.appendChild(renderer.domElement);
|
|
|
|
// Lighting
|
|
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
|
|
scene.add(ambientLight);
|
|
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
|
|
directionalLight.position.set(20, 30, 20);
|
|
directionalLight.castShadow = true;
|
|
directionalLight.shadow.camera.top = 20;
|
|
directionalLight.shadow.camera.bottom = -20;
|
|
directionalLight.shadow.camera.left = -20;
|
|
directionalLight.shadow.camera.right = 20;
|
|
scene.add(directionalLight);
|
|
|
|
// Field
|
|
const fieldGeometry = new THREE.PlaneGeometry(60, 100);
|
|
const fieldMaterial = new THREE.MeshStandardMaterial({ color: 0x008000 }); // Green grass
|
|
const field = new THREE.Mesh(fieldGeometry, fieldMaterial);
|
|
field.rotation.x = -Math.PI / 2;
|
|
field.receiveShadow = true;
|
|
scene.add(field);
|
|
|
|
// Player
|
|
const playerGeometry = new THREE.CapsuleGeometry(1, 2, 4, 8);
|
|
const playerMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 }); // Red player
|
|
const player = new THREE.Mesh(playerGeometry, playerMaterial);
|
|
player.position.y = 1.5; // Stand on the field
|
|
player.castShadow = true;
|
|
scene.add(player);
|
|
|
|
// Simple Bot Players (Static)
|
|
const botMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff }); // Blue bots
|
|
for (let i = 0; i < 4; i++) {
|
|
const bot = new THREE.Mesh(playerGeometry, botMaterial);
|
|
bot.position.set(
|
|
(Math.random() - 0.5) * 50,
|
|
1.5,
|
|
(Math.random() - 0.5) * 80
|
|
);
|
|
bot.castShadow = true;
|
|
scene.add(bot);
|
|
}
|
|
|
|
|
|
// Player Controls
|
|
const keyboardState = {};
|
|
window.addEventListener('keydown', (e) => { keyboardState[e.code] = true; });
|
|
window.addEventListener('keyup', (e) => { keyboardState[e.code] = false; });
|
|
|
|
const playerSpeed = 0.2;
|
|
|
|
function updatePlayerPosition() {
|
|
if (keyboardState['ArrowUp']) {
|
|
player.position.z -= playerSpeed;
|
|
}
|
|
if (keyboardState['ArrowDown']) {
|
|
player.position.z += playerSpeed;
|
|
}
|
|
if (keyboardState['ArrowLeft']) {
|
|
player.position.x -= playerSpeed;
|
|
}
|
|
if (keyboardState['ArrowRight']) {
|
|
player.position.x += playerSpeed;
|
|
}
|
|
}
|
|
|
|
// Animation Loop
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
updatePlayerPosition();
|
|
|
|
// Camera follows player from the sideline
|
|
camera.position.z = player.position.z;
|
|
camera.lookAt(player.position);
|
|
|
|
renderer.render(scene, camera);
|
|
}
|
|
|
|
// Handle Window Resize
|
|
window.addEventListener('resize', () => {
|
|
camera.aspect = window.innerWidth / window.innerHeight;
|
|
camera.updateProjectionMatrix();
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
});
|
|
|
|
animate();
|