2023-09-19 01:14:15 +02:00
|
|
|
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";
|
2024-12-08 16:53:56 +01:00
|
|
|
import TilorswiftMenuEffectsClickedEvent from "./events/TilorswiftMenuEffectsClickedEvent.js";
|
2023-09-19 01:14:15 +02:00
|
|
|
import TilorswiftEvent from "./events/TilorswiftEvent.js";
|
|
|
|
import BrushMode from "./BrushMode.js";
|
|
|
|
import DialogNewTerrain from "./dialog/DialogNewTerrain.js";
|
|
|
|
import DialogGravity from "./dialog/DialogGravity.js";
|
2024-12-08 16:53:56 +01:00
|
|
|
import DialogEffects from "./dialog/DialogEffects.js";
|
2023-09-19 01:14:15 +02:00
|
|
|
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";
|
2023-09-24 01:48:01 +02:00
|
|
|
import {IntelligentBrushSwitch} from "./menu/IntelligentBrushSwitch.js";
|
2024-12-08 16:53:56 +01:00
|
|
|
import {SnowEffect} from "../../js/effects/SnowEffect.js";
|
|
|
|
import {FullscreenEffectFactory} from "../../js/effects/FullscreenEffectFactory.js";
|
2023-09-19 01:14:15 +02:00
|
|
|
|
2020-02-02 23:00:14 +01:00
|
|
|
export default class Tilorswift
|
|
|
|
{
|
2024-12-08 16:53:56 +01:00
|
|
|
static EFFECT_NAMES = {
|
|
|
|
[SnowEffect.NAME]: 'Schnee',
|
|
|
|
}
|
|
|
|
|
2023-09-19 01:14:15 +02:00
|
|
|
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);
|
2023-09-24 01:48:01 +02:00
|
|
|
this.intelligentBrushSwitch = new IntelligentBrushSwitch(this.tilesetPicker, this.brush);
|
|
|
|
this.widgetBar.addWidget(this.intelligentBrushSwitch);
|
2023-09-19 01:14:15 +02:00
|
|
|
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));
|
2024-12-08 16:53:56 +01:00
|
|
|
menuLevel.addMenuEntry(new MainMenuEntry('Effekte...', TilorswiftMenuEffectsClickedEvent));
|
2023-09-19 01:14:15 +02:00
|
|
|
this.mainbar.addMenuGroup(menuLevel);
|
|
|
|
|
|
|
|
document.body.appendChild(this.mainbar.getElement());
|
|
|
|
|
|
|
|
this.addEventListeners();
|
|
|
|
}
|
|
|
|
|
2023-09-19 11:44:56 +02:00
|
|
|
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,
|
2024-12-08 16:53:56 +01:00
|
|
|
effects: this.level.fullscreenEffects.map((effect) => {return effect.getName()}),
|
2023-09-19 11:44:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return JSON.stringify(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
openLevelFromFile()
|
|
|
|
{
|
|
|
|
const dialog = new LoadLevelDialog();
|
|
|
|
dialog.onLoad = (json) => {
|
2024-12-08 16:53:56 +01:00
|
|
|
console.log(json);
|
2023-09-19 11:44:56 +02:00
|
|
|
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);
|
2023-09-24 01:48:01 +02:00
|
|
|
|
|
|
|
this.initializeIntelligentBrushWidget();
|
2023-09-19 11:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-09-24 01:48:01 +02:00
|
|
|
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);
|
2023-09-27 22:05:06 +02:00
|
|
|
this.level.setGravity(GraphicSet[tilesetIndex].gravity);
|
2023-09-24 01:48:01 +02:00
|
|
|
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)
|
|
|
|
);
|
|
|
|
|
2023-09-24 01:57:26 +02:00
|
|
|
field.setIndex(index);
|
2023-09-24 01:48:01 +02:00
|
|
|
|
2023-09-24 01:57:26 +02:00
|
|
|
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)
|
|
|
|
);
|
2023-09-24 01:48:01 +02:00
|
|
|
|
2023-09-24 01:57:26 +02:00
|
|
|
neighbour.setIndex(neighbourIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
removeTerrain(field)
|
|
|
|
{
|
|
|
|
field.setIndex(-1);
|
2023-09-24 01:48:01 +02:00
|
|
|
|
2023-09-24 01:57:26 +02:00
|
|
|
if (this.brush.isIntelligent) {
|
|
|
|
for (const neighbour of this.level.terrain.getFieldNeighbours(field)) {
|
|
|
|
this.updateNeighbours(field);
|
2023-09-24 01:48:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-19 01:14:15 +02:00
|
|
|
addEventListeners()
|
|
|
|
{
|
|
|
|
window.addEventListener(
|
|
|
|
TilorswiftEvent.FIELD_CLICKED,
|
|
|
|
(event) => {
|
|
|
|
if (this.brush.mode === BrushMode.TERRAIN && !event.getField().isEntrancePoint) {
|
|
|
|
switch (event.button) {
|
|
|
|
case 0:
|
2023-09-24 01:48:01 +02:00
|
|
|
this.addTerrain(event.getField());
|
2023-09-19 01:14:15 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2023-09-24 01:57:26 +02:00
|
|
|
this.removeTerrain(event.getField());
|
2023-09-19 01:14:15 +02:00
|
|
|
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) {
|
2023-09-24 01:48:01 +02:00
|
|
|
this.addTerrain(event.getField());
|
2023-09-19 01:14:15 +02:00
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2024-12-08 16:53:56 +01:00
|
|
|
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',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-09-19 01:14:15 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2024-12-08 16:53:56 +01:00
|
|
|
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)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-09-19 01:14:15 +02:00
|
|
|
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) => {
|
2023-09-24 01:48:01 +02:00
|
|
|
this.createNewTerrain(event.tilesetIndex, event.tilesX, event.tilesY);
|
2023-09-19 01:14:15 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
/* 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,
|
2023-09-19 11:44:56 +02:00
|
|
|
() => {
|
2023-09-19 01:23:18 +02:00
|
|
|
if (this.saveLevelToFile()) {
|
2023-09-19 01:14:15 +02:00
|
|
|
window.dispatchEvent(new TilorswiftSavedEvent());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|