Починаючи зі сфери, що зависла в повітрі, додайте силу гравітації, яка щокадру прискорює м'яч донизу. Коли він торкається підлоги, застосуйте відскок із поглинанням енергії, щоб м'яч зрештою зупинився. Опануйте інтегрування за Ейлером, накопичення швидкості та коефіцієнт відновлення.
-
М'яч падає з
vy += g * dt, що застосовується щокадру -
М'яч відскакує від площини підлоги за
vy *= -restitution - М'яч сповільнюється та зупиняється (restitution < 1)
- Керування: повзунок сили гравітації (0 → 30 м/с²)
// Three.js r160 вже завантажено
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, innerWidth/innerHeight, 0.1, 100);
camera.position.set(0, 2, 8);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
// М'яч
const ball = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 32, 32),
new THREE.MeshStandardMaterial({ color: 0x3b82f6 })
);
ball.position.y = 5;
scene.add(ball);
// Підлога
scene.add(new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshStandardMaterial({ color: 0x1e293b })
).rotateX(-Math.PI / 2));
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
scene.add(Object.assign(new THREE.DirectionalLight(0xffffff, 1), { position: { set: (x,y,z) => { } } }));
// TODO: додайте фізику гравітації тут
let vy = 0;
const GRAVITY = 9.8; // м/с²
const RESTITUTION = 0.7; // пружність
const FLOOR_Y = 0.5; // радіус м'яча
let last = performance.now();
function animate() {
requestAnimationFrame(animate);
const now = performance.now();
const dt = Math.min((now - last) / 1000, 0.05);
last = now;
// ← Ваш код тут
renderer.render(scene, camera);
}
animate();
vy -= GRAVITY * dt. Потім рухайте м'яч:
ball.position.y += vy * dt. Знак мінус змушує
гравітацію тягнути донизу (від'ємний Y).
if (ball.position.y < FLOOR_Y). Якщо умова
істинна, поверніть його назад: ball.position.y = FLOOR_Y, потім
змініть напрямок і послабте швидкість:
vy = Math.abs(vy) * RESTITUTION. Якщо
vy < 0.1, прирівняйте її до 0, щоб м'яч
остаточно зупинився.
<input type="range" min="0" max="30"
value="9.8">.
Зчитуйте його значення всередині циклу анімації як
const g = parseFloat(slider.value). Не
забудьте про <label> для доступності.
vy -= GRAVITY * dt;
ball.position.y += vy * dt;
if (ball.position.y < FLOOR_Y) {
ball.position.y = FLOOR_Y;
vy = Math.abs(vy) * RESTITUTION;
if (vy < 0.05) vy = 0;
}