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()); } } ); } }