As a newcomer to THREE.js with limited physics knowledge, I am in the process of developing a top-view football game engine. However, I am currently facing challenges related to the ball's movement.
When attempting to move the ball from side to side, its rotation always faces one direction, and I am struggling to make it rotate in the direction it is moving towards.
I have included a simple code snippet showcasing this issue. Any assistance you can provide would be greatly appreciated.
/*
*
* SET UP MOTION PARAMS
*
*/
var degrees = 10;
var power = 1;
var angleRad = degrees * Math.PI / 120;
var velocityX = Math.cos(angleRad) * power;
var velocityY = Math.sin(angleRad) * power;
var velocityZ = 1;
var friction = 1;
var gravity = 0.2;
var bounciness = 0.9;
window.onload = function (params) {
/*
*
* SET UP THE WORLD
*
*/
//set up the ratio
var gWidth = window.innerWidth;
var gHeight = window.innerHeight;
var ratio = gWidth / gHeight;
var borders = [40, 24] //indicate where the ball needs to move in mirror position
//set the scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xeaeaea);
//set the camera
var camera = new THREE.PerspectiveCamera(35, ratio, 0.1, 1000);
camera.position.z = 120;
//set the light
var light = new THREE.SpotLight(0xffffff, 1);
light.position.set(100, 1, 0);
light.castShadow = true;
light.position.set(0, 0, 100);
scene.add(light);
// set the renderer
var renderer = new THREE.WebGLRenderer();
//properties for casting shadow
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(gWidth, gHeight);
document.body.appendChild(renderer.domElement);
/*
*
* ADD MESH TO SCENE
*
*/
// create and add the ball
var geometry = new THREE.SphereGeometry(5, 5, 5);
var material = new THREE.MeshLambertMaterial({ color: 'gray' });
var ball = new THREE.Mesh(geometry, material);
ball.castShadow = true;
ball.receiveShadow = false;
scene.add(ball);
// create and add the field
var margin = 20;
var fieldRatio = 105 / 68;
var width = 90;
var height = width / fieldRatio;
var material = new THREE.MeshLambertMaterial({ color: 'green' });
var geometry = new THREE.BoxGeometry(width, height, 1);
var field = new THREE.Mesh(geometry, material);
field.receiveShadow = true;
field.position.z = -1;
scene.add(field);
/*
* setting up rotation axis
*/
var rotation_matrix = null;
var setQuaternions = function () {
setMatrix();
ball.rotation.set(Math.PI / 2, Math.PI / 4, Math.PI / 4); // Set initial rotation
ball.matrix.makeRotationFromEuler(ball.rotation); // Apply rotation to the object's matrix
}
var setMatrix = function () {
rotation_matrix = new THREE.Matrix4().makeRotationZ(angleRad); // Animated rotation will be in .01 radians along object's X axis
}
setQuaternions();
/*
*
* ANIMATION STEP
*
*/
var render = function (params) {
// add velocity to ball
ball.position.x += velocityX;
ball.position.z += velocityZ;
ball.position.y += velocityY;
//validate if ball is stop moving
if (Math.abs(velocityX) < 0.02 && Math.abs(velocityY) < 0.02) {
console.log("DONE!");
return;
}
// handle boucing effect
if (ball.position.z < 1) {
velocityZ *= -bounciness;
ball.position.z = 1
}
// Update the object's rotation & apply it
ball.matrix.multiply(rotation_matrix);
ball.rotation.setFromRotationMatrix(ball.matrix);
//reducing speed by friction
angleRad *= friction;
velocityX *= friction;
velocityY *= friction;
velocityZ *= friction;
//set up the matrix
setMatrix();
//validate ball is withing its borders otherwise go in the mirror direction
if (Math.abs(ball.position.x) > borders[0]) {
velocityX *= -1;
ball.position.x = (ball.position.x < 0) ? borders[0] * -1 : borders[0];
}
if (Math.abs(ball.position.y) > borders[1]) {
velocityY *= -1;
ball.position.y = (ball.position.y < 0) ? borders[1] * -1 : borders[1];
}
// reduce ball height with gravity
velocityZ -= gravity;
//render the page
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
}
body {
padding: 0;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<html>
<head>
</head>
<body>
</body>
</html>