544 lines
20 KiB
TypeScript
544 lines
20 KiB
TypeScript
import {Level} from "../wordrotator/Level/Level";
|
|
|
|
const helpIcon = require("../../img/help.png").default;
|
|
const view = require("../../html/sites/level.html");
|
|
const coinSound = require("../../sound/single_coin_fall_on_concrete_.mp3").default;
|
|
|
|
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
|
|
import {LevelHelper} from "../wordrotator/Level/LevelHelper";
|
|
import {EndSite} from "./EndSite";
|
|
|
|
import {
|
|
MenuAction,
|
|
Toast,
|
|
ScaleHelper,
|
|
Matomo,
|
|
NativeStoragePromise,
|
|
} from "cordova-sites/dist/client";
|
|
|
|
import {Helper} from "js-helper/dist/shared/Helper";
|
|
import {LevelData} from "../../../shared/model/LevelData";
|
|
import {LevelPlayed} from "../model/LevelPlayed";
|
|
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
|
|
|
|
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
|
|
import {MenuSite} from "cordova-sites/dist/client/js/Context/MenuSite";
|
|
|
|
export class LevelSite extends MenuSite {
|
|
|
|
public static readonly RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 110, 111, 112, 120, 140, 160];
|
|
public static readonly TUTORIAL = {
|
|
FIRST_LEVEL: 67,
|
|
SECOND_LEVEL: 15,
|
|
BIG_SEGMENT_LEVEL: 1921
|
|
};
|
|
|
|
private coinAction: MenuAction;
|
|
private levelCounterAction: MenuAction;
|
|
private levelCounter: number;
|
|
private levelScaler: () => void;
|
|
private wonParams: { aborted: boolean; coinCounterTimer: any };
|
|
private coinPromise: Promise<any>;
|
|
private continueButtonScaler: () => Promise<unknown>;
|
|
private wonTextScaler: () => Promise<unknown>;
|
|
private wonText: HTMLElement;
|
|
private templateContainer: TemplateContainer;
|
|
private coinTemplate: HTMLElement;
|
|
private coinContainer: HTMLElement;
|
|
private level: Level;
|
|
|
|
constructor(siteManager) {
|
|
super(siteManager, view);
|
|
// this.getNavbarFragment().setBackgroundImage(null);
|
|
}
|
|
|
|
async onCreateMenu(navbar) {
|
|
super.onCreateMenu(navbar);
|
|
|
|
let coinAction = new MenuAction(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"), () => {
|
|
}, MenuAction.SHOW_ALWAYS, 900);
|
|
coinAction._shouldTranslate = false;
|
|
coinAction.setLiClass("coin-counter img");
|
|
navbar.addAction(coinAction);
|
|
this.coinAction = coinAction;
|
|
|
|
let levelCounterAction = new MenuAction(Helper.nonNull(this.levelCounter, "1"), () => {
|
|
}, MenuAction.SHOW_ALWAYS, 900);
|
|
levelCounterAction._shouldTranslate = false;
|
|
levelCounterAction.setLiClass("level-counter");
|
|
navbar.addAction(levelCounterAction);
|
|
this.levelCounterAction = levelCounterAction;
|
|
|
|
let helpAction = new MenuAction("", () => {
|
|
this.help();
|
|
}, MenuAction.SHOW_ALWAYS, 900);
|
|
helpAction._shouldTranslate = false;
|
|
helpAction._icon = helpIcon;
|
|
helpAction.setLiClass("help-action show-while-playing");
|
|
navbar.addAction(helpAction);
|
|
|
|
return navbar;
|
|
}
|
|
|
|
async onConstruct(args) {
|
|
this.levelCounter = Helper.nonNull(await NativeStoragePromise.getItem("levelCounter"), 1);
|
|
// this.levelCounter = 9999;
|
|
this.levelScaler = () => {
|
|
};
|
|
this.wonParams = {
|
|
aborted: false,
|
|
coinCounterTimer: null,
|
|
};
|
|
this.coinPromise = Promise.resolve();
|
|
|
|
let soundManager = SoundManager.getInstance();
|
|
soundManager.set({
|
|
audio: coinSound,
|
|
muted: ((await NativeStoragePromise.getItem("play-sound", "1")) !== "1"),
|
|
volume: 0.7
|
|
}, SoundManager.CHANNELS.SOUND);
|
|
|
|
soundManager.resume(SoundManager.CHANNELS.MUSIC);
|
|
|
|
return super.onConstruct(args);
|
|
}
|
|
|
|
async onViewLoaded() {
|
|
let res = super.onViewLoaded();
|
|
let leafSegmentTemplate = this.findBy("#segment-leaf-template");
|
|
let parentSegmentTemplate = this.findBy("#segment-parent-template");
|
|
let rowSegmentTemplate = this.findBy("#segment-row-template");
|
|
let triangleTemplate = this.findBy("#segment-triangle-template");
|
|
let columnTemplate = this.findBy("#segment-column-template");
|
|
|
|
leafSegmentTemplate.removeAttribute("id");
|
|
parentSegmentTemplate.removeAttribute("id");
|
|
rowSegmentTemplate.removeAttribute("id");
|
|
triangleTemplate.removeAttribute("id");
|
|
columnTemplate.removeAttribute("id");
|
|
|
|
leafSegmentTemplate.remove();
|
|
parentSegmentTemplate.remove();
|
|
rowSegmentTemplate.remove();
|
|
triangleTemplate.remove();
|
|
columnTemplate.remove();
|
|
|
|
let continueButton = this.findBy("#continue-button");
|
|
continueButton.addEventListener("click", () => {
|
|
continueButton.style.opacity = 0;
|
|
this.nextLevel();
|
|
});
|
|
|
|
let wonText = this.findBy("#won-text");
|
|
|
|
let scaleHelper = new ScaleHelper();
|
|
this.continueButtonScaler = await scaleHelper.scaleToFull(continueButton, continueButton.parentElement, false, true, 2);
|
|
this.wonTextScaler = await scaleHelper.scaleToFull(wonText, wonText.parentElement, false, false, 2, null, 5);
|
|
this.wonText = wonText;
|
|
this.wonText.style.fontSize = "0";
|
|
|
|
this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate, columnTemplate);
|
|
|
|
this.coinTemplate = this.findBy("#coin-template");
|
|
this.coinContainer = this.findBy("#coin-container");
|
|
|
|
this.coinTemplate.id = null;
|
|
ViewHelper.removeAllChildren(this.coinContainer);
|
|
|
|
// this.findBy("#help-button").addEventListener("click", () => {
|
|
// this.help();
|
|
// });
|
|
await this.loadLastLevel();
|
|
|
|
return res;
|
|
}
|
|
|
|
async loadLastLevel() {
|
|
try {
|
|
let currentLevelInfo = await NativeStoragePromise.getItem("currentLevel");
|
|
if (Helper.isNotNull(currentLevelInfo)) {
|
|
currentLevelInfo = JSON.parse(currentLevelInfo);
|
|
|
|
let levelData = await LevelData.findById(currentLevelInfo["id"]);
|
|
|
|
if (Helper.isNull(levelData)) {
|
|
return this.nextLevel();
|
|
}
|
|
|
|
let level = LevelHelper.inflateLevel(levelData, this.templateContainer);
|
|
level.setStartRotations(currentLevelInfo["rotations"]);
|
|
|
|
level.getWonPromise().then(() => {
|
|
this.levelWon(level);
|
|
});
|
|
|
|
level.createSegments();
|
|
level.setLocks(currentLevelInfo["locks"]);
|
|
level.getRootSegment()._updateElement();
|
|
|
|
level.saveAsCurrentLevel();
|
|
|
|
let levelSegment = this.findBy("#level");
|
|
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
|
|
let scaleHelper = new ScaleHelper();
|
|
this.levelScaler = await scaleHelper.scaleTo(1, levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
|
|
|
|
this.level = level;
|
|
Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]);
|
|
this.level.checkHasWon();
|
|
return;
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
return this.nextLevel();
|
|
}
|
|
|
|
startEndSite() {
|
|
this.startSite(EndSite);
|
|
this.finish();
|
|
}
|
|
|
|
updateLevelCounter() {
|
|
this.levelCounterAction.setName(this.levelCounter);
|
|
if (this.levelCounter >= 10 && this.levelCounter <= 99) {
|
|
this.levelCounterAction.setLiClass("num-10 level-counter");
|
|
} else if (this.levelCounter >= 100 && this.levelCounter <= 999) {
|
|
this.levelCounterAction.setLiClass("num-100 level-counter");
|
|
} else if (this.levelCounter >= 1000) {
|
|
this.levelCounterAction.setLiClass("num-1000 level-counter");
|
|
} else {
|
|
this.levelCounterAction.setLiClass("level-counter");
|
|
}
|
|
}
|
|
|
|
async nextLevel() {
|
|
this.showLoadingSymbol();
|
|
try {
|
|
let levelData = await LevelPlayed.getNextLevelData(LevelSite.RENDERER_TYPES);
|
|
|
|
if (Helper.isNull(levelData)) {
|
|
this.startEndSite();
|
|
return;
|
|
}
|
|
|
|
const level = LevelHelper.inflateLevel(levelData, this.templateContainer);
|
|
|
|
//Waiting for Level to be done
|
|
if (this.level && level.id === this.level.id) {
|
|
console.log("Level is the same as before! reload!");
|
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
// return;
|
|
debugger;
|
|
return this.nextLevel();
|
|
}
|
|
|
|
level.getWonPromise().then(async () => {
|
|
await this.levelWon(level);
|
|
});
|
|
|
|
level.createSegments();
|
|
level.getRootSegment()._updateElement();
|
|
|
|
level.saveAsCurrentLevel();
|
|
|
|
let levelSegment = this.findBy("#level");
|
|
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
|
|
|
|
this._view.classList.remove('won');
|
|
this.wonText.style.fontSize = "0";
|
|
this.removeLoadingSymbol();
|
|
|
|
let scaleHelper = new ScaleHelper();
|
|
this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
|
|
|
|
this.level = level;
|
|
this.updateLevelCounter();
|
|
|
|
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
|
|
// this.coinAction.redraw();
|
|
|
|
this.wonParams.aborted = true;
|
|
clearTimeout(this.wonParams.coinCounterTimer);
|
|
|
|
Matomo.push(["trackEvent", "LevelSite", "NextLevel", "Level Number Normal", this.levelCounter]);
|
|
|
|
this.level.checkHasWon();
|
|
|
|
return this.tutorial();
|
|
} catch (e) {
|
|
console.log("Fehler!");
|
|
console.error(e);
|
|
this.startEndSite();
|
|
}
|
|
}
|
|
|
|
async onStart(args) {
|
|
this.setTitle("WR");
|
|
|
|
Matomo.update("Level Sites");
|
|
let res = super.onStart(args);
|
|
|
|
if (this.levelCounterAction) {
|
|
this.updateLevelCounter();
|
|
}
|
|
this.levelScaler();
|
|
|
|
//TODO Sound
|
|
let soundManager = SoundManager.getInstance();
|
|
soundManager.set({
|
|
audio: coinSound,
|
|
muted: (await NativeStoragePromise.getItem("play-sound", "1") !== "1"),
|
|
volume: 0.7
|
|
}, SoundManager.CHANNELS.SOUND);
|
|
|
|
await this.tutorial();
|
|
|
|
return res;
|
|
}
|
|
|
|
async levelWon(level) {
|
|
try {
|
|
const savePromise = LevelPlayed.setPlayed(level.getLevelData());
|
|
|
|
// savePromise.then((r) => console.log("levelSaved!", r));
|
|
|
|
this.levelCounter++;
|
|
await NativeStoragePromise.setItem("levelCounter", this.levelCounter);
|
|
await NativeStoragePromise.remove("currentLevel");
|
|
|
|
let continueButton = this.findBy("#continue-button");
|
|
continueButton.style.transition = "none";
|
|
continueButton.style.opacity = 0;
|
|
|
|
//Todo richtiges Element aufrufen?
|
|
this._view.classList.add('won');
|
|
ViewHelper.removeAllChildren(this.coinContainer);
|
|
let coinsPerLevel = await NativeStoragePromise.getItem("coinsPerLevel", 5);
|
|
|
|
let coinsBefore = 0;
|
|
|
|
let soundManager = SoundManager.getInstance();
|
|
let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND);
|
|
|
|
this.coinPromise = this.coinPromise.then(async () => {
|
|
coinsBefore = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
|
|
await NativeStoragePromise.setItem("coins", coinsBefore + parseInt(coinsPerLevel));
|
|
}).then(async () => {
|
|
return Promise.all([new Promise<void>((r) => {
|
|
setTimeout(() => {
|
|
//TODO animationen einbauen
|
|
continueButton.style.opacity = 1;
|
|
r();
|
|
}, 500)
|
|
}),
|
|
audioOptions.loadedPromise.catch(e => {
|
|
console.error(e)
|
|
})
|
|
]);
|
|
});
|
|
|
|
this.wonParams.aborted = false;
|
|
|
|
for (let i = 0; i < coinsPerLevel; i++) {
|
|
let coinElem = <HTMLElement>this.coinTemplate.cloneNode(true);
|
|
this.coinContainer.appendChild(coinElem);
|
|
this.coinPromise = this.coinPromise.then(() => {
|
|
return new Promise<void>(r => {
|
|
let timeout = 350;
|
|
if (!this.wonParams.aborted) {
|
|
//TODO animationen einbauen
|
|
|
|
coinElem.style.opacity = "1";
|
|
soundManager.play(SoundManager.CHANNELS.SOUND);
|
|
|
|
this.wonParams.coinCounterTimer = setTimeout(() => {
|
|
if (!this.wonParams.aborted) {
|
|
this.coinAction.setName(++coinsBefore);
|
|
}
|
|
}, timeout / 2);
|
|
} else {
|
|
r();
|
|
}
|
|
|
|
//Always do the next promise for garbage collection
|
|
setTimeout(r, timeout);
|
|
})
|
|
});
|
|
}
|
|
|
|
this.coinPromise = this.coinPromise.catch((e) => {
|
|
console.error(e)
|
|
});
|
|
|
|
this.wonTextScaler();
|
|
this.continueButtonScaler();
|
|
this.levelScaler();
|
|
|
|
Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"))]);
|
|
|
|
let leafs = level.getLeafSegments();
|
|
leafs.forEach((leaf, i) => {
|
|
let elem = leaf.getElement();
|
|
elem.style.animationDelay = i * 50 + "ms";
|
|
elem.classList.add("jump-animation");
|
|
})
|
|
|
|
await savePromise;
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
async help() {
|
|
let cost = await NativeStoragePromise.getItem("costForHelp", 25);
|
|
let currentCoins = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), 0));
|
|
|
|
if (currentCoins >= cost) {
|
|
currentCoins -= cost;
|
|
await NativeStoragePromise.setItem("coins", currentCoins);
|
|
this.coinAction.setName(currentCoins);
|
|
|
|
let rotatables = this.level.getRotatableSegments();
|
|
rotatables = rotatables.filter((segment) => {
|
|
return (!segment.isSolved(false));
|
|
});
|
|
|
|
let index = Math.floor(Math.random() * rotatables.length);
|
|
|
|
let segmentToHelp = rotatables[index];
|
|
while (segmentToHelp.rotation !== 0) {
|
|
segmentToHelp.rotate();
|
|
}
|
|
segmentToHelp.setIsRotatable(false);
|
|
this.level.saveAsCurrentLevel();
|
|
|
|
// Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
|
|
} else {
|
|
new Toast("not-enough-coins").show();
|
|
// Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
|
|
}
|
|
}
|
|
|
|
async tutorial() {
|
|
const tutorialScale = 0.01;
|
|
|
|
if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) {
|
|
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "1");
|
|
|
|
let scaleHelper = new ScaleHelper();
|
|
this._view.classList.add("tutorial");
|
|
this._view.classList.add("step-" + currentStep);
|
|
|
|
switch (currentStep) {
|
|
case "1": {
|
|
this.level.setSegmentClickedListener(async () => {
|
|
this._view.classList.remove("step-1");
|
|
await NativeStoragePromise.setItem("tutorial-step", "2");
|
|
this.tutorial();
|
|
});
|
|
|
|
// let textElem = this.findBy(".tutorial-text .step-1");
|
|
|
|
await this.levelScaler();
|
|
// scaleHelper.scaleTo(tutorialScale, textElem, textElem.parentElement, null, true, 2, 2);
|
|
|
|
break;
|
|
}
|
|
case "2": {
|
|
this.level.setSegmentClickedListener(() => {
|
|
});
|
|
this.level.getWonPromise().then(async () => {
|
|
this._view.classList.remove("tutorial");
|
|
this._view.classList.remove("step-2");
|
|
await NativeStoragePromise.remove("tutorial-step");
|
|
this.coinPromise = this.coinPromise.then(async () => {
|
|
new Toast("extra-coins-after-first-level").show();
|
|
await NativeStoragePromise.setItem("coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0")) + 50);
|
|
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
|
|
// this.coinAction.redraw();
|
|
});
|
|
});
|
|
|
|
// let textElem = this.findBy(".tutorial-text .step-2");
|
|
|
|
await this.levelScaler();
|
|
// scaleHelper.scaleTo(tutorialScale, textElem, textElem.parentElement, null, true, 1, 2);
|
|
|
|
break;
|
|
}
|
|
default: {
|
|
this._view.classList.remove("tutorial");
|
|
}
|
|
}
|
|
} else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) {
|
|
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "3");
|
|
|
|
switch (currentStep) {
|
|
case "3": {
|
|
let scaleHelper = new ScaleHelper();
|
|
|
|
this._view.classList.add("tutorial");
|
|
this._view.classList.add("step-" + currentStep);
|
|
|
|
let eventListener = async () => {
|
|
this._view.classList.remove("tutorial");
|
|
this._view.classList.remove("step-3");
|
|
await NativeStoragePromise.setItem("tutorial-step", "4");
|
|
// this.findBy("#help-button").removeEventListener("click", eventListener);
|
|
this.levelScaler();
|
|
};
|
|
this.findBy(".help-action").addEventListener("click", eventListener);
|
|
|
|
// let textElem = this.findBy(".tutorial-text .step-3");
|
|
|
|
await this.levelScaler();
|
|
// scaleHelper.scaleTo(tutorialScale, textElem, textElem.parentElement, null, true, 1, 2);
|
|
break;
|
|
}
|
|
default: {
|
|
this._view.classList.remove("tutorial");
|
|
}
|
|
}
|
|
} else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) {
|
|
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "4");
|
|
|
|
switch (currentStep) {
|
|
case "4": {
|
|
|
|
let scaleHelper = new ScaleHelper();
|
|
this._view.classList.add("tutorial");
|
|
this._view.classList.add("step-" + currentStep);
|
|
|
|
let rotatableSegments = this.level.getRotatableSegments();
|
|
let firstSegment = rotatableSegments[2];
|
|
|
|
let pointer = this.findBy("#tutorial-pointer");
|
|
pointer.remove();
|
|
firstSegment.element.appendChild(pointer);
|
|
|
|
this.level.setSegmentClickedListener(async (segment) => {
|
|
if (firstSegment === segment) {
|
|
this._view.classList.remove("tutorial");
|
|
this._view.classList.remove("step-4");
|
|
await NativeStoragePromise.setItem("tutorial-step", "5");
|
|
this.levelScaler();
|
|
}
|
|
});
|
|
|
|
// let textElem = this.findBy(".tutorial-text .step-4");
|
|
|
|
await this.levelScaler();
|
|
// debugger;
|
|
// scaleHelper.scaleTo(tutorialScale, textElem, textElem.parentElement, null, true, 1, 2);
|
|
|
|
break;
|
|
}
|
|
default: {
|
|
this._view.classList.remove("tutorial");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|