render-engine.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import * as three from "three-js";
  2. import { actor } from "./actor.js";
  3. class render_engine {
  4. #renderer;
  5. #scene;
  6. #camera;
  7. #canvas;
  8. #actors;
  9. #player;
  10. constructor(canvas, context, player) {
  11. if (!(canvas instanceof HTMLCanvasElement)) {
  12. throw new TypeError("Canvas must be an HTMLCanvasElement.");
  13. }
  14. if (!(context instanceof WebGL2RenderingContext)) {
  15. throw new TypeError("Context must be WebGL2 RenderingContext.");
  16. }
  17. if (!(player instanceof actor)) {
  18. throw new TypeError("Player must be an actor.");
  19. }
  20. this.#actors = {};
  21. this.#player = player;
  22. this.#canvas = canvas;
  23. this.#scene = new three.Scene();
  24. this.#scene.background = new three.Color(0x101010);
  25. this.#camera = new three.PerspectiveCamera(75, 1, 0.1, 1000);
  26. this.#renderer = new three.WebGLRenderer({
  27. canvas: this.#canvas,
  28. context: context
  29. });
  30. this.#renderer.shadowMap.enable = true;
  31. this.#renderer.shadowMap.type = three.BasicShadowMap;
  32. this.#resize_canvas();
  33. this.#update_camera();
  34. window.addEventListener("resize", () => {
  35. this.#resize_canvas();
  36. this.#update_camera();
  37. });
  38. }
  39. #resize_canvas() {
  40. this.#canvas.width = window.innerWidth;
  41. this.#canvas.height = window.innerHeight;
  42. this.#renderer.setSize(this.#canvas.width, this.#canvas.height);
  43. }
  44. #update_camera() {
  45. this.#camera.aspect = this.#canvas.width / this.#canvas.height;
  46. this.#camera.updateProjectionMatrix();
  47. }
  48. run() {
  49. this.#init();
  50. //this.#renderer.setAnimationLoop(() => { this.#render(); });
  51. this.#loop();
  52. }
  53. #loop() {
  54. const start = performance.now();
  55. this.#render();
  56. const stop = performance.now();
  57. const tooked = stop - start;
  58. const new_frame = 1000 / 60 - tooked;
  59. if (new_frame <= 0) {
  60. setTimeout(() => { this.#loop(); }, 1);
  61. return;
  62. }
  63. setTimeout(() => { this.#loop(); }, new_frame);
  64. }
  65. #init() {
  66. const geometry = new three.BoxGeometry(1, 1, 1);
  67. const material = new three.MeshStandardMaterial({ color: 0x009000 });
  68. this.#actors.cube = new three.Mesh(geometry, material);
  69. this.#actors.cube.position.x = 10;
  70. this.#actors.cube.position.y = 0;
  71. this.#actors.cube.position.z = 10;
  72. const light = new three.HemisphereLight(0x707070);
  73. light.position.x = 0;
  74. light.position.y = 10;
  75. light.position.z = 0;
  76. this.#scene.add(this.#actors.cube);
  77. this.#scene.add(light);
  78. this.#camera.position.y = 0;
  79. this.#player.rotate = 270;
  80. }
  81. #sync_camera() {
  82. this.#player.update();
  83. this.#camera.position.x = this.#player.x;
  84. this.#camera.position.z = this.#player.y;
  85. this.#camera.rotation.y
  86. = three.MathUtils.degToRad(this.#player.rotate);
  87. }
  88. #render() {
  89. this.#sync_camera();
  90. this.#actors.cube.rotation.x += 0.01;
  91. this.#actors.cube.rotation.y += 0.01;
  92. this.#renderer.render(this.#scene, this.#camera);
  93. }
  94. }
  95. export { render_engine };