@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
111 lines (91 loc) • 3.32 kB
JavaScript
import { clamp } from "../../../core/math/clamp.js";
import Entity from "../../ecs/Entity.js";
import { decodeMouseEventButtons } from "../../input/devices/mouse/decodeMouseEventButtons.js";
import InputController from "../../input/ecs/components/InputController.js";
import { Camera } from "../ecs/camera/Camera.js";
import TopDownCameraController, { rotate_from_view } from "../ecs/camera/topdown/TopDownCameraController.js";
/**
*
* @param {number} camera_entity
* @param {EntityComponentDataset} ecd
* @param {HTMLElement} dom_element
* @param {number} [sensitivity]
* @return {Entity}
*/
export function makeOrbitalCameraController({
camera_entity,
ecd,
dom_element,
sensitivity = 1
}) {
/**
*
* @returns {TopDownCameraController}
*/
function getCameraController() {
return ecd.getComponent(camera_entity, TopDownCameraController)
}
function getCamera() {
return ecd.getComponent(camera_entity, Camera)
}
/**
*
* @param {Vector2} delta
*/
function orbit(delta) {
const cameraController = getCameraController();
const scale = sensitivity * 2 * Math.PI / dom_element.clientHeight;
rotate_from_view(delta.x * scale, delta.y * scale, cameraController, cameraController);
}
/**
*
* @param {Vector2} delta
*/
function pan(delta) {
const d = delta.clone();
const cameraController = getCameraController();
const camera = getCamera();
TopDownCameraController.pan(d, camera.object, dom_element, cameraController.distance, camera.object.fov, cameraController.target);
}
function zoom(delta) {
const cameraController = getCameraController();
const new_distance = cameraController.distance + delta;
cameraController.distance = clamp(new_distance, cameraController.distanceMin, cameraController.distanceMax);
}
const inputController = new InputController([
{
path: 'pointer/on/tap',
listener(position, event) {
// event.preventDefault();
}
},
{
path: 'pointer/on/down',
listener(position, event) {
// event.preventDefault();
}
},
{
path: 'pointer/on/drag',
listener: function (position, origin, lastDragPosition, event) {
const delta = lastDragPosition.clone().sub(position);
const buttons = decodeMouseEventButtons(event.buttons);
if (buttons[0]) {
pan(delta);
} else {
orbit(delta);
}
event.preventDefault();
}
},
{
path: 'pointer/on/wheel',
listener(delta, event) {
zoom(delta.y);
}
}
]);
const eb = new Entity();
eb.add(inputController);
return eb;
}