Refactored the WHOLE project
From a simple test file, we're now on road to create a real project Took 3 hours, but code looks nice
This commit is contained in:
37
src/utils/addAssetsOnScene.js
Normal file
37
src/utils/addAssetsOnScene.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import * as THREE from 'three';
|
||||
import * as MathUtils from 'three/src/math/MathUtils.js';
|
||||
import { createGround } from '../objects/ground.js';
|
||||
import {loadModel} from './import.js';
|
||||
|
||||
|
||||
function alignGround(ground, MovingObject){
|
||||
/*Function used to place an object on top of another object. In fact, this is used only to place correctly objects on the ground*/
|
||||
const boundingBoxGround = new THREE.Box3().setFromObject(ground);
|
||||
const boundingBoxMovingObject = new THREE.Box3().setFromObject(MovingObject);
|
||||
|
||||
const MovingObjectHeight = boundingBoxMovingObject.max.z - boundingBoxMovingObject.min.z;
|
||||
MovingObject.position.y = MovingObjectHeight/2 + boundingBoxGround.max.z;
|
||||
}
|
||||
|
||||
export async function addAssetsOnScene(scene){
|
||||
/*This function takes the scene as arg, and is used to load everything needed on the terrain.
|
||||
Player, trees, fences, and everything displayed on the screen is added by this function, at the right place
|
||||
|
||||
Will return an object containing created objects*/
|
||||
|
||||
scene.add(new THREE.AmbientLight(0x404040, 50));//Light, required to see
|
||||
|
||||
const ground = createGround();
|
||||
scene.add(ground);
|
||||
|
||||
const player = await loadModel('src/objects/models/player.gltf');//Loading player
|
||||
player.scene.scale.set(0.2,0.2,0.2);
|
||||
alignGround(ground, player.scene);
|
||||
player.scene.rotateOnWorldAxis(new THREE.Vector3(1,0,0), MathUtils.degToRad(90));//Must be standing up
|
||||
scene.add( player.scene );
|
||||
|
||||
return {
|
||||
ground: ground,
|
||||
player: player,
|
||||
};
|
||||
}
|
||||
28
src/utils/animateMesh.js
Normal file
28
src/utils/animateMesh.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
const ANIMATION_SPEED_MULTIPLIER = 1.4;
|
||||
let mixersToUpdateEachFrame = [];
|
||||
|
||||
export function addAnimationMixerOnMesh(mesh, actions){
|
||||
//See https://threejs.org/docs/#manual/en/introduction/Animation-system
|
||||
/*Function used to add an animationMixer on a mesh, so we can easily start or stop animations
|
||||
Takes the animated mesh, and a list of actions names that should become animated */
|
||||
|
||||
const mixer = new THREE.AnimationMixer(mesh.scene);//We create a new mixer to manage every animations on this mesh
|
||||
|
||||
mesh.animationMixer = mixer;//We add this mixer on the mesh
|
||||
mesh.animationActions = {};//And create an object that will hold actions
|
||||
|
||||
actions.forEach(element => {
|
||||
const clip = THREE.AnimationClip.findByName( mesh.animations, element );//For each given action name, we get a clip
|
||||
mesh.animationActions[element] = mixer.clipAction(clip);//and save it as an action
|
||||
});
|
||||
|
||||
mixersToUpdateEachFrame.push(mixer);
|
||||
}
|
||||
|
||||
export function updateAnimations(deltaSeconds){
|
||||
mixersToUpdateEachFrame.forEach(element => {
|
||||
element.update(deltaSeconds * ANIMATION_SPEED_MULTIPLIER);
|
||||
});
|
||||
};
|
||||
18
src/utils/import.js
Normal file
18
src/utils/import.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
|
||||
const loader = new GLTFLoader();
|
||||
|
||||
export function loadModel(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
loader.load(
|
||||
path,
|
||||
(gltf) => {
|
||||
resolve(gltf);
|
||||
},
|
||||
undefined,
|
||||
(error) => {
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
export function alignGround(ground, MovingObject){
|
||||
const boundingBoxGround = new THREE.Box3().setFromObject(ground);
|
||||
const boundingBoxMovingObject = new THREE.Box3().setFromObject(MovingObject);
|
||||
|
||||
const MovingObjectHeight = boundingBoxMovingObject.max.z - boundingBoxMovingObject.min.z;
|
||||
MovingObject.position.y = MovingObjectHeight/2 + boundingBoxGround.max.z;
|
||||
}
|
||||
69
src/utils/playerMovement.js
Normal file
69
src/utils/playerMovement.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import * as THREE from 'three';
|
||||
import * as MathUtils from 'three/src/math/MathUtils.js';
|
||||
|
||||
const PLAYER_SPEED = 0.015;
|
||||
const ROTATION_SPEED = 0.05; // Vitesse de rotation
|
||||
const playerDirection = new THREE.Vector3(0, 0, 0);
|
||||
const playerRotation = new THREE.Quaternion();
|
||||
|
||||
//Managing keys
|
||||
export function handleKeyDown(event) {
|
||||
switch (event.code) {
|
||||
case 'ArrowUp':
|
||||
case 'KeyW':
|
||||
playerDirection.y = 1; // Up
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
case 'KeyS':
|
||||
playerDirection.y = -1; // Back
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
case 'KeyA':
|
||||
playerDirection.x = -1; // Left
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
case 'KeyD':
|
||||
playerDirection.x = 1; // Right
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function handleKeyUp(event) {
|
||||
switch (event.code) {
|
||||
case 'ArrowUp':
|
||||
case 'KeyW':
|
||||
case 'ArrowDown':
|
||||
case 'KeyS':
|
||||
playerDirection.y = 0; // Arrêter le mouvement vertical
|
||||
break;
|
||||
case 'ArrowLeft':
|
||||
case 'KeyA':
|
||||
case 'ArrowRight':
|
||||
case 'KeyD':
|
||||
playerDirection.x = 0; // Arrêter le mouvement horizontal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function updatePlayerPositionAnimation(player, camera) {
|
||||
/* Function called in the main loop
|
||||
Used to calculate the position and orientation of the player
|
||||
Also used to start and stop walking animation */
|
||||
const delta = playerDirection.clone().multiplyScalar(PLAYER_SPEED);
|
||||
player.scene.position.add(delta);
|
||||
camera.position.add(delta);//The camera must follow the player
|
||||
|
||||
if (playerDirection.length() > 0) {//If a movement key is pressed ( or something in playerDirection )
|
||||
if(!player.animationActions.Walk.isRunning()) player.animationActions.Walk.play();//Playing walk animation
|
||||
|
||||
const angle = Math.atan2(playerDirection.x, -playerDirection.y);//Get the angle between center (0;0) and the coordinates, which are directly provided by the pressed keys
|
||||
const targetRotation = new THREE.Quaternion();
|
||||
|
||||
targetRotation.setFromAxisAngle(new THREE.Vector3(0, 1, 0), angle);
|
||||
playerRotation.slerp(targetRotation, ROTATION_SPEED);//Slowly moving from playerRotation to targetRotation
|
||||
player.scene.setRotationFromQuaternion(playerRotation);
|
||||
player.scene.rotateOnWorldAxis(new THREE.Vector3(1, 0, 0), MathUtils.degToRad(90));//Used to force the player to be standing up instead of sleeping
|
||||
}else{
|
||||
if(player.animationActions.Walk.isRunning()) player.animationActions.Walk.stop();//Not walking, we can stop this animation
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user