- new class SoloGame/MultiGame
This commit is contained in:
Kum1ta
2024-08-28 14:09:54 +02:00
parent e35ddd2477
commit f2414f56a8
9 changed files with 299 additions and 175 deletions

View File

@ -0,0 +1,129 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Ball.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/20 17:02:47 by edbernar #+# #+# */
/* Updated: 2024/08/28 11:17:08 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import * as THREE from 'three';
class Ball
{
object = null;
centerPos = {};
limits = {};
interval = null;
constructor(scene, map)
{
this.object = this.#createBall();
this.centerPos = map.centerPos;
this.centerPos.y += this.object.geometry.parameters.radius;
this.limits = map.playerLimits;
this.resetPosBall();
scene.add(this.object);
}
#createBall()
{
const geometry = new THREE.SphereGeometry(0.15);
const material = new THREE.MeshPhysicalMaterial({ color: 0xff5555 });
const mesh = new THREE.Mesh(geometry, material);
mesh.receiveShadow = true;
mesh.castShadow = true;
mesh.position.set(this.centerPos.x, this.centerPos.y, this.centerPos.z);
return (mesh);
}
resetPosBall()
{
this.setPosition(this.centerPos.x, this.centerPos.y, this.centerPos.z);
}
setPosition(x, y, z)
{
this.object.position.set(x, y, z);
}
changeGravity(ballIsOnJumper)
{
let diffTop = this.limits.up - this.object.position.y;
let diffBot = this.object.position.y - this.limits.down;
let speed = 0.15;
const slower = speed / 3;
if (diffBot > diffTop)
speed *= -1;
if (this.interval)
clearInterval(this.interval);
this.interval = setInterval(() => {
this.object.position.y += speed;
if ((speed > 0 && this.object.position.y >= this.limits.up)
|| (speed < 0 && this.object.position.y <= this.limits.down))
{
clearInterval(this.interval);
this.interval = null;
if (speed > 0)
this.setPosition(this.object.position.x, this.limits.up, this.object.position.z);
else
this.setPosition(this.object.position.x, this.limits.down, this.object.position.z);
ballIsOnJumper.can = true;
}
speed -= speed * slower;
}, 10);
}
/*---------------- FUNCTION FOR TEST ----------------*/
initMoveBallTmp()
{
console.warn("Don't forget to remove function initMoveBallTmp");
const speedBallTmp = 0.1;
let warn = false;
document.addEventListener('keypress', (e) => {
if (!this.object && !warn)
{
console.warn("EventListener in initMoveBallTmp() is still here");
warn = true;
return ;
}
if (e.key == '4')
this.object.position.x -= speedBallTmp;
if (e.key == '6')
this.object.position.x += speedBallTmp;
if (e.key == '8')
this.object.position.z -= speedBallTmp;
if (e.key == '2')
this.object.position.z += speedBallTmp;
if (e.key == '9')
this.changeGravity();
});
}
/*---------------------------------------------------*/
dispose()
{
if (this.interval)
clearInterval(this.interval);
this.interval = null;
if (this.object)
{
if (this.object.geometry)
this.object.geometry.dispose();
if (this.object.material)
this.object.material.dispose();
if (this.object.texture)
this.object.texture.dispose();
}
this.object = null;
}
}
export { Ball };

View File

