UNPKG

convex-pixel

Version:

The library for creating pseudo 3d interactive scenes based on webgl

203 lines 7.22 kB
import { TweenMax, Expo, Sine } from "gsap"; import * as PIXI from "pixi.js"; import * as SonarUtils from "../utils/sonar"; import { CameraControllerManager, CameraControllerEventTypes } from "./controller"; import { Vector2D } from "../utils/geom"; const DEFAULT_BOUNDS = new PIXI.Rectangle(0, 0, 640, 480); export class Camera extends PIXI.utils.EventEmitter { constructor(_room, _viewport = DEFAULT_BOUNDS, config) { super(); this._room = _room; this._viewport = _viewport; this._x = 0; this._y = 0; this._cameraPosition = Vector2D.new(); this._pov = Vector2D.new(); this._maxZoom = 1; this._handlerCameraMove = (target) => { const needAnimation = this.normalizeCameraMove(target); if (!needAnimation) { this._handlePivotUpdate(); return; } if (this._tweenPivot) { this._tweenPivot.updateTo({ x: target.x, y: target.y }, true); } else { this._tweenPivot = TweenMax.to(this._cameraPosition, 2, { x: target.x, y: target.y, onUpdate: this._handlePivotUpdate, ease: Sine.easeOut, }); } target.free(); }; this._handlerCameraPOV = (target) => { this.normalizeCameraPOV(target); if (this._tweenPOV) { this._tweenPOV.updateTo({ x: target.x, y: target.y }, true); } else { this._tweenPOV = TweenMax.to(this._pov, 0.5, { x: target.x, y: target.y, onUpdate: this._handlePOVUpdate, ease: Expo.easeOut, }); } target.free(); }; this._handlePivotUpdate = () => { this._x = this._cameraPosition.x; this._y = this._cameraPosition.y; this.emit(CameraControllerEventTypes.MOVE, this._cameraPosition); }; this._handlePOVUpdate = () => { this.emit(CameraControllerEventTypes.POV, this._pov); }; this._handlerCameraZoom = (zoom) => { this.emit(CameraControllerEventTypes.ZOOM, zoom); }; this._handlerCameraRotate = (rotation) => { this.emit(CameraControllerEventTypes.ROTATE, rotation); }; this._povFactor = config.pov || 1; this._dof = (1 / (config.dof || 35)) * 30; this._maxXOffset = config.maxXOffset || 100; this._maxYOffset = config.maxYOffset || 100; this._xOffset = config.xOffset || 10; this._yOffset = config.yOffset || 10; this._float = config.float || false; this.createControllerManager(); this._sonarViewport = new SonarUtils.SonarDetector(this._viewport, ["x", "y", "width", "height"], "change"); this._sonarViewport.addListener("change", () => { // this.emit("change-bound", { ...this._bounds }); }); } get room() { return this._room; } set maxZoom(v) { this._maxZoom = v; this.emit(CameraControllerEventTypes.ZOOM, { maxZoom: this._maxZoom }); // reposition the camera target TweenMax.killTweensOf(this._cameraPosition); this.normalizeCameraMove(this._cameraPosition); this._handlePivotUpdate(); // reset pov factor TweenMax.killTweensOf(this._pov); this.normalizeCameraPOV(this._pov); this._handlePOVUpdate(); } get maxZoom() { return this._maxZoom; } /** * If you change the properties of the Bound then the Sonar will * begin to check it for changes. */ get viewport() { return this._viewport; } get float() { return this._float; } /** * Returns PointOfView */ get pov() { return this._pov; } get dof() { return this._dof; } get controllers() { return this._controllers; } get x() { return this._x; } get y() { return this._y; } get povFactor() { return this._povFactor; } get maxXOffset() { return this._maxXOffset; } get maxYOffset() { return this._maxYOffset; } get xOffset() { return this._xOffset; } get yOffset() { return this._yOffset; } destroy() { if (this._tweenPivot) { this._tweenPivot.kill(); this._tweenPivot = undefined; } this.removeControllerManager(); this._sonarViewport.destroy(); this._cameraPosition.free(); this._pov.free(); } /** * Normalize and modify the target */ normalizeCameraMove(target) { const sceneBounds = this._room.roomBound; const sWidth = sceneBounds.width * this._room.scale.x; const sHeight = sceneBounds.height * this._room.scale.y; const maxX = sWidth - this._viewport.width; const maxY = sHeight - this._viewport.height; if (maxX <= 0) { target.x = maxX * 0.5; } else { if (target.x > maxX) target.x = maxX; else if (target.x < 0) target.x = 0; } if (maxY <= 0) { target.y = maxY * 0.5; } else { if (target.y > maxY) target.y = maxY; else if (target.y < 0) target.y = 0; } return true; } normalizeCameraPOV(target) { /*if (this._maxXOffset && Math.abs(target.x) > this._maxXOffset) { target.x = this._maxXOffset * Math.sign(target.x); } if (this._maxYOffset && Math.abs(target.y) > this._maxYOffset) { target.y = this._maxYOffset * Math.sign(target.y); }*/ } createControllerManager() { this._controllers = new CameraControllerManager(this); this._controllers.addListener(CameraControllerEventTypes.MOVE, this._handlerCameraMove); this._controllers.addListener(CameraControllerEventTypes.POV, this._handlerCameraPOV); this._controllers.addListener(CameraControllerEventTypes.ZOOM, this._handlerCameraZoom); this._controllers.addListener(CameraControllerEventTypes.ROTATE, this._handlerCameraRotate); } removeControllerManager() { if (this._controllers) { this._controllers.removeListener(CameraControllerEventTypes.MOVE, this._handlerCameraMove); this._controllers.removeListener(CameraControllerEventTypes.POV, this._handlerCameraPOV); this._controllers.removeListener(CameraControllerEventTypes.ZOOM, this._handlerCameraZoom); this._controllers.removeListener(CameraControllerEventTypes.ROTATE, this._handlerCameraRotate); this._controllers.destroy(); } } } //# sourceMappingURL=camera.js.map