mr-crocs-adventures/tilorswift/js/Tilorswift.js

412 lines
14 KiB
JavaScript

import {LoadLevelDialog} from "../../js/ui/LoadLevelDialog.js";
import GraphicSet from "../../js/GraphicSet.js";
import Setting from "../../js/Setting.js";
import Brush from "./Brush.js";
import Tileset from "./Tileset.js";
import WidgetBar from "./menu/WidgetBar.js";
import TilesetPickerWidget from "./menu/TilesetPickerWidget.js";
import EntrancePointWidget from "./menu/EntrancePointWidget.js";
import TargetPointWidget from "./menu/TargetPointWidget.js";
import Mouse from "./Mouse.js";
import MainMenu from "./menu/MainMenu.js";
import MenuGroup from "./menu/MenuGroup.js";
import MainMenuEntry from "./menu/MainMenuEntry.js";
import TilorswiftMenuNewTerrainClickedEvent from "./events/TilorswiftMenuNewTerrainClickedEvent.js";
import {TilorswiftMenuOpenCLickedEvent} from "./events/TilorswiftMenuOpenCLickedEvent.js";
import TilorswiftMenuSaveClickedEvent from "./events/TilorswiftMenuSaveClickedEvent.js";
import TilorswiftAddRowsClickedEvent from "./events/TilorswiftAddRowsClickedEvent.js";
import TilorswiftAddColumnsClickedEvent from "./events/TilorswiftAddColumnsClickedEvent.js";
import TilorswiftMenuGravityClickedEvent from "./events/TilorswiftMenuGravityClickedEvent.js";
import TilorswiftMenuEffectsClickedEvent from "./events/TilorswiftMenuEffectsClickedEvent.js";
import TilorswiftEvent from "./events/TilorswiftEvent.js";
import BrushMode from "./BrushMode.js";
import DialogNewTerrain from "./dialog/DialogNewTerrain.js";
import DialogGravity from "./dialog/DialogGravity.js";
import DialogEffects from "./dialog/DialogEffects.js";
import DialogAddRows from "./dialog/DialogAddRows.js";
import DialogAddColumns from "./dialog/DialogAddColumns.js";
import Terrain from "./Terrain.js";
import TilorswiftSavedEvent from "./events/TilorswiftSavedEvent.js";
import Level from "../../js/Level.js";
import {IntelligentBrushSwitch} from "./menu/IntelligentBrushSwitch.js";
import {SnowEffect} from "../../js/effects/SnowEffect.js";
import {FullscreenEffectFactory} from "../../js/effects/FullscreenEffectFactory.js";
export default class Tilorswift
{
static EFFECT_NAMES = {
[SnowEffect.NAME]: 'Schnee',
}
constructor(level) {
this.level = level;
this.map = document.getElementById('map');
this.brush = new Brush();
this.tileset = new Tileset(this.level.terrain.tileset.setId);
this.widgetBar = new WidgetBar('widget-bar');
this.tilesetPicker = new TilesetPickerWidget(this.tileset, this.brush);
this.widgetBar.addWidget(this.tilesetPicker);
this.intelligentBrushSwitch = new IntelligentBrushSwitch(this.tilesetPicker, this.brush);
this.widgetBar.addWidget(this.intelligentBrushSwitch);
this.entrancePicker = new EntrancePointWidget(this.widgetBar, this.brush);
this.widgetBar.addWidget(this.entrancePicker);
this.targetPicker = new TargetPointWidget(this.widgetBar, this.brush);
this.widgetBar.addWidget(this.targetPicker);
this.mouse = new Mouse();
this.mainbar = new MainMenu('mainbar');
}
init()
{
document.body.appendChild(this.widgetBar.getElement());
const menuFile = new MenuGroup('Datei');
menuFile.addMenuEntry(new MainMenuEntry('Neu...', TilorswiftMenuNewTerrainClickedEvent));
menuFile.addMenuEntry(new MainMenuEntry('Öffnen...', TilorswiftMenuOpenCLickedEvent));
menuFile.addMenuEntry(new MainMenuEntry('Speichern...', TilorswiftMenuSaveClickedEvent));
this.mainbar.addMenuGroup(menuFile);
const menuEdit = new MenuGroup('Bearbeiten');
menuEdit.addMenuEntry(new MainMenuEntry('Zeilen einfügen...', TilorswiftAddRowsClickedEvent));
menuEdit.addMenuEntry(new MainMenuEntry('Spalten einfügen...', TilorswiftAddColumnsClickedEvent));
this.mainbar.addMenuGroup(menuEdit);
const menuLevel = new MenuGroup('Level');
menuLevel.addMenuEntry(new MainMenuEntry('Gravitation...', TilorswiftMenuGravityClickedEvent));
menuLevel.addMenuEntry(new MainMenuEntry('Effekte...', TilorswiftMenuEffectsClickedEvent));
this.mainbar.addMenuGroup(menuLevel);
document.body.appendChild(this.mainbar.getElement());
this.addEventListeners();
}
getLevelAsJson()
{
let matrix = [];
for (let y = 0; y < this.level.terrain.fields.length; y++) {
let row = [];
for (let x = 0; x < this.level.terrain.fields[y].length; x++) {
row.push(this.level.terrain.fields[y][x].index);
}
matrix.push(row);
}
let data = {
tileset: this.level.getTilesetId(),
rows: this.level.getRows(),
columns: this.level.getColumns(),
startX: this.level.getStartX(),
startY: this.level.getStartY(),
targetX: this.level.getTargetX(),
targetY: this.level.getTargetY(),
gravity: this.level.gravity,
matrix: matrix,
effects: this.level.fullscreenEffects.map((effect) => {return effect.getName()}),
};
return JSON.stringify(data);
}
openLevelFromFile()
{
const dialog = new LoadLevelDialog();
dialog.onLoad = (json) => {
console.log(json);
this.tileset = new Tileset(JSON.parse(json).tileset);
this.level = Level.createFromJson(json);
this.loadLevel();
dialog.close();
}
dialog.openFileBrowser();
}
loadLevel()
{
this.tileset = new Tileset(this.level.terrain.tileset.setId);
document.body.style.backgroundColor = this.level.getBackgroundColor();
if (GraphicSet[this.level.terrain.tileset.setId].backgroundImage !== null) {
document.body.style.backgroundImage = 'url("../' + Setting.GRAPHICS_LOCATION + GraphicSet[this.level.terrain.tileset.setId].backgroundImage + '")';
} else {
document.body.style.backgroundImage = 'none';
}
this.map.innerHTML = '';
this.map.appendChild(this.level.terrain.getElement());
this.tilesetPicker.reloadTileset(this.tileset);
this.initializeIntelligentBrushWidget();
}
saveLevelToFile()
{
if (!this.level.hasEntrancePoint()) {
alert('Es muss ein Startpunkt definiert sein!');
return false;
}
if (!this.level.hasTargetPoint()) {
alert('Es muss ein Zielpunkt definiert sein!');
return false;
}
const filename = prompt('Dateiname', 'terrain.json');
if (filename === null) {
return false;
}
const json = this.getLevelAsJson(level);
const download = document.createElement('a');
download.setAttribute('download', filename);
download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json));
download.click();
download.remove();
return true;
}
initializeIntelligentBrushWidget()
{
if (this.tileset.hasExtendedTiles()) {
this.intelligentBrushSwitch.enable();
this.intelligentBrushSwitch.switchOn();
} else {
this.intelligentBrushSwitch.switchOff();
this.intelligentBrushSwitch.disable();
}
}
createNewTerrain(tilesetIndex, tilesX, tilesY)
{
this.tileset = new Tileset(tilesetIndex);
this.level.terrain = new Terrain(this.tileset, tilesX, tilesY, GraphicSet[tilesetIndex].backgroundColor);
this.level.setGravity(GraphicSet[tilesetIndex].gravity);
document.body.style.backgroundColor = this.level.getBackgroundColor();
if (GraphicSet[tilesetIndex].backgroundImage !== null) {
document.body.style.backgroundImage = 'url("../' + Setting.GRAPHICS_LOCATION + GraphicSet[tilesetIndex].backgroundImage + '")';
} else {
document.body.style.backgroundImage = 'none';
}
this.map.innerHTML = '';
this.map.appendChild(this.level.terrain.getElement());
this.tilesetPicker.reloadTileset(this.tileset);
this.initializeIntelligentBrushWidget();
}
addTerrain(field)
{
if (this.brush.isIntelligent) {
const index = this.level.terrain.brushTileIndex + this.tileset.primaryTiles * this.tileset.getTileIndexFactor(
this.level.terrain.getFieldNeighbourCode(field)
);
field.setIndex(index);
this.updateNeighbours(field);
} else {
field.setIndex(this.level.terrain.brushTileIndex);
}
}
updateNeighbours(field)
{
for (const neighbour of this.level.terrain.getFieldNeighbours(field)) {
if (neighbour.index === -1) {
continue;
}
const neighbourIndex = (neighbour.index % this.tileset.primaryTiles) + this.tileset.primaryTiles * this.tileset.getTileIndexFactor(
this.level.terrain.getFieldNeighbourCode(neighbour)
);
neighbour.setIndex(neighbourIndex);
}
}
removeTerrain(field)
{
field.setIndex(-1);
if (this.brush.isIntelligent) {
for (const neighbour of this.level.terrain.getFieldNeighbours(field)) {
this.updateNeighbours(field);
}
}
}
addEventListeners()
{
window.addEventListener(
TilorswiftEvent.FIELD_CLICKED,
(event) => {
if (this.brush.mode === BrushMode.TERRAIN && !event.getField().isEntrancePoint) {
switch (event.button) {
case 0:
this.addTerrain(event.getField());
break;
case 2:
this.removeTerrain(event.getField());
break;
}
} else if (this.brush.mode === BrushMode.ENTRANCE) {
if (event.getField().index === -1) {
const coordinates = this.level.terrain.getFieldCoordinates(event.getField());
this.level.terrain.setEntrancePoint(coordinates.x, coordinates.y);
this.brush.mode = BrushMode.TERRAIN;
this.widgetBar.enableWidgets();
}
} else if (this.brush.mode === BrushMode.EXIT) {
if (event.getField().index === -1) {
const coordinates = this.level.terrain.getFieldCoordinates(event.getField());
this.level.terrain.setTargetPoint(coordinates.x, coordinates.y);
this.brush.mode = BrushMode.TERRAIN;
this.widgetBar.enableWidgets();
}
}
}
);
window.addEventListener(
'contextmenu',
(event) => {
event.preventDefault();
}
);
window.addEventListener(
TilorswiftEvent.FIELD_ENTERED,
(event) => {
if (this.mouse.isPressedLeft) {
this.addTerrain(event.getField());
} else if (this.mouse.isPressedRight) {
event.getField().setIndex(-1);
}
}
);
window.addEventListener(
TilorswiftEvent.NEW_TERRAIN_CLICKED,
() => {
new DialogNewTerrain();
}
);
window.addEventListener(
TilorswiftEvent.MENU_GRAVITY_CLICKED,
() => {
new DialogGravity(this.level.gravity);
}
);
window.addEventListener(
TilorswiftEvent.MENU_EFFECTS_CLICKED,
() => {
const effects = [];
for (const effect of this.level.fullscreenEffects) {
effects.push(effect.getName());
}
new DialogEffects(
FullscreenEffectFactory.getNames(),
effects,
{
[SnowEffect.NAME]: 'Schnee',
}
);
}
);
window.addEventListener(
TilorswiftEvent.ADD_ROWS_CLICKED,
() => {
new DialogAddRows();
}
);
window.addEventListener(
TilorswiftEvent.ADD_COLUMNS_CLICKED,
() => {
new DialogAddColumns();
}
);
window.addEventListener(
TilorswiftEvent.GRAVITY_UPDATED,
(event) => {
this.level.gravity = event.gravity;
}
);
window.addEventListener(
TilorswiftEvent.EFFECTS_UPDATED,
(event) => {
this.level.fullscreenEffects = [];
const effectFactory = new FullscreenEffectFactory();
for (const effectName of event.effectNames) {
this.level.fullscreenEffects.push(
effectFactory.getEffect(effectName)
);
}
}
);
window.addEventListener(
TilorswiftEvent.ADD_ROWS,
(event) => {
this.level.terrain.addRows(event.beforeRow, event.rowCount);
}
);
window.addEventListener(
TilorswiftEvent.ADD_COLUMNS,
(event) => {
this.level.terrain.addColumns(event.beforeColumn, event.columnCount);
}
);
window.addEventListener(
TilorswiftEvent.NEW_TERRAIN,
(event) => {
this.createNewTerrain(event.tilesetIndex, event.tilesX, event.tilesY);
}
);
/* Prevents Firefox's annoying default drag and drop behavior for images */
document.addEventListener(
'dragstart',
(event) => {
event.preventDefault();
}
);
window.addEventListener(
TilorswiftEvent.MENU_OPEN_CLICKED,
() => {
this.openLevelFromFile();
}
);
window.addEventListener(
TilorswiftEvent.MENU_SAVE_CLICKED,
() => {
if (this.saveLevelToFile()) {
window.dispatchEvent(new TilorswiftSavedEvent());
}
}
);
}
}