@ -0,0 +1,552 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Map.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/20 14:52:55 by hubourge #+# #+# */
/* Updated: 2024/08/28 11:04:41 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
// import * as THREE from '/static/javascript/three/build/three.module.js';
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { Video } from './Video.js';
let loader = null;
let scene = null;
let videoList = [];
let interval2 = null;
let videoCanvas = null;
let videoCanvasTexture = null;
let materialCanvas = null;
// Plane
let textureLoaderPlane = null;
let texturePlane = null;
// Border wall
// Gravity changer
// Wall obstacle
// Banner
// Gravity changer animation
class Map
{
arrObject = [];
ballObject = null;
mapLength = 0;
banner = null;
centerPos = {
x: -1,
y: -1,
z:-1
};
playerLimits = {
up : 3,
down: 0.3,
left: -3,
right: 3,
};
ballIsOnJumper = {
can: true
};
dispose()
{
videoList.forEach(elem => {
elem.video.pause();
elem.video.src = '';
elem.video.removeAttribute('src');
elem.video.load();
})
videoList = null;
videoCanvas.remove();
if (videoCanvasTexture)
videoCanvasTexture.dispose();
if (materialCanvas)
materialCanvas.dispose();
videoCanvas = null;
textureLoaderPlane = null;
loader = null;
if (texturePlane)
texturePlane.dispose();
this.arrObject.forEach(elem => {
if (elem.mesh instanceof THREE.Group)
{
elem.mesh.children.forEach(child => {
if (child.geometry)
child.geometry.dispose();
if (child.material)
child.material.dispose();
if (child.texture)
child.texture.dispose();
});
}
else
{
if (elem.mesh.geometry)
elem.mesh.geometry.dispose();
if (elem.mesh.material)
elem.mesh.material.dispose();
if (elem.mesh.texture)
elem.mesh.texture.dispose();
}
scene.remove(elem.mesh);
});
this.arrObject = null;
if (interval2)
clearInterval(interval2);
scene = null;
}
constructor(sceneToSet, length, obstacles)
{
loader = new GLTFLoader();
scene = sceneToSet;
this.centerPos.x = 0;
this.centerPos.y = 0.15;
this.centerPos.z = -length / 2 + length / 2;
this.mapLength = length;
scene.add(this.#createPlanes(7.5, length, -(Math.PI / 2), "planeBottom", true, '/textures/pastel.jpg'));
scene.add(this.#createPlanes(7.5, length, (Math.PI / 2), "planeTop", false, '/textures/pastel.jpg'));
scene.add(this.#createWall(-3.5, 0.4, -length/2, "wallLeft"));
scene.add(this.#createWall(3.5, 0.4, -length/2, "wallRight"));
this.#createBanner();
if (obstacles)
this.#generateObstacle();
};
#createPlanes(x, y, rot, name, isBottom, visual)
{
let geometryPlane = null;
let materialPlane = null;
let meshPlane = null;
for (let i = 0; i < this.arrObject.length; i++)
{
if (this.arrObject[i].name == name)
throw Error("Name already exist.");
}
geometryPlane = new THREE.PlaneGeometry(x, y);
if (typeof(visual) == 'string')
{
textureLoaderPlane = new THREE.TextureLoader();
texturePlane = textureLoaderPlane.load(visual);
materialPlane = new THREE.MeshPhysicalMaterial({ map: texturePlane });
}
else if (typeof(visual) == 'number')
materialPlane = new THREE.MeshPhysicalMaterial({ color: visual });
else
materialPlane = new THREE.MeshPhysicalMaterial();
meshPlane = new THREE.Mesh(geometryPlane, materialPlane);
meshPlane.rotateX(rot);
if (isBottom)
meshPlane.position.set(0, 0.15, 0);
else
meshPlane.position.set(0, 3.15, 0);
this.arrObject.push({mesh: meshPlane, name: name, type: "plane"});
meshPlane.receiveShadow = true;
return (meshPlane);
};
#createWall(x, y, z, name)
{
let geometryWall = null;
let materialWall = null;
let meshWall = null;
for (let i = 0; i < this.arrObject.length; i++)
{
if (this.arrObject[i].name == name)
throw Error("Name already exist.");
}
geometryWall = new THREE.BoxGeometry(0.05, 0.5, 0.75);
materialWall = new THREE.MeshPhysicalMaterial();
meshWall = new THREE.Mesh(geometryWall, materialWall);
meshWall.position.set(x, y, z);
materialWall.transparent = true;
materialWall.opacity = 0.5;
this.arrObject.push({mesh: meshWall, name: name, type: "wall"});
return (meshWall);
};
#createGravityChanger(x, y, z, name, typeName, onTop)
{
let geometry1 = null;
let material1 = null;
let ring1 = null;
let geometry2 = null;
let material2 = null;
let ring2 = null;
let geometry3 = null;
let material3 = null;
let ring3 = null;
let geometry4 = null;
let material4 = null;
let circle1 = null;
let geometry5 = null;
let material5 = null;
let circle2 = null;
let geometry6 = null;
let material6 = null;
let collider = null;
let groupJumper = null;
for (let i = 0; i < this.arrObject.length; i++)
{
if (this.arrObject[i].name == name)
throw Error("Name already exist.");
}
geometry1 = new THREE.TorusGeometry(1, 0.1, 12, 24);
material1 = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
ring1 = new THREE.Mesh(geometry1, material1);
ring1.rotateX(-Math.PI / 2);
ring1.position.set(0, 0, 0);
ring1.scale.set(0.2, 0.2, 0.2);
material1.transparent = true;
material1.opacity = 0.75;
geometry2 = new THREE.TorusGeometry(1, 0.1, 12, 24);
material2 = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
ring2 = new THREE.Mesh(geometry2, material2);
ring2.rotateX(-Math.PI / 2);
ring2.position.set(0, 0 + 0.1, 0);
ring2.scale.set(0.18, 0.18, 0.18);
material2.transparent = true;
material2.opacity = 0.65;
geometry3 = new THREE.TorusGeometry(1, 0.1, 12, 24);
material3 = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
ring3 = new THREE.Mesh(geometry3, material3);
ring3.rotateX(-Math.PI / 2);
ring3.position.set(0, 0 + 0.2, 0);
ring3.scale.set(0.16, 0.16, 0.16);
material3.transparent = true;
material3.opacity = 0.35;
geometry4 = new THREE.CircleGeometry(0.2, 24);
material4 = new THREE.MeshPhysicalMaterial({color: 0xaaffaa});
circle1 = new THREE.Mesh(geometry4, material4);
circle1.rotateX(-Math.PI / 2);
circle1.position.set(0, 0 - 0.048, 0);
geometry5 = new THREE.CircleGeometry(0.24, 24);
material5 = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
circle2 = new THREE.Mesh(geometry5, material5);
circle2.rotateX(-Math.PI / 2);
circle2.position.set(0, 0 - 0.049, 0);
geometry6 = new THREE.CylinderGeometry(0.15, 0.15, 0.35);
material6 = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
collider = new THREE.Mesh(geometry6, material6);
collider.position.set(0, 0 + 0.1, 0);
material6.transparent = true;
material6.opacity = 0.1;
groupJumper = new THREE.Group();
groupJumper.add(ring1);
groupJumper.add(ring2);
groupJumper.add(ring3);
groupJumper.add(circle1);
groupJumper.add(circle2);
groupJumper.add(collider);
// Set groupJumper position groud / top
for (let i = 0; i < groupJumper.children.length && onTop; i++)
groupJumper.children[i].position.set(x, y - 0.1, z);
for (let i = 0; i < groupJumper.children.length && !onTop; i++)
groupJumper.children[i].position.set(x, y, z);
let distanceY = [-0.04, -0.14, -0.24, 0.048, 0.049, -0.125];
let rotate = [0, 0, 0, 1, 1, 0];
// Set distance between each object
for (let i = 0; i < groupJumper.children.length; i++)
{
if (onTop)
{
if (rotate[i])
groupJumper.children[i].rotateX(Math.PI);
groupJumper.children[i].position.set(groupJumper.children[i].position.x, groupJumper.children[i].position.y + distanceY[i], groupJumper.children[i].position.z);
}
else
groupJumper.children[i].position.set(groupJumper.children[i].position.x, groupJumper.children[i].position.y - distanceY[i], groupJumper.children[i].position.z);
}
this.arrObject.push({mesh: groupJumper, name: name, type: typeName});
scene.add(groupJumper);
};
#createWallObstacle(x, y, size, onTop)
{
let geometryWallObs = null;
let materialWallObs = null;
let meshWallObs = null;
geometryWallObs = new THREE.BoxGeometry(size, 0.5, 0.1);
materialWallObs = new THREE.MeshPhysicalMaterial({color: 0xaaaafe});
meshWallObs = new THREE.Mesh(geometryWallObs, materialWallObs);
if (onTop)
meshWallObs.position.set(x, this.playerLimits.up - 0.1, y);
else
meshWallObs.position.set(x, 0.4, y);
return (meshWallObs);
}
/* Todo (Hugo) :
- Faire une zone Player banner (importer un model blender)
- Faire une zone pour les pub (s'inspirer de theFinals) (ok)
- Effet gros pixel (ok)
- Effet de lumière en 2d
- Preparer une animation pour le but
*/
#createBanner()
{
// Create canvas
videoCanvas = document.createElement('canvas');
const ctx = videoCanvas.getContext('2d');
videoCanvas.width = 100 * 2.33 * 20;
videoCanvas.height = 100;
const path = [
'../textures/video/goal2.webm',
'../textures/video/pingpong.mp4',
'../textures/video/catch.mp4',
'../textures/video/easteregg.webm',
'../textures/video/fortnite.mp4',
'../textures/video/Composition 1_1.webm',
]
path.sort(() => Math.random() - 0.5);
let spacingImages = [
100 * 2.33 * 10 - (100 * 2.33), // 2 images
100 * 2.33 * 5 - (100 * 2.33), // 4 images
100 * 2.33 * 2.5 - (100 * 2.33), // 8 images
100 * 2.33 * 1.25 - (100 * 2.33), // 16 images
];
const nbVideos = 5; // 1, 2, 3, 4, 5
const nbImages = 3; // 0 = 2 img, 1 = 4 img, 2 = 8 img, 3 = 16 img
const startIndex = ((Math.random() * (path.length - nbVideos)).toFixed(0)) % path.length;
// const startIndex = 5;
for (let i = startIndex; i < (nbVideos + startIndex); i++)
{
let videoTmp = new Video(path[i]).video;
videoTmp.addEventListener('loadeddata', () => {
videoTmp.play();
drawVideoOnCanvas();
});
videoList.push({video: videoTmp, imageWidth: 100 * 2.33, imageHeight: 100});
}
function drawVideoOnCanvas()
{
if (videoCanvas)
{
ctx.clearRect(0, 0, videoCanvas.width, videoCanvas.height);
if (nbVideos == 0)
return ;
let nbDraw = 0;
let vIndex = 0;
let y = 0;
for (let x = 0; x < videoCanvas.width; x += (videoList[vIndex].imageWidth + spacingImages[nbImages]))
{
ctx.drawImage(videoList[vIndex].video, x, y, videoList[vIndex].imageWidth, videoList[vIndex].imageHeight);
nbDraw++;
if (nbVideos > 1)
vIndex++;
if (vIndex >= nbVideos)
vIndex = 0;
}
videoCanvasTexture.needsUpdate = true;
requestAnimationFrame(drawVideoOnCanvas);
}
}
// Create texture
videoCanvasTexture = new THREE.CanvasTexture(videoCanvas);
videoCanvasTexture.wrapS = THREE.RepeatWrapping;
videoCanvasTexture.wrapT = THREE.RepeatWrapping;
videoCanvasTexture.repeat.set(-1, 1);
materialCanvas = new THREE.MeshBasicMaterial({ map: videoCanvasTexture, side: THREE.BackSide , transparent: true});
loader.load( '../blender/exported/banner.glb', (gltf) => {
this.banner = gltf.scene.children[0];
gltf = null;
this.banner.material = materialCanvas;
this.banner.position.y += 1.7;
this.banner.rotation.x = (Math.PI);
this.banner.rotation.y += -0.15;
scene.add(this.banner);
interval2 = setInterval(() => {
this.banner.rotation.y += 0.001;
}, 10);
}, undefined, function ( error ) {
console.error( error );
} );
}
#animationGravityChanger(group, onTop)
{
let geometryGC = new THREE.TorusGeometry(1.5, 0.05, 12, 24);
let materialGC = new THREE.MeshPhysicalMaterial({color: 0x00ff00});
let ringGC = new THREE.Mesh(geometryGC, materialGC);
let landmarkGC = group.children[0];
let speed = 0.1;
let interval = null;
ringGC.rotateX(-Math.PI / 2);
ringGC.position.set(landmarkGC.position.x, landmarkGC.position.y, landmarkGC.position.z);
ringGC.scale.set(0.2, 0.2, 0.2);
materialGC.transparent = true;
scene.add(ringGC);
interval = setInterval(() => {
if (onTop)
ringGC.position.y -= speed;
else
ringGC.position.y += speed;
materialGC.opacity -= 0.02;
speed *= 0.90;
if (materialGC.opacity == 0)
clearInterval(interval);
}, 10);
}
#generateObstacle()
{
const wallPos = [
{ x: 1, y: 0, z: 1, onTop: false},
{ x: 1, y: 0, z: 1, onTop: true},
{ x: -1, y: 0, z: 1, onTop: false},
{ x: -1, y: 0, z: 1, onTop: true}
];
for (let i = 0; i < wallPos.length; i++)
{
if (Math.random() < 0.5)
scene.add(this.#createWallObstacle(wallPos[i].x, wallPos[i].y, wallPos[i].z, wallPos[i].onTop));
}
const type = "gravityChanger";
const typeNameBottom = "jumperBottom";
const typeNameTop = "jumperTop";
const jumperPos = [
{ x: -1.5, y: 0.2, z: this.mapLength / 4, type: type, typeName: typeNameBottom, onTop: false},
{ x: -1.5, y: 3.2, z: this.mapLength / 4, type: type, typeName: typeNameTop, onTop: true},
{ x: 1.5, y: 0.2, z: this.mapLength / 4, type: type, typeName: typeNameBottom, onTop: false},
{ x: 1.5, y: 3.2, z: this.mapLength / 4, type: type, typeName: typeNameTop, onTop: true},
{ x: -1.5, y: 0.2, z: -this.mapLength / 4, type: type, typeName: typeNameBottom, onTop: false},
{ x: -1.5, y: 3.2, z: -this.mapLength / 4, type: type, typeName: typeNameTop, onTop: true},
{ x: 1.5, y: 0.2, z: -this.mapLength / 4, type: type, typeName: typeNameBottom, onTop: false},
{ x: 1.5, y: 3.2, z: -this.mapLength / 4, type: type, typeName: typeNameTop, onTop: true}
];
for (let i = 0; i < jumperPos.length; i++)
{
if (Math.random() < 0.5)
{
this.#createGravityChanger(jumperPos[i].x, jumperPos[i].y, jumperPos[i].z, jumperPos[i].type + i, jumperPos[i].typeName, jumperPos[i].onTop);
if (i % 2 == 0)
i++;
}
}
};
update(ball)
{
for (let i = 0; i < this.arrObject.length; i++)
{
if (this.arrObject[i].name == "wallLeft")
{
// Move the wall with the ball position
if (ball.object.position.z < this.mapLength / 2 - 0.35 && ball.object.position.z > -this.mapLength / 2 + 0.35)
this.arrObject[i].mesh.position.z = ball.object.position.z;
if (ball.object.position.y > 0.4 + 0.1 && ball.object.position.y < 3.2)
this.arrObject[i].mesh.position.y = ball.object.position.y - 0.1;
// Change the opacity of the wall
let diff = ball.object.position.x - this.arrObject[i].mesh.position.x - 0.1;
if (diff > 2)
this.arrObject[i].mesh.material.opacity = 0;
else
this.arrObject[i].mesh.material.opacity = 1 - (diff / 2);
}
if (this.arrObject[i].name == "wallRight")
{
// Move the wall with the ball position
if (ball.object.position.z < this.mapLength / 2 - 0.35 && ball.object.position.z > -this.mapLength / 2 + 0.35)
this.arrObject[i].mesh.position.z = ball.object.position.z;
if (ball.object.position.y > 0.4 + 0.1 && ball.object.position.y < 3.2)
this.arrObject[i].mesh.position.y = ball.object.position.y - 0.1;
// Change the opacity of the wall
let diff = this.arrObject[i].mesh.position.x - ball.object.position.x - 0.1;
if (diff > 2)
this.arrObject[i].mesh.material.opacity = 0;
else
this.arrObject[i].mesh.material.opacity = 1 - (diff / 2);
}
if (this.arrObject[i].type == 'jumperBottom')
{
const cylinder = this.arrObject[i].mesh.children[5];
const distance = ball.object.position.distanceTo(cylinder.position);
const speed = 0.1;
// Detect if the ball is on the jumper
if (distance < 0.25 && this.ballIsOnJumper.can)
{
this.ballIsOnJumper.can = false;
ball.changeGravity(this.ballIsOnJumper);
this.#animationGravityChanger(this.arrObject[i].mesh, false);
}
// Gravity changer animation
for (let j = 0; j < 3; j++)
{
this.arrObject[i].mesh.children[j].rotation.x = Math.sin(Date.now() * 0.001 + (j - 2) * 5) * 0.1 + Math.PI / 2;
this.arrObject[i].mesh.children[j].rotation.y = Math.sin(Date.now() * 0.001 + (j - 2) * 5) * 0.1 + Math.cos(Date.now() * 0.001) * 0.1;;
}
}
if (this.arrObject[i].type == 'jumperTop')
{
const cylinder = this.arrObject[i].mesh.children[5];
const distance = ball.object.position.distanceTo(cylinder.position);
const speed = 0.1;
// Detect if the ball is on the jumper
if (distance < 0.4 && this.ballIsOnJumper.can)
{
this.ballIsOnJumper.can = false;
ball.changeGravity(this.ballIsOnJumper);
this.#animationGravityChanger(this.arrObject[i].mesh, true);
}
// Gravity changer animation
for (let j = 0; j < 3; j++)
{
this.arrObject[i].mesh.children[j].rotation.x = Math.sin(Date.now() * 0.001 + (j - 2) * 5) * 0.1 + Math.PI / 2;
this.arrObject[i].mesh.children[j].rotation.y = Math.sin(Date.now() * 0.001 + (j - 2) * 5) * 0.1 + Math.cos(Date.now() * 0.001) * 0.1;;
}
}
}
};
};
export { Map };

