UNPKG

3js-game-framework

Version:

3js-game-framework is a lightweight and flexible framework designed to streamline the creation of 3D games and interactive applications using Three.js

153 lines 6.48 kB
import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import constants from "../constants"; export class TJSGame { /** * * @param options - TGame Options */ constructor(options = {}) { this.animationLoopEnabled = true; this.setupLights = (lightsOptions) => { if (!(lightsOptions === null || lightsOptions === void 0 ? void 0 : lightsOptions.disableDefaults)) { // Ambient light const ambientLight = new THREE.AmbientLight(0x404040); // soft white light this.scene.add(ambientLight); // Directional light const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(-5, 5, 10); directionalLight.castShadow = true; this.scene.add(directionalLight); } if (Array.isArray(lightsOptions === null || lightsOptions === void 0 ? void 0 : lightsOptions.lights)) { lightsOptions.lights.forEach((light) => this.scene.add(light)); } }; this.gameObjects = new Set(); this.clock = new THREE.Clock(); this.animationLoopEnabled = options.disableAnimationLoop ? false : true; this.SCREEN_WIDTH = Math.floor(window.innerWidth); this.SCREEN_HEIGHT = Math.floor(window.innerHeight); this.gameObjectMap = new Map(); this.setupScene(options.scene); this.setupLights(options.lights); this.setupRenderer(); this.setupCamera(options.camera); this.addResizeListener(); } addResizeListener() { window.addEventListener("resize", () => { this.SCREEN_WIDTH = Math.floor(window.innerWidth); this.SCREEN_HEIGHT = Math.floor(window.innerHeight); //@ts-ignore this.camera.aspect = this.SCREEN_WIDTH / this.SCREEN_HEIGHT; //@ts-ignore this.camera.updateProjectionMatrix(); this.renderer.setSize(this.SCREEN_WIDTH, this.SCREEN_HEIGHT); }); } setupScene(sceneOptions) { this.scene = new THREE.Scene(); this.scene.background = (sceneOptions === null || sceneOptions === void 0 ? void 0 : sceneOptions.background) || constants.scene.background; if (sceneOptions === null || sceneOptions === void 0 ? void 0 : sceneOptions.addAxisHelper) { const axesHelper = new THREE.AxesHelper(50); this.scene.add(axesHelper); } } setupCamera(cameraOptions) { const cameraDefaults = constants.camera; this.camera = new THREE.PerspectiveCamera((cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.fov) || cameraDefaults.fov, this.SCREEN_WIDTH / this.SCREEN_HEIGHT, (cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.near) || cameraDefaults.near, (cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.far) || cameraDefaults.far); // Set camera position const cameraPosition = (cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.position) || cameraDefaults.position; this.camera.position.set(cameraPosition[0], cameraPosition[1], cameraPosition[2]); if (cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.enableOrbitControls) { this.controls = new OrbitControls(this.camera, this.renderer.domElement); this.controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled this.controls.dampingFactor = 0.25; this.controls.screenSpacePanning = false; this.controls.maxPolarAngle = Math.PI / 2; this.controls.update(); } } setupRenderer() { var _a; this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize(this.SCREEN_WIDTH, this.SCREEN_HEIGHT); (_a = document === null || document === void 0 ? void 0 : document.body) === null || _a === void 0 ? void 0 : _a.appendChild(this.renderer.domElement); } /** * Start the game and all game objects */ start() { this.clock.start(); for (let gameObject of this.gameObjects) { gameObject.start(); } if (this.animationLoopEnabled) this.animate(); } /** * Animation loop */ animate() { requestAnimationFrame(this.animate.bind(this)); this.update(this.clock.getDelta()); } /** * Add GameObject to the TSGame * @param gameObject - GameObject to be added to the game */ addGameObject(gameObject) { if (this.clock.running) gameObject.start(); this.gameObjects.add(gameObject); let name = (gameObject === null || gameObject === void 0 ? void 0 : gameObject.name) || gameObject.constructor.name; if (this.gameObjectMap.has(name)) { name = `${name}-${Math.floor(Math.random() * 1000)}`; `GameObject with name ${gameObject.name} already exists. Generated new ${name}.`; } if (name !== gameObject.name) { console.warn(); gameObject.name = name; } this.gameObjectMap.set(name, gameObject); } /** * Remove GameObject from the TSGame * @param gameObject - GameObject to be removed from the game */ removeGameObject(gameObject) { if (this.clock.running) gameObject.end(); this.gameObjects.delete(gameObject); } /** * Get GameObject by name * @param name - Name of the GameObject * @returns GameObject */ getGameObject(name) { return this.gameObjectMap.get(name); } /** * All updates will be done here * @param dt - Delta time since last update */ update(dt) { for (let gameObject of this.gameObjects) { gameObject.update(dt); } if (this.controls) this.controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true this.renderer.render(this.scene, this.camera); } /** * To be invoked when the game ends */ end() { this.gameObjects.forEach((gameObject) => gameObject.end()); this.clock.stop(); } } //# sourceMappingURL=TJSGame.js.map