Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ The UI is written in Vue.js and the application itself in Phaser 3. We use TypeS
Feel free to shoot issues and PRs at us. Just keep in mind that this was designed as a fun little side project without serious production usage in mind.

New commits to master are automatically deployed to tree.sahnee.de. However, due to highly aggressive caching(Cloudflare, Service Worker & GitHub Pages) it may take a while for the changes to be visible on your machine.

Please make all Pull Requests against the `develop` branch only. We will merge `develop` into `master` once it is time for a new release.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="UTF-8">
<title>slow-tree</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta http-equiv="cleartype" content="on">
Expand Down
546 changes: 275 additions & 271 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "slow-tree",
"version": "1.0.1",
"version": "1.1.0",
"description": "",
"main": "index.js",
"scripts": {
Expand All @@ -22,29 +22,31 @@
"author": "Patrick Sachs & Jakob Heubl",
"license": "",
"dependencies": {
"clean-webpack-plugin": "^2.0.0",
"file-saver": "^2.0.1",
"hammerjs": "^2.0.8",
"phaser": "^3.16.2",
"phaser3-nineslice": "git+https://github.com/PatrickSachs/phaser3-nineslice.git#types",
"vue": "^2.6.6",
"phaser3-nineslice": "^0.5.0",
"vue": "^2.6.9",
"vue-class-component": "^6.3.2",
"vue-property-decorator": "^7.3.0",
"vuetify": "^1.5.1"
"vuetify": "^1.5.6"
},
"devDependencies": {
"@types/file-saver": "^2.0.0",
"@types/workbox-sw": "^3.2.0",
"@types/hammerjs": "^2.0.36",
"@types/workbox-sw": "^3.2.1",
"browser-sync": "^2.26.3",
"browser-sync-webpack-plugin": "^2.2.2",
"clean-webpack-plugin": "^2.0.1",
"copy-webpack-plugin": "^5.0.1",
"css-loader": "^2.1.0",
"css-loader": "^2.1.1",
"dotenv": "^6.2.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"typescript": "^3.2.4",
"vue-loader": "^15.6.2",
"vue-template-compiler": "^2.6.6",
"webpack": "^4.29.4",
"typescript": "^3.3.3333",
"vue-loader": "^15.7.0",
"vue-template-compiler": "^2.6.9",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.1",
"workbox-webpack-plugin": "^4.1.0"
}
Expand Down
86 changes: 84 additions & 2 deletions src/components/App.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<template>
<div id="app">
<v-app dark>
<v-navigation-drawer app v-model="drawer" :mini-variant.sync="mini" hide-overlay stateless>
<v-navigation-drawer
app
v-model="drawer"
:mini-variant.sync="mini"
touchless
hide-overlay
stateless
>
<v-toolbar flat class="transparent">
<v-list class="pa-0">
<v-list-tile avatar>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
31 changes: 31 additions & 0 deletions src/utils/mousewheel.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}