128 lines
4.1 KiB
JavaScript
128 lines
4.1 KiB
JavaScript
import { Cube } from "./Cube.js";
|
|
import { Rotation } from "./utils.js";
|
|
import { jumpDemo } from "./Game.js";
|
|
|
|
export class Player extends Cube {
|
|
constructor(color) {
|
|
super(color, "assets/images/player.jpg");
|
|
|
|
this.data.position.x = -2;
|
|
this.data.rotation.x = this.gameRotation;
|
|
|
|
this.movementData = new Rotation(this.data.position);
|
|
}
|
|
|
|
/**
|
|
* Play the player animation
|
|
* @param {*} listEnnemies
|
|
* @param {boolean} demo
|
|
* @returns boolean if the player is alive or not
|
|
*/
|
|
animation = (listEnnemies, demo) => {
|
|
if (demo) {
|
|
listEnnemies.forEach((ennemy) => {
|
|
const pos = ennemy.position.x - this.data.position.x;
|
|
if (pos > 0 && pos < Math.random() * 1.5 + 0.5) {
|
|
dispatchEvent(jumpDemo);
|
|
}
|
|
});
|
|
}
|
|
|
|
// If we jump
|
|
if (this.movementData.state) {
|
|
// Rotation
|
|
this.data.rotation.y -= this.movementData.rotationVelocity / 1.6;
|
|
|
|
// If we're falling (2nd part of the jump)
|
|
if (this.movementData.falling()) {
|
|
// Gravity!
|
|
this.data.position.y -= this.movementData.jumpVelocity;
|
|
} else {
|
|
// If we're jumping (1st part of the jump) : jumping
|
|
this.data.position.y += this.movementData.jumpVelocity;
|
|
|
|
// Check if the jump stop and we need to goes down
|
|
if (this.data.position.y >= this.movementData.jump) {
|
|
this.movementData.changeJump(this.movementData.default.y);
|
|
}
|
|
}
|
|
|
|
// End of the rotation
|
|
if (this.data.rotation.y <= this.movementData.rotation) {
|
|
// Force the final rotation
|
|
this.data.rotation.y = this.movementData.rotation;
|
|
|
|
// Force the end of the jump
|
|
this.data.position.y = this.movementData.default.y;
|
|
|
|
// End
|
|
this.movementData.changeState();
|
|
}
|
|
}
|
|
|
|
return !this.checkCollision(listEnnemies);
|
|
};
|
|
|
|
/**
|
|
* Handle player's input
|
|
* @param {string} key key pressed
|
|
*/
|
|
controlUser = (key) => {
|
|
if (key.code == "Space" && !this.movementData.state) {
|
|
this.movementData.changeRotation(
|
|
this.data.rotation.y - Math.PI / 2
|
|
);
|
|
this.movementData.changeJump(
|
|
3 * this.data.position.y + Math.PI / 2
|
|
);
|
|
this.movementData.changeState();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Check collisions with ennemies
|
|
* @param {*} listEnnemies
|
|
* @returns boolean
|
|
*/
|
|
checkCollision = (listEnnemies) => {
|
|
for (
|
|
let vertexIndex = 0;
|
|
vertexIndex < this.data.geometry.attributes.position.array.length;
|
|
vertexIndex++
|
|
) {
|
|
// Retrieve the vertex from the player geometry
|
|
const localVertex = new THREE.Vector3()
|
|
.fromBufferAttribute(
|
|
this.data.geometry.attributes.position,
|
|
vertexIndex
|
|
)
|
|
.clone();
|
|
|
|
// Apply the player matrix for the vector
|
|
const globalVertex = localVertex.applyMatrix4(this.data.matrix);
|
|
|
|
// Substract the position to obtain the position
|
|
const directionVector = globalVertex.sub(this.data.position);
|
|
|
|
// Create the raycaster for this vector from the player position
|
|
const rc = new THREE.Raycaster(
|
|
this.data.position,
|
|
directionVector.clone().normalize()
|
|
);
|
|
|
|
// Check if the raycaster hit ennemies
|
|
const collisionResults = rc.intersectObjects(listEnnemies, false);
|
|
if (
|
|
collisionResults.length > 0 &&
|
|
directionVector.length() < 1.5 &&
|
|
collisionResults[0].distance < directionVector.length()
|
|
) {
|
|
// Yes some ennemies are in the way
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// No ennemies found
|
|
return false;
|
|
};
|
|
}
|