Zaczynając od kuli unoszącej się w powietrzu, dodaj siłę grawitacji, która przyspiesza piłkę w dół w każdej klatce. Gdy uderzy w podłogę, zastosuj odbicie pochłaniające energię, aby ostatecznie się zatrzymała. Poznaj całkowanie Eulera, akumulację prędkości i współczynnik restytucji.
-
Piłka spada z zastosowanym
vy += g * dtw każdej klatce -
Piłka odbija się od podłogi z
vy *= -restitution - Piłka zwalnia i zatrzymuje się (restitution < 1)
- Sterowanie: suwak siły grawitacji (0 → 30 m/s²)
// Three.js r160 jest już wczytane
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);
// Piłka
const ball = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 32, 32),
new THREE.MeshStandardMaterial({ color: 0x3b82f6 })
);
ball.position.y = 5;
scene.add(ball);
// Podłoga
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: dodaj tutaj fizykę grawitacji
let vy = 0;
const GRAVITY = 9.8; // m/s²
const RESTITUTION = 0.7; // odbojność
const FLOOR_Y = 0.5; // promień piłki
let last = performance.now();
function animate() {
requestAnimationFrame(animate);
const now = performance.now();
const dt = Math.min((now - last) / 1000, 0.05);
last = now;
// ← Twój kod tutaj
renderer.render(scene, camera);
}
animate();
vy -= GRAVITY * dt. Następnie przesuń piłkę:
ball.position.y += vy * dt. Znak minus
sprawia, że grawitacja ciągnie w dół (ujemne Y).
if (ball.position.y < FLOOR_Y). Jeśli
prawda, przypnij ją z powrotem:
ball.position.y = FLOOR_Y, następnie odwróć
i osłab prędkość:
vy = Math.abs(vy) * RESTITUTION. Jeśli
vy < 0.1, ustaw ją na 0, aby piłka
naprawdę się zatrzymała.
<input type="range" min="0" max="30"
value="9.8">
na canvasie. Odczytaj jej wartość w pętli animacji jako
const g = parseFloat(slider.value). Nie
zapomnij o <label> dla dostępności.
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;
}