diff --git a/index.html b/index.html
index 370b79c..0100fe1 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
-
+
@@ -205,6 +212,8 @@ import uuid from "@/utils/uuid";
import LeavesGameObject from "@/gameobjects/LeavesGameObject";
import FileSaver from "file-saver";
import pkg from "../../package.json";
+import clamp from "@/utils/clamp";
+import * as mousewheel from "@/utils/mousewheel";
interface IMenuItem {
id: string;
@@ -243,6 +252,7 @@ export default class STApp extends Vue {
private oldSavegameVersion: boolean = false;
private errorMessage: string = "";
private pkg = pkg;
+ private hammertime: HammerManager | null = null;
/**
* Called when the component is ready to be used, but has no HTMl elements yet.
@@ -258,9 +268,18 @@ export default class STApp extends Vue {
*/
mounted() {
console.log("Component ready, creating game ...", this);
+ const el = this.$refs.game as HTMLDivElement;
// Create the Phaser game and wait for it to be ready.
- this.game = new Game(this.$refs.game as HTMLDivElement);
+ this.game = new Game(el);
this.game.events.on("ready", this.onGameReady);
+ // Hook up touch events.
+ this.hammertime = new Hammer(el);
+ this.hammertime.get("pinch").set({ enable: true });
+ this.hammertime.get("pan").set({ enable: true });
+ this.hammertime.on("pinchstart", this.onHammerPinch);
+ this.hammertime.on("panstart", this.onHammerPan);
+ mousewheel.addEventHandler(el, this.onMouseWheel);
+ // Add a property to the window oject for debugging purposes.
window.game = this.game;
}
@@ -289,6 +308,9 @@ export default class STApp extends Vue {
scene.tree.on("interact", this.onTreeInteract, this);
scene.background.on("new-background", this.onNewBackground);
this.onNewBackground(scene.background.backgroundImage);
+ // Set camera bounds
+ const camera = scene.cameras.main;
+ camera.setBounds(0, 0, camera.width, camera.height);
// Check cache
const cache = localStorage.getItem("cache");
let willCache = true;
@@ -311,6 +333,66 @@ export default class STApp extends Vue {
}
}
+ /**
+ * Called whenever we pinch.
+ * @param e The event.
+ */
+ onHammerPinch(e: HammerInput) {
+ if (this.hammertime && this.scene) {
+ const camera = this.scene.cameras.main;
+ const oldZoom = camera.zoom;
+ const pinchHandler = (e: HammerInput) => {
+ const change = e.scale;
+ const zoom = clamp(1, 10, oldZoom * e.scale);
+ camera.zoom = zoom;
+ };
+ const pinchEndHandler = (e: HammerInput) => {
+ if (this.hammertime) {
+ this.hammertime.off("pinch", pinchHandler);
+ this.hammertime.off("pinchend", pinchEndHandler);
+ }
+ };
+ this.hammertime.on("pinch", pinchHandler);
+ this.hammertime.on("pinchend", pinchEndHandler);
+ }
+ }
+
+ /**
+ * Called when we pan around.
+ * @param e The event.
+ */
+ onHammerPan(e: HammerInput) {
+ if (this.hammertime && this.scene) {
+ const camera = this.scene.cameras.main;
+ const origX = camera.scrollX;
+ const origY = camera.scrollY;
+ const panHandler = (e: HammerInput) => {
+ camera.scrollX = origX - e.deltaX / camera.zoom;
+ camera.scrollY = origY - e.deltaY / camera.zoom;
+ };
+ const panEndHandler = (e: HammerInput) => {
+ if (this.hammertime) {
+ this.hammertime.off("pan", panHandler);
+ this.hammertime.off("panend", panEndHandler);
+ }
+ };
+ this.hammertime.on("pan", panHandler);
+ this.hammertime.on("panend", panEndHandler);
+ }
+ }
+
+ /**
+ * Called when we scroll with the mouse wheel.
+ */
+ onMouseWheel(scroll: number) {
+ if (this.scene) {
+ const camera = this.scene.cameras.main;
+ const oldScroll = camera.zoom;
+ const zoom = clamp(1, 10, oldScroll + scroll);
+ camera.zoom = zoom;
+ }
+ }
+
/**
* Called whenever a menu item is clicked.
* @param item The menu item.
diff --git a/src/index.ts b/src/index.ts
index 878476d..af73b3f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,6 +4,7 @@ import Vuetify from 'vuetify';
// TODO: Serve as seperate CSS file -> https://vuetifyjs.com/en/getting-started/quick-start (CDN section)
import 'vuetify/dist/vuetify.min.css';
import "./register-serviceworker";
+import "hammerjs";
Vue.use(Vuetify);
diff --git a/src/utils/mousewheel.ts b/src/utils/mousewheel.ts
new file mode 100644
index 0000000..df15f24
--- /dev/null
+++ b/src/utils/mousewheel.ts
@@ -0,0 +1,31 @@
+import clamp from "./clamp";
+
+// https://stackoverflow.com/questions/37019995/how-to-detect-scroll-event-and-direction-in-a-not-scrollable-element-using-javas
+// https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel
+
+// All code in this file is super non standard and different on every browser/OS combination.
+
+const HANDLER_KEY = "__mousewheel_handler__";
+
+type Callback = (scroll: number) => void;
+
+export const addEventHandler = (element: HTMLElement, callback: Callback, options: any = false) => {
+ const handler = (e: any) => {
+ e = window.event || e;
+ const delta = clamp(-1, 1, e.wheelData || -e.detail || e.deltaY);
+ e.preventDefault();
+ callback(delta);
+ return false;
+ }
+ (callback as any)[HANDLER_KEY] = handler;
+ element.addEventListener("mousewheel", handler, options);
+ element.addEventListener("DOMMouseScroll", handler, options);
+}
+
+export const removeEventHandler = (element: HTMLElement, callback: Callback, options: any = false) => {
+ const handler = (callback as any)[HANDLER_KEY];
+ if (handler) {
+ element.removeEventListener("mousewheel", handler, options);
+ element.removeEventListener("DOMMouseScroll", handler, options);
+ }
+}