View File

@ -0,0 +1,50 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Opponent.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/21 10:34:49 by edbernar #+# #+# */
/* Updated: 2024/08/28 11:39:59 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import { playerExist } from './Player'
import * as THREE from 'three';
// import * as THREE from '/static/javascript/three/build/three.module.js';
let opponentExist = false;
class Opponent
{
object = null;
speed = 0.1;
interval = null;
limits = {};
player = null;
constructor (object, map)
{
if (opponentExist)
throw Error("Opponent is already init.");
opponentExist = true;
this.object = object;
this.limits = map.limits;
this.object.position.set(0, 0.3, -map.mapLength / 2 + 0.2);
}
dispose()
{
opponentExist = false;
}
update()
{
//en attente du serveur
}
}
export { Opponent };

View File

@ -0,0 +1,303 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Player.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/18 00:30:31 by edbernar #+# #+# */
/* Updated: 2024/08/28 11:38:45 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
import * as THREE from 'three';
// import * as THREE from '/static/javascript/three/build/three.module.js';
/*
Explication du code :
- Un seul joueur peut etre instancié, sinon ça throw une erreur
- Lorsqu'une touche est pressée, celle-ci sera ajoutée à la variable "pressedButton"
Exemple : w et a sont pressées -> pressedButton = ['w', 'a']
- Les lignes avec cleanup sont l'êquivalent d'un destructeur en CPP
- Pour appliquer des actions sur les touches, il suffit de faire ça dans la fonction
update en regardant si la touche voulue est dans la variable "pressedButton"
- Par défaut, la caméra est accrochée, si on veut qu'elle ne bouge plus, il faut
modifier "cameraFixed" à true (se fait avec la touche 'm' en jeu)
- Si on utilise une touche qui ne sera utilisée que pour un appui simple, il faudra la
mettre dans 'addEventListerner('keypress') et pas dans update() pour eviter les
problèmes de touche non détecté
- La variable "limits" sert à délimiter les mouvements de la barre
*/
/*
Todo (Eddy) :
- Ajouter une camera sur l'object (OK)
- Faire une fonction pour changer le mode de la camera (fix ou accrochée) (OK)
- Ajouter une rotation quand la caméra est fixe (OK)
- Corriger bug quand changement de caméra (camera qui se remet au dessus
quand on repasse au dessus alors qu'elle devrait être en dessous vu que la
barre est en haut). Mais peut etre faire ça quand la barre aura des mouvements
définis sur la hauteur. (OK)
- Ajouter les mouvements définis sur l'axe y (OK)
- Faire une fonction qui change de camera quand il y a un but avec un fondu en noir (OK)
- Ajouter un zoom sur la camera de la fonction pointAnimation (OK)
- Ajouter une fonction pour l'animation de point marqué (OK)
*/
let playerExist = false;
let isOnPointAnim = false;
let pressedButton = [];
class Player
{
object = null;
camera = null;
speed = 4;
cameraFixed = false;
interval = null;
limits = {};
previousTime = Date.now();
deltaTime = 1;
constructor (object, map)
{
if (playerExist)
throw Error("Player is already init.");
playerExist = true;
isOnPointAnim = false;
pressedButton = [];
this.object = object;
this.limits = map.playerLimits;
this.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 10000);
this.object.position.set(0, this.limits.down, map.mapLength / 2 - 0.2);
this.setCameraPosition(
this.object.position.x,
this.object.position.y + 0.7,
this.object.position.z + 1.5
);
document.addEventListener('keydown', addKeyInArr);
document.addEventListener('keyup', remKeyInArr);
document.addEventListener('keypress', simplePressKey);
}
dispose()
{
playerExist = false;
isOnPointAnim = false;
document.removeEventListener('keydown', addKeyInArr);
document.removeEventListener('keyup', remKeyInArr);
document.removeEventListener('keypress', simplePressKey);
pressedButton = [];
if (this.interval)
clearInterval(interval);
}
pointAnimation(map)
{
const tmpCamera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 10000);
const tmp = this.camera;
let interval = null;
const startColor = this.object.material.color.clone();
let hue = 0;
document.getElementsByTagName('canvas')[0].style.animation = 'fadeIn 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(0)';
setTimeout(() => {
document.getElementsByTagName('canvas')[0].style.animation = 'fadeOut 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(1)';
}, 300)
setTimeout(() => {
tmpCamera.position.set(this.limits.left, this.limits.up / 2 + 0.5, map.centerPos.z);
isOnPointAnim = true;
this.camera = tmpCamera;
interval = setInterval(() => {
tmpCamera.lookAt(this.object.position);
hue += 0.01;
if (hue > 1)
hue = 0;
this.object.material.color.setHSL(hue, 1, 0.5);
tmpCamera.fov -= 0.05;
tmpCamera.updateProjectionMatrix();
}, 10);
setTimeout(() => {
clearInterval(interval);
document.getElementsByTagName('canvas')[0].style.animation = null;
document.getElementsByTagName('canvas')[0].style.animation = 'fadeIn 0.19s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(0)';
setTimeout(() => {
this.camera = tmp;
this.object.material.color.copy(startColor);
isOnPointAnim = false;
if (!this.cameraFixed)
{
this.setCameraPosition(
this.object.position.x,
this.object.position.y - (this.object.position.y >= this.limits.up ? 0.7 : -0.7),
this.object.position.z + 2
);
}
document.getElementsByTagName('canvas')[0].style.animation = 'fadeOut 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(1)';
}, 200);
}, 4000);
}, 200)
}
pointOpponentAnimation(map, oppponentObject)
{
const tmpCamera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 10000);
const tmp = this.camera;
let interval = null;
const startColor = oppponentObject.material.color.clone();
let hue = 0;
document.getElementsByTagName('canvas')[0].style.animation = 'fadeIn 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(0)';
setTimeout(() => {
document.getElementsByTagName('canvas')[0].style.animation = 'fadeOut 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(1)';
}, 300)
setTimeout(() => {
tmpCamera.position.set(this.limits.left, this.limits.up / 2 + 0.5, map.centerPos.z);
isOnPointAnim = true;
this.camera = tmpCamera;
interval = setInterval(() => {
tmpCamera.lookAt(oppponentObject.position);
console.log(tmpCamera.position)
hue += 0.01;
if (hue > 1)
hue = 0;
oppponentObject.material.color.setHSL(hue, 1, 0.5);
tmpCamera.fov -= 0.05;
tmpCamera.updateProjectionMatrix();
}, 10);
setTimeout(() => {
clearInterval(interval);
document.getElementsByTagName('canvas')[0].style.animation = null;
document.getElementsByTagName('canvas')[0].style.animation = 'fadeIn 0.19s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(0)';
setTimeout(() => {
this.camera = tmp;
oppponentObject.material.color.copy(startColor);
isOnPointAnim = false;
if (!this.cameraFixed)
{
this.setCameraPosition(
this.object.position.x,
this.object.position.y - (this.object.position.y >= this.limits.up ? 0.7 : -0.7),
this.object.position.z + 2
);
}
document.getElementsByTagName('canvas')[0].style.animation = 'fadeOut 0.199s';
document.getElementsByTagName('canvas')[0].style.filter = 'brightness(1)';
}, 200);
}, 4000);
}, 200)
}
update()
{
const currentTime = Date.now();
this.deltaTime = (currentTime - this.previousTime) / 1000;
this.previousTime = currentTime;
let i;
i = 0;
while (i < pressedButton.length)
{
if (pressedButton[i] == 'w' && this.object.position.y < this.limits.up)
{
if (this.interval)
clearInterval(this.interval);
this.interval = setInterval(() => {
this.object.position.y += this.speed / 40;
if (!this.cameraFixed && !isOnPointAnim)
this.camera.position.y += (this.speed / 80);
if (this.object.position.y >= this.limits.up)
{
clearInterval(this.interval);
this.interval = null;
}
}, 5);
}
if (pressedButton[i] == 's' && this.object.position.y > this.limits.down)
{
if (this.interval)
clearInterval(this.interval);
this.interval = setInterval(() => {
this.object.position.y -= this.speed / 40;
if (!this.cameraFixed && !isOnPointAnim)
this.camera.position.y -= (this.speed / 80);
if (this.object.position.y <= this.limits.down)
{
clearInterval(this.interval);
this.interval = null;
this.object.position.y = this.limits.down;
}
}, 5);
}
if (pressedButton[i] == 'd' && this.object.position.x < this.limits.right)
{
this.object.position.x += this.speed * this.deltaTime;
if (!this.cameraFixed && !isOnPointAnim)
this.camera.position.x += this.speed * this.deltaTime;
}
if (pressedButton[i] == 'a' && this.object.position.x > this.limits.left)
{
this.object.position.x -= this.speed * this.deltaTime;
if (!this.cameraFixed && !isOnPointAnim)
this.camera.position.x -= this.speed * this.deltaTime;
}
i++;
}
}
setCameraPosition(x, y, z)
{
this.camera.position.set(x, y, z);
}
};
function addKeyInArr(e)
{
let i;
i = 0;
while (i < pressedButton.length && e.key != pressedButton[i])
i++;
if (i == pressedButton.length)
pressedButton.push(e.key);
}
function remKeyInArr(e)
{
let i;
i = 0;
while (i < pressedButton.length && e.key != pressedButton[i])
i++;
if (i != pressedButton.length)
pressedButton.splice(i, 1);
}
function simplePressKey(e)
{
if (e.key == 'm' && !isOnPointAnim)
{
this.cameraFixed = !this.cameraFixed;
if (!this.cameraFixed)
{
this.setCameraPosition(
this.object.position.x,
this.object.position.y - (this.object.position.y >= this.limits.up ? 0.7 : -0.7),
this.object.position.z + 1.5
);
this.camera.rotation.set(0, 0, 0);
}
else
this.setCameraPosition(0, 1.5, this.object.position.z + 3);
}
}
export { Player, playerExist };

View File

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Video.js :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: edbernar <edbernar@student.42angouleme. +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/26 18:57:00 by hubourge #+# #+# */
/* Updated: 2024/08/27 14:27:27 by edbernar ### ########.fr */
/* */
/* ************************************************************************** */
class Video
{
video = null;
constructor(path)
{
this.video = document.createElement('video');
this.video.src = path;
this.video.muted = true;
this.video.autoplay = true;
this.video.loop = true;
}
}
export { Video };