import * as three from "three-js"; import { actor } from "./actor.js"; import { factor } from "./factor.js"; class render_engine { #renderer; #scene; #camera; #canvas; #actors; #player; #looped; constructor(canvas, context, player) { if (!(canvas instanceof HTMLCanvasElement)) { throw new TypeError("Canvas must be an HTMLCanvasElement."); } if (!(context instanceof WebGL2RenderingContext)) { throw new TypeError("Context must be WebGL RenderingContext."); } if (!(player instanceof actor)) { throw new TypeError("Player must be an actor."); } this.#actors = new Array(); this.#player = player; this.#canvas = canvas; this.#scene = new three.Scene(); this.#camera = new three.PerspectiveCamera(75, 1, 0.1, 1000); this.#renderer = new three.WebGLRenderer({ canvas: this.#canvas, context: context }); this.#renderer.shadowMap.enable = true; this.#renderer.shadowMap.type = three.BasicShadowMap; this.#resize_canvas(); this.#update_camera(); window.addEventListener("resize", () => { this.#resize_canvas(); this.#update_camera(); }); } get player() { return this.#player; } get canvas() { return this.#canvas; } set background(target) { if (typeof(target) !== "number") { throw new TypeError("Background must be an number."); } this.#scene.background = target; } get background() { return this.#scene.background; } #resize_canvas() { this.#canvas.width = window.innerWidth; this.#canvas.height = window.innerHeight; this.#renderer.setSize(this.#canvas.width, this.#canvas.height); } #update_camera() { this.#camera.aspect = this.#canvas.width / this.#canvas.height; this.#camera.updateProjectionMatrix(); } run() { this.#looped = true; this.#loop(); } stop() { this.#looped = false; } #loop() { if (!this.#looped) { return; } const start = performance.now(); this.#render(); const stop = performance.now(); const tooked = stop - start; const new_frame = 1000 / 60 - tooked; if (new_frame <= 0) { setTimeout(() => { this.#loop(); }, 1); return; } setTimeout(() => { this.#loop(); }, new_frame); } add_factor(target) { if (!(target instanceof factor)) { throw new TypeError("New factor must be in factor class."); } this.#actors.push(target); this.#scene.add(target.mesh); } #sync_camera() { this.#player.update(); this.#camera.position.x = this.#player.x; this.#camera.position.z = this.#player.y; this.#camera.rotation.y = three.MathUtils.degToRad(this.#player.rotate); } #render() { this.#sync_camera(); this.#actors.forEach(actor => { actor.loop(); }); this.#renderer.render(this.#scene, this.#camera); } } export { render_engine };