131 lines
4.6 KiB
JavaScript
Executable File
131 lines
4.6 KiB
JavaScript
Executable File
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';
|
|
document.getElementById('crosshair').style.display = 'block';
|
|
}
|
|
function unlock() {
|
|
const startDiv = document.getElementById('start');
|
|
startDiv.style.display = 'flex'; // Forza il layout Flexbox
|
|
// Nascondi l'HUD
|
|
document.getElementById('punti').style.display = 'none';
|
|
document.getElementById('tempo').style.display = 'none';
|
|
document.getElementById('crosshair').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 OGGETTI DI SCENA (20 rifiuti + 6 alberi)
|
|
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, 0.2);
|
|
}
|
|
});
|
|
|
|
loader.load('models/tree.glb', (gltf) => {
|
|
const mesh = gltf.scene;
|
|
mesh.scale.set(4, 4, 4);
|
|
console.log(mesh);
|
|
|
|
function spawn(obj, radius, minDistance) {
|
|
const points = [];
|
|
const attempts = 1000; // Numero massimo di tentativi per trovare un punto valido
|
|
for (let i = 0; i < attempts; i++) {
|
|
let angle = Math.random() * 2 * Math.PI;
|
|
let dist = Math.random() * radius;
|
|
let x = dist * Math.cos(angle);
|
|
let z = dist * Math.sin(angle);
|
|
let valid = true;
|
|
for (let j = 0; j < points.length; j++) {
|
|
const dx = x - points[j].x;
|
|
const dz = z - points[j].z;
|
|
const distance = Math.sqrt(dx * dx + dz * dz);
|
|
if (distance < minDistance) {
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
if (valid) {
|
|
points.push({ x: x, z: z });
|
|
}
|
|
}
|
|
|
|
// Spawna gli alberi nei punti generati
|
|
for (let i = 0; i < points.length; i++) {
|
|
const clone = obj.clone();
|
|
clone.position.set(points[i].x, -0.3, points[i].z);
|
|
clone.rotation.y = Math.random() * Math.PI * 2; // Rotazione tra 0 e 360 gradi
|
|
scene.add(clone);
|
|
}
|
|
}
|
|
spawn(mesh, 18, 8); // Raggio 18, distanza minima 5
|
|
});
|
|
console.log(scene)
|
|
|
|
function spawn(obj) {
|
|
const a = Math.random() * Math.PI * 2;
|
|
const r = Math.random() * 18;
|
|
obj.position.set(Math.cos(a) * r, 0.1, 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(); |