import nipplejs from "nipplejs"; import styles from "./virtual-gamepad-controls.css"; AFRAME.registerComponent("virtual-gamepad-controls", { schema: {}, init() { // Setup gamepad elements const leftTouchZone = document.createElement("div"); leftTouchZone.classList.add(styles.touchZone, styles.left); document.body.appendChild(leftTouchZone); const rightTouchZone = document.createElement("div"); rightTouchZone.classList.add(styles.touchZone, styles.right); document.body.appendChild(rightTouchZone); const leftStick = nipplejs.create({ zone: leftTouchZone, color: "white", fadeTime: 0 }); const rightStick = nipplejs.create({ zone: rightTouchZone, color: "white", fadeTime: 0 }); this.onMoveJoystickChanged = this.onMoveJoystickChanged.bind(this); this.onMoveJoystickEnd = this.onMoveJoystickEnd.bind(this); this.onLookJoystickChanged = this.onLookJoystickChanged.bind(this); this.onLookJoystickEnd = this.onLookJoystickEnd.bind(this); leftStick.on("move", this.onMoveJoystickChanged); leftStick.on("end", this.onMoveJoystickEnd); rightStick.on("move", this.onLookJoystickChanged); rightStick.on("end", this.onLookJoystickEnd); this.leftTouchZone = leftTouchZone; this.rightTouchZone = rightTouchZone; this.leftStick = leftStick; this.rightStick = rightStick; this.inVr = false; this.moving = false; this.rotating = false; this.moveEvent = { axis: [0, 0] }; this.rotateYEvent = { value: 0 }; this.onEnterVr = this.onEnterVr.bind(this); this.onExitVr = this.onExitVr.bind(this); this.el.sceneEl.addEventListener("enter-vr", this.onEnterVr); this.el.sceneEl.addEventListener("exit-vr", this.onExitVr); }, onMoveJoystickChanged(event, joystick) { const angle = joystick.angle.radian; const force = joystick.force < 1 ? joystick.force : 1; const x = Math.cos(angle) * force; const z = Math.sin(angle) * force; this.moving = true; this.moveEvent.axis[0] = x; this.moveEvent.axis[1] = z; }, onMoveJoystickEnd() { this.moving = false; this.moveEvent.axis[0] = 0; this.moveEvent.axis[1] = 0; this.el.sceneEl.emit("move", this.moveEvent); }, onLookJoystickChanged(event, joystick) { // Set pitch and yaw angles on right stick move const angle = joystick.angle.radian; const force = joystick.force < 1 ? joystick.force : 1; this.rotating = true; this.rotateYEvent.value = Math.cos(angle) * force; }, onLookJoystickEnd() { this.rotating = false; this.rotateYEvent.value = 0; this.el.sceneEl.emit("rotateY", this.rotateYEvent); }, tick() { if (!this.inVr) { if (this.moving) { this.el.sceneEl.emit("move", this.moveEvent); } if (this.rotating) { this.el.sceneEl.emit("rotateY", this.rotateYEvent); } } }, onEnterVr() { // Hide the joystick controls this.inVr = true; this.leftTouchZone.style.display = "none"; this.rightTouchZone.style.display = "none"; }, onExitVr() { // Show the joystick controls this.inVr = false; this.leftTouchZone.style.display = "block"; this.rightTouchZone.style.display = "block"; }, remove() { this.el.sceneEl.removeEventListener("entervr", this.onEnterVr); this.el.sceneEl.removeEventListener("exitvr", this.onExitVr); document.body.removeChild(this.leftTouchZone); document.body.removeChild(this.rightTouchZone); } });