import * as three from "three-js"; import { actor } from "./actor.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 WebGLRenderingContext)) { throw new TypeError("Context must be WebGL RenderingContext."); } if (!(player instanceof actor)) { throw new TypeError("Player must be an actor."); } this.#actors = {}; this.#player = player; this.#canvas = canvas; this.#scene = new three.Scene(); this.#scene.background = new three.Color(0x101010); 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(); }); } #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.#init(); 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); } #init() { const geometry = new three.BoxGeometry(1, 1, 1); const material = new three.MeshStandardMaterial({ color: 0x009000 }); this.#actors.cube = new three.Mesh(geometry, material); this.#actors.cube.position.x = 10; this.#actors.cube.position.y = 0; this.#actors.cube.position.z = 10; const light = new three.HemisphereLight(0x707070); light.position.x = 0; light.position.y = 10; light.position.z = 0; this.#scene.add(this.#actors.cube); this.#scene.add(light); this.#camera.position.y = 0; this.#player.rotate = 270; } #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.cube.rotation.x += 0.01; this.#actors.cube.rotation.y += 0.01; this.#renderer.render(this.#scene, this.#camera); } } export { render_engine };