import { Element } from "./Element.js"; import { Quality } from "./utils.js"; import { Size } from "./Cone.js"; import { Spade } from "./Spade.js"; export class TypeEntity { static other = 0; static player = 1; static ennemy = 2; } export class Env { constructor() { this.scene = new THREE.Scene(); this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); this.camera.position.z = 7; this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize(window.innerWidth, window.innerHeight); // Change the default quality of the rendered scene this.setQuality(Quality.medium); // Store all elements in the env this.elements = []; // Setup renderer for lights this.renderer.shadowMap.enabled = true; this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Add light source const light = new THREE.DirectionalLight(THREE.Color.NAMES.white); // On top : 1, right : 2 and between player (0) and camera (7) : 4 light.position.set(2, 1, 4); light.castShadow = true; this.scene.add(light); // Clock this.clock = new THREE.Clock(); } /** * Get the Canvas element * @returns domElement */ getDomElement = () => this.renderer.domElement; /** * Get current scene * @returns Scene */ getScene = () => this.scene; /** * Get used camera * @returns Camera */ getCamera = () => this.camera; /** * Get current renderer * @returns Render */ getRenderer = () => this.renderer; /** * Change the quality of the render * @param {Quality} quality * @returns */ setQuality = (quality) => { this.quality = quality; this.renderer.setSize( window.innerWidth / quality, window.innerHeight / quality, false ); }; /** * Add an element to the scene * @param {Element} element Element * @param {TypeEntity} type Type of the element added */ addToScene = (element, type) => { if (!type) { type = TypeEntity.other; } this.elements.push([element, type]); this.scene.add(element.data); }; /** * Animate all the entities in the environnement */ animate = () => { // Retrieve ennemies const ennemies = this.elements .filter((entityData) => entityData[1] == TypeEntity.ennemy) .map((ennemyData) => ennemyData[0]); // Player animation this.elements .filter((entityData) => entityData[1] == TypeEntity.player) .map((playerData) => playerData[0]) .forEach((player) => { if (player.animation) { if ( !player.animation(ennemies.map((object) => object.data)) ) { // If animation returned false, the player died! console.log("player died!"); // TODO: Stop the game // Destroy the player? // End game } } }); // Enemy animation ennemies.forEach((ennemy) => { ennemy.data.position.x -= 0.05; if (ennemy.data.position.x <= -10) { ennemy.data.position.x = ennemy.startPos + Math.random() * 20; } }); }; /** * Render the current scene, using the camera * @returns */ render = () => this.renderer.render(this.scene, this.camera); /** * Update the game logic */ update = () => { this.animate(); this.render(); }; /** * Generate a random map of ennemies * @param {number} numberOfEnnemies */ generateRandomMap = (numberOfEnnemies) => { // Distance before the first ennemy hit the player const startDelta = 5; // Simple Spade for (let index = 1; index < numberOfEnnemies + 1; index++) { const spade = new Spade( Math.random() * 0xffffff, Math.round(Math.random()) ? Size.little : Size.big, startDelta + index + Math.random() * 20 ); this.addToScene(spade, TypeEntity.ennemy); } }; }