Add initial game setup with Three.js, including scene, camera, and controls

This commit is contained in:
Simone
2026-03-07 17:12:57 +01:00
parent 211b13e2fe
commit fcd3d1a7e5
14 changed files with 222 additions and 0 deletions
Executable
+87
View File
@@ -0,0 +1,87 @@
import * as THREE from 'three';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// 1. SCENA E CAMERA
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87ceeb);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', function () {
renderer.setSize(window.innerWidth, window.innerHeight)
})
// 2. LUCI E AMBIENTE
scene.add(new THREE.AmbientLight(0xffffff, 1));
const island = new THREE.Mesh(new THREE.CircleGeometry(20, 32), new THREE.MeshStandardMaterial({ color: 0x4df556 })); // #4df555
island.rotation.x = -Math.PI / 2;
scene.add(island);
// 3. CONTROLLI
function lock() {
document.getElementById('start').style.display = 'none';
document.getElementById('punti').style.display = 'block';
document.getElementById('tempo').style.display = 'block';
}
function unlock() {
document.getElementById('start').style.display = 'flex';
document.getElementById('punti').style.display = 'none';
document.getElementById('tempo').style.display = 'none';
}
const controls = new PointerLockControls(camera, document.body);
document.getElementById('start').addEventListener('click', () => controls.lock());
controls.addEventListener('lock', lock);
controls.addEventListener('unlock', unlock);
// 4. GESTIONE RIFIUTI (20 pezzi)
const trashArray = [];
let score = 0;
const loader = new GLTFLoader();
loader.load('models/rifiuto.glb', (gltf) => {
const mesh = gltf.scene.getObjectByName("Trash_Pile_03_GEO");
mesh.geometry.center(); // Centra l'oggetto per collisioni precise
for (let i = 0; i < 20; i++) {
const clone = mesh.clone();
scene.add(clone);
trashArray.push(clone);
spawn(clone);
}
});
function spawn(obj) {
const a = Math.random() * Math.PI * 2;
const r = Math.random() * 18;
obj.position.set(Math.cos(a) * r, 0.3, Math.sin(a) * r);
}
// 5. MOVIMENTO E COLLISIONI
const keys = {};
document.onkeydown = (e) => keys[e.code] = true;
document.onkeyup = (e) => keys[e.code] = false;
function animate() {
requestAnimationFrame(animate);
if (controls.isLocked) {
if (keys['KeyW']) controls.moveForward(0.15);
if (keys['KeyS']) controls.moveForward(-0.15);
if (keys['KeyA']) controls.moveRight(-0.15);
if (keys['KeyD']) controls.moveRight(0.15);
camera.position.y = 1.6;
// Controllo collisioni
const pPos = camera.position.clone();
pPos.y -= 1.0;
trashArray.forEach(t => {
if (new THREE.Box3().setFromObject(t).expandByScalar(0.3).containsPoint(pPos)) {
score++;
document.getElementById('score').innerText = score;
spawn(t);
}
});
}
renderer.render(scene, camera);
}
animate();