Compare commits

..

5 Commits

Author SHA1 Message Date
Mal
83c1ae8119 Level added 2022-05-16 17:18:06 +02:00
Mal
e476e689e1 Mouse cursor is visible again 2021-09-21 11:19:05 +02:00
Mal
2fe9b63c70 Double frame rate 2021-09-21 09:48:54 +02:00
Mal
598dbc67ac Optimization for Firefox and Chrome 2021-09-21 09:47:27 +02:00
Mal
46c584d9ee Static frame rate established 2021-09-15 17:24:53 +02:00
75 changed files with 668 additions and 16785 deletions

View File

@ -10,14 +10,7 @@
"name": "Moon",
"tileset": "moon.jpg",
"tiles": 2,
"backgroundColor": "#000000",
"backgroundImage": "background_earth.jpg"
},
{
"name": "Io",
"tileset": "io.jpg",
"tiles": 3,
"backgroundColor": "#000000",
"backgroundImage": "background_jupiter.jpg"
"backgroundColor": "black",
"backgroundImage": null
}
]
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

View File

@ -13,12 +13,10 @@
position: absolute;
top: 0;
left: 0;
cursor: none;
}
</style>
<link rel="shortcut icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="tilorswift/style.css">
<script type="module" src="js/module.js" defer></script>
<script type="module" src="js/module.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>

View File

@ -4,8 +4,7 @@ export default class FileLoader
{
this.filename = filename;
this.content = '';
this.onLoad = () => {};
this.loadContent();
}
getContent()
@ -20,11 +19,10 @@ export default class FileLoader
request.onreadystatechange = () => {
if (request.status === 200 && request.readyState === 4) {
this.content = request.responseText;
this.onLoad(this.content);
}
};
request.open('GET', this.filename, false);
request.send();
}
}
}

84
js/FrameRateMeasurer.js Normal file
View File

@ -0,0 +1,84 @@
import FrameRateMeasuredEvent from "./events/FrameRateMeasuredEvent.js";
export default class FrameRateMeasurer
{
constructor(rounds = 30)
{
this.rounds = rounds;
this.round = 0;
this.lastTimestamp = undefined;
this.frameDurations = [];
window.requestAnimationFrame(
(timestamp) => {
this.measureFrameRate(timestamp);
}
);
}
measureFrameRate(timestamp)
{
if (this.lastTimestamp !== undefined) {
this.round++;
this.frameDurations.push(timestamp - this.lastTimestamp);
this.lastTimestamp = timestamp;
if (this.round < this.rounds) {
window.requestAnimationFrame(
(timestamp) => {
this.measureFrameRate(timestamp);
}
);
} else {
window.dispatchEvent(new FrameRateMeasuredEvent(this.getAverageFrameRate()));
}
} else {
this.round = 0;
this.lastTimestamp = timestamp;
window.requestAnimationFrame(
(timestamp) => {
this.measureFrameRate(timestamp);
}
);
}
this.lastTimestamp = timestamp
}
getAverageFrameRate()
{
let frameDurationSum = 0;
this.frameDurations.forEach(
(duration) => {
frameDurationSum += duration;
}
);
let durationAverage = frameDurationSum / this.frameDurations.length;
return 1000 / durationAverage;
}
getFrameRate()
{
const DEFAULT_FRAME_RATES = [30, 60, 120];
let averageFrameRate = this.getAverageFrameRate();
let closestDistance = {frameRate: 0, distance: 99999};
DEFAULT_FRAME_RATES.forEach(
(frameRate) => {
let distance = Math.abs(frameRate - averageFrameRate);
if (closestDistance.distance > distance) {
closestDistance.frameRate = frameRate;
closestDistance.distance = distance;
}
}
);
return closestDistance.frameRate;
}
}

View File

@ -1,252 +0,0 @@
import MrCroc from "./MrCroc.js";
import Gisela from "./Gisela.js";
import RetroArchitecture from "./retro/RetroArchitecture.js";
import Camera from "./Camera.js";
import TextMessageMrCroc from "./ui/TextMessageMrCroc.js";
import TextMessageGisela from "./ui/TextMessageGisela.js";
import UserInterface from "./ui/UserInterface.js";
import Key from "./Key.js";
import Setting from "./Setting.js";
import {EventBus} from "./events/EventBus.js";
export class Game
{
static GAME_SPEED = 1
constructor(level) {
this.level = level;
this.fps = 60;
this.frameDuration = 1000.0 / this.fps;
this.lastRendered = undefined;
this.lastTimestamp = undefined;
this.canvas = document.getElementById('canvas');
this.context = this.canvas.getContext('2d');
this.mrCroc = new MrCroc();
this.gisela = new Gisela();
this.architecture = RetroArchitecture.createFromData(this.level);
const cameraPosition = this.architecture.getStartPosition();
this.camera = new Camera(cameraPosition.x, cameraPosition.y);
this.gameFinished = false;
this.hasPlayerLeftArchitecture = false;
this.textBoxGameStart = new TextMessageMrCroc('Mr. Croc: "Where is Gisela? I have to find her!"', this.context);
this.textBoxGameFinished = new TextMessageGisela(
'Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."',
this.context
);
this.userInterface = new UserInterface();
this.isPaused = true;
this.KeyLeft = new Key('ArrowLeft');
this.KeyRight = new Key('ArrowRight');
this.KeyJump = new Key('Space');
this.KeyLoad = new Key('KeyL');
}
render(timestamp)
{
if (timestamp - this.lastRendered < this.frameDuration) {
return;
}
/*
if (this.gisela.currentAnimation !== 'SLEEP_LEFT' && this.mrCroc.position.x < this.gisela.position.x) {
this.gisela.currentAnimation = 'SLEEP_LEFT';
} else if (this.gisela.currentAnimation !== 'SLEEP_RIGHT' && this.mrCroc.position.x >= this.gisela.position.x) {
this.gisela.currentAnimation = 'SLEEP_RIGHT';
}
*/
if (!this.gameFinished) {
if (this.mrCroc.position.x < this.gisela.position.x) {
this.gisela.playAnimation('SLEEP_LEFT', timestamp);
} else {
this.gisela.playAnimation('SLEEP_RIGHT', timestamp);
}
}
this.context.clearRect(0, 0, window.innerWidth, window.innerHeight);
this.architecture.draw(this.context, this.camera);
this.mrCroc.draw(this.context, this.camera);
this.gisela.draw(this.context, this.camera);
for (const effect of this.level.fullscreenEffects) {
effect.update(timestamp);
effect.render(this.context, this.camera);
}
this.userInterface.draw(this.context);
this.lastRendered = timestamp;
}
canBeFinished()
{
return (
!this.gameFinished &&
this.mrCroc.isJumping === false &&
this.architecture.isMovableInsideTargetPosition(this.mrCroc)
);
}
handlePhysics(delta, timestamp)
{
const ceilingHeight = Math.max(
this.architecture.getCeilingHeight(this.mrCroc.getPositionHeadLeft()),
this.architecture.getCeilingHeight(this.mrCroc.getPositionHeadRight()),
);
const groundHeight = Math.min(
this.architecture.getGroundHeight(this.mrCroc.getPositionFootLeft()),
this.architecture.getGroundHeight(this.mrCroc.getPositionFootRight())
);
/* Handle falling */
this.mrCroc.position.y += this.mrCroc.fallSpeed * delta * 0.6;
this.mrCroc.fallSpeed += this.level.gravity * delta;
/* Handle ground collision */
if (this.mrCroc.position.y > groundHeight && this.mrCroc.fallSpeed > 0) {
this.mrCroc.position.y = groundHeight;
this.mrCroc.fallSpeed = 0;
}
/* Handle ceiling collision */
if (this.mrCroc.position.y - this.mrCroc.getHeight() <= ceilingHeight) {
this.mrCroc.fallSpeed = 0;
this.mrCroc.position.y = ceilingHeight + this.mrCroc.getHeight() + 1;
}
this.handlePlayerMovement(delta, timestamp, groundHeight);
}
updateCamera()
{
this.camera.focusPosition(
this.mrCroc.position.x - this.mrCroc.getWidth() * 0.5,
this.mrCroc.position.y - this.mrCroc.getHeight() * 0.5,
20
);
this.camera.lockCameraIntoBorders();
}
handlePlayerMovement(delta, timestamp, groundHeight)
{
/* Jumping */
if (!this.mrCroc.isJumping && this.mrCroc.fallSpeed === 0 && this.mrCroc.position.y === groundHeight && this.KeyJump.isPressed()) {
this.mrCroc.jump();
} else if (!this.KeyJump.isPressed()) {
this.mrCroc.isJumping = false;
}
/* Movement left and right */
if (!this.hasPlayerLeftArchitecture && this.KeyLeft.isPressed()) {
const lastWallLeft = Math.min(
this.architecture.getWallLeft(this.mrCroc.getPositionHeadLeft()),
this.architecture.getWallLeft(this.mrCroc.getPositionFootLeft())
);
this.mrCroc.moveLeft(timestamp, delta);
if (this.mrCroc.position.x <= lastWallLeft + this.mrCroc.getWidth() * 0.5) {
this.mrCroc.position.x = lastWallLeft + this.mrCroc.getWidth() * 0.5 + 1;
}
} else if (!this.hasPlayerLeftArchitecture && this.KeyRight.isPressed()) {
const lastWallRight = Math.max(
this.architecture.getWallRight(this.mrCroc.getPositionHeadRight()),
this.architecture.getWallRight(this.mrCroc.getPositionFootRight())
);
this.mrCroc.moveRight(timestamp, delta);
if (this.mrCroc.position.x >= lastWallRight - this.mrCroc.getWidth() * 0.5) {
this.mrCroc.position.x = lastWallRight - this.mrCroc.getWidth() * 0.5 - 1;
}
}
if (!this.hasPlayerLeftArchitecture && !this.architecture.isInsideArchitecture(this.mrCroc.position)) {
this.hasPlayerLeftArchitecture = true;
setTimeout(
() => {
this.architecture.setMovableToStartPosition(this.mrCroc);
this.hasPlayerLeftArchitecture = false;
}, 2000
);
}
}
finish()
{
if (this.mrCroc.position.x < this.gisela.position.x) {
this.gisela.currentAnimation = 'LOOK_LEFT';
} else {
this.gisela.currentAnimation = 'LOOK_RIGHT';
}
this.gameFinished = true;
this.KeyLeft.pressed = false;
this.KeyRight.pressed = false;
this.KeyJump.pressed = false;
this.lastTimestamp = undefined;
this.lastRendered = undefined;
this.textBoxGameFinished.updateLines(window.innerWidth - 40, this.context);
this.textBoxGameFinished.animate(75);
this.userInterface.addTextBox(this.textBoxGameFinished);
}
init(loopFunction) {
if (this.isChromeBrowser()) {
this.canvas.width = window.innerWidth - 1;
this.canvas.height = window.innerHeight - 1;
}
this.canvas.style.backgroundAttachment = 'fixed';
this.canvas.style.backgroundSize = 'cover';
this.canvas.style.backgroundPosition = 'center center';
if (this.level.getBackgroundImage() !== undefined) {
this.canvas.style.backgroundImage = "url("+ Setting.GRAPHICS_LOCATION + this.level.getBackgroundImage() + ")";
} else {
this.canvas.style.backgroundImage = 'none';
}
this.canvas.style.backgroundColor = this.level.getBackgroundColor();
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
EventBus.addEventListener(
'resize',
function () {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
);
this.textBoxGameStart.animate(75, 1000);
this.textBoxGameStart.show(1000);
this.textBoxGameStart.hide(10000);
this.userInterface.addTextBox(this.textBoxGameStart);
this.camera.borderRight = this.architecture.columns * this.architecture.tileWidth;
this.camera.borderBottom = this.architecture.rows * this.architecture.tileHeight;
this.architecture.setMovableToStartPosition(this.mrCroc);
this.architecture.setMovableToTargetPosition(this.gisela);
this.isPaused = false;
for (const effect of this.level.fullscreenEffects) {
effect.init();
}
window.requestAnimationFrame(loopFunction);
}
isChromeBrowser()
{
return navigator.userAgent.match('Chrome') !== null;
}
}

View File

@ -15,13 +15,5 @@ export default class Gisela extends Movable
'LOOK_RIGHT',
new RetroAnimation(Setting.GRAPHICS_LOCATION + 'gisela-right.png', 1, SCALE, 0.01)
);
this.addAnimation(
'SLEEP_LEFT',
new RetroAnimation(Setting.GRAPHICS_LOCATION + 'giesela-left-sleeping.png', 4, SCALE, 6)
);
this.addAnimation(
'SLEEP_RIGHT',
new RetroAnimation(Setting.GRAPHICS_LOCATION + 'giesela-right-sleeping.png', 4, SCALE, 6)
);
}
}
}

View File

@ -5,10 +5,7 @@ let GraphicSet = [
tiles: 8,
scale: 3,
backgroundColor: '#6096ff',
backgroundImage: null,
tilePreview: 5,
primaryTiles: 8,
gravity: 9.806,
backgroundImage: null
},
{
name: 'Moon',
@ -16,55 +13,8 @@ let GraphicSet = [
tiles: 2,
scale: 3,
backgroundColor: 'black',
backgroundImage: 'background_earth.jpg',
tilePreview: 1,
primaryTiles: 2,
gravity: 2.4515,
},
{
name: 'Death Star',
tileset: 'deathstar.png',
tiles: 96,
scale: 1,
backgroundColor: '#171721',
backgroundImage: null,
tilePreview: 3,
primaryTiles: 6,
gravity: 9.806,
},
{
name: 'Nature 2.0',
tileset: 'nature.png',
tiles: 48,
scale: 3,
backgroundColor: '#6096ff',
backgroundImage: null,
tilePreview: 46,
primaryTiles: 3,
gravity: 9.806,
},
{
name: 'Io',
tileset: 'io.png',
tiles: 96,
scale: 1,
backgroundColor: '#000000',
backgroundImage: 'background_jupiter.jpg',
tilePreview: 2,
primaryTiles: 6,
gravity: 1.796,
},
{
name: 'Southpole',
tileset: 'southpole.png',
tiles: 112,
scale: 1,
backgroundColor: '#00000',
backgroundImage: 'background-southpole.jpg',
tilePreview: 2,
primaryTiles: 7,
gravity: 9.806,
},
backgroundImage: 'background_earth.jpg'
}
];
export default GraphicSet;
export default GraphicSet;

View File

@ -3,25 +3,15 @@ export default class ImageLoader
images = [];
numberImagesLoaded = 0;
constructor() {
this.onLoad = () => {}
}
update()
{
this.numberImagesLoaded++;
if (this.numberImagesLoaded === this.images.length) {
window.dispatchEvent(new Event('imagesloaded'));
this.onLoad();
}
}
isComplete()
{
return this.numberImagesLoaded === this.images.length;
}
getCurrentProgress()
{
return this.numberImagesLoaded / this.images.length;
@ -29,19 +19,14 @@ export default class ImageLoader
addImage(imagePath)
{
this.images.push(imagePath);
}
let image = new Image();
image.src = imagePath;
image.addEventListener(
'load', () => {
this.update();
}
);
load()
{
for (const imagePath of this.images) {
let image = new Image();
image.src = imagePath;
image.addEventListener(
'load', () => {
this.update();
}
);
}
this.images.push(image);
}
}

View File

@ -1,12 +1,11 @@
import {EventBus} from "./events/EventBus.js";
export default class Key
{
constructor(name)
{
this.name = name;
this.pressed = false;
EventBus.addEventListener(
window.addEventListener(
'keydown',
(event) => {
if (event.code === this.name) {
@ -14,7 +13,8 @@ export default class Key
}
}
);
EventBus.addEventListener(
window.addEventListener(
'keyup',
(event) => {
if (event.code === this.name) {

View File

@ -1,15 +1,11 @@
import FileLoader from "./FileLoader.js";
import Terrain from "../tilorswift/js/Terrain.js";
import {FullscreenEffectFactory} from "./effects/FullscreenEffectFactory.js";
export default class Level
{
static FACTOR_GRAVITY = 4.903;
constructor(terrain)
{
this.terrain = terrain;
this.fullscreenEffects = [];
this.gravity = 2.0;
}
@ -78,47 +74,14 @@ export default class Level
this.gravity = gravity;
}
static createFromFile(filename, callback = () => {})
static createFromFile(filename)
{
let loader = new FileLoader(filename);
loader.onLoad = (data) => {
const json = JSON.parse(data);
const level = new Level(Terrain.createFromJson(json));
level.setGravity(json.gravity / Level.FACTOR_GRAVITY);
if (json.hasOwnProperty('effects')) {
const effectFactory = new FullscreenEffectFactory();
for (const effect of json.effects) {
level.fullscreenEffects.push(
effectFactory.getEffect(effect)
);
}
}
callback(level);
}
loader.loadContent();
}
static createFromJson(json)
{
const data = JSON.parse(json);
const terrain = Terrain.createFromJson(data);
const level = new Level(terrain);
level.setGravity(data.gravity / Level.FACTOR_GRAVITY);
if (data.hasOwnProperty('effects')) {
const effectFactory = new FullscreenEffectFactory();
for (const effect of data.effects) {
level.fullscreenEffects.push(
effectFactory.getEffect(effect)
);
}
}
let levelData = JSON.parse(loader.getContent());
let terrain = Terrain.createFromJson(levelData);
let level = new Level(terrain);
level.setGravity(levelData.gravity);
return level;
}
}
}

View File

@ -6,15 +6,10 @@ export default class MrCroc extends Movable
{
constructor() {
const SCALE = 2;
const month = new Date().getMonth();
const animationRight = month === 11 ? 'mr-croc-walk-right-christmas.png' : 'mr-croc-walk-right.png';
const animationLeft = month === 11 ? 'mr-croc-walk-left-christmas.png' : 'mr-croc-walk-left.png';
super(new RetroAnimation(Setting.GRAPHICS_LOCATION + animationRight, 2, SCALE), 7);
super(new RetroAnimation(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png', 2, SCALE), 7);
this.isJumping = false;
this.addAnimation('WALK_RIGHT', new RetroAnimation(Setting.GRAPHICS_LOCATION + animationRight, 2, SCALE, 10));
this.addAnimation('WALK_LEFT', new RetroAnimation(Setting.GRAPHICS_LOCATION + animationLeft, 2, SCALE, 10));
this.addAnimation('WALK_RIGHT', new RetroAnimation(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png', 2, SCALE, 10));
this.addAnimation('WALK_LEFT', new RetroAnimation(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png', 2, SCALE, 10));
}
moveRight(timestamp, delta = 1)
@ -28,4 +23,4 @@ export default class MrCroc extends Movable
this.playAnimation('WALK_LEFT', timestamp);
super.moveLeft(delta);
}
}
}

View File

@ -44,15 +44,15 @@ export default class UrlParam
getInt(name)
{
const value = parseInt(this.get(name));
let value = parseInt(this.get(name));
return isNaN(value) ? 0 : value;
return isNaN(value) ? undefined : value;
}
getFloat(name)
{
const value = parseFloat(this.get(name));
let value = parseFloat(this.get(name));
return isNaN(value) ? 0.0 : value;
return isNaN(value) ? undefined : value;
}
}
}

View File

@ -1,26 +0,0 @@
export class FullscreenEffect
{
static NAME = '';
constructor(canvas)
{
this.canvas = canvas;
}
init()
{
}
update(timestamp)
{
}
render(context, camera)
{
}
getName()
{
return this.constructor.NAME;
}
}

View File

@ -1,30 +0,0 @@
import {SnowEffect} from "./SnowEffect.js";
import {RainEffect} from "./RainEffect.js";
import {ThunderstormEffect} from "./ThunderstormEffect.js";
export class FullscreenEffectFactory
{
static EFFECTS = {
[SnowEffect.NAME]: SnowEffect,
[RainEffect.NAME]: RainEffect,
[ThunderstormEffect.NAME]: ThunderstormEffect,
}
getEffect(name)
{
return new FullscreenEffectFactory.EFFECTS[name]();
}
static getNames()
{
const names = [];
for (const name in FullscreenEffectFactory.EFFECTS) {
names.push(name);
}
console.log(names);
return names;
}
}

View File

@ -1,51 +0,0 @@
import {FullscreenEffect} from "./FullscreenEffect.js";
export class RainEffect extends FullscreenEffect
{
static NAME = 'rain';
constructor()
{
super();
this.image = new Image();
this.image.src = 'js/effects/rain.png';
this.sound = new Audio('js/effects/rain.mp3');
this.sound.loop = true;
this.offset = 0;
this.speed = 1.3;
}
init()
{
super.init();
this.sound.play();
}
update(timestamp)
{
super.update(timestamp);
this.offsetX = (timestamp * 0.65 * this.speed) % this.image.width;
this.offsetY = (timestamp * 1.5 * this.speed) % this.image.height;
}
render(context, camera)
{
super.render(context, camera);
const cameraX = -1 * (camera.position.x % this.image.width);
const cameraY = -1 * (camera.position.y % this.image.height);
for (let y = -1; y < Math.ceil(context.canvas.height / this.image.height) + 1; y++) {
for (let x = -1; x < Math.ceil(context.canvas.width / this.image.width) + 1; x++) {
context.drawImage(
this.image,
cameraX + this.offsetX + this.image.width * x,
cameraY + this.offsetY + this.image.height * y,
);
}
}
}
}

View File

@ -1,51 +0,0 @@
import {FullscreenEffect} from "./FullscreenEffect.js";
export class SnowEffect extends FullscreenEffect
{
static NAME = 'snow';
constructor()
{
super();
this.audio = new Audio('js/effects/storm.mp3');
this.audio.loop = true;
this.image = new Image();
this.image.src = 'js/effects/snow.png';
this.offset = 0;
this.speed = 1.0;
}
init()
{
super.init();
this.audio.play();
}
update(timestamp)
{
super.update(timestamp);
this.offsetX = (timestamp * 0.65 * this.speed) % this.image.width;
this.offsetY = (timestamp * 1.5 * this.speed) % this.image.height;
}
render(context, camera)
{
super.render(context);
const cameraX = -1 * (camera.position.x % this.image.width);
const cameraY = -1 * (camera.position.y % this.image.height);
for (let y = -1; y < Math.ceil(context.canvas.height / this.image.height) + 1; y++) {
for (let x = -1; x < Math.ceil(context.canvas.width / this.image.width) + 1; x++) {
context.drawImage(
this.image,
cameraX + this.offsetX + this.image.width * x,
cameraY + this.offsetY + this.image.height * y,
);
}
}
}
}

View File

@ -1,88 +0,0 @@
import {FullscreenEffect} from "./FullscreenEffect.js";
export class ThunderstormEffect extends FullscreenEffect
{
static NAME = 'thunderstorm';
constructor()
{
super();
this.currentAlpha = 0.0;
this.nextFlash = undefined;
this.duration = 150;
this.sounds = [
new Audio('js/effects/thunder01.mp3'),
new Audio('js/effects/thunder02.mp3'),
new Audio('js/effects/thunder03.mp3'),
new Audio('js/effects/thunder04.mp3'),
];
this.currentSound = 0;
}
shuffleSounds(iterations = 10)
{
const buffer = this.sounds.slice(0, this.sounds.length - 1);
for (let i = 0; i < iterations; i++) {
buffer.sort(
(a, b) => {
return 1 - Math.round(Math.random()) * 2
}
);
}
const index = 1 + Math.round(Math.random() * (buffer.length - 1));
this.sounds = buffer.slice(0, index)
.concat([this.sounds[this.sounds.length - 1]])
.concat(buffer.slice(index));
}
update(timestamp)
{
super.update(timestamp);
if (this.nextFlash > timestamp) {
this.currentAlpha = 0.0;
return;
}
if (timestamp < this.nextFlash + this.duration) {
const progress = (timestamp - this.nextFlash) / this.duration;
this.currentAlpha = Math.sin(Math.PI * progress) * 0.75;
} else {
const duration = 3000 + Math.round(Math.random() * 27000);
this.nextFlash = timestamp + duration;
setTimeout(
() => {
if (this.currentSound === 0) {
this.shuffleSounds();
}
this.sounds[this.currentSound].currentTime = 0;
this.sounds[this.currentSound].play();
this.currentSound = (this.currentSound + 1) % this.sounds.length;
},
duration + 1000
);
}
}
render(context, camera)
{
super.render(context, camera);
if (this.currentAlpha === 0.0) {
return;
}
context.fillStyle = 'rgba(255, 255, 255, ' + this.currentAlpha + ')';
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,25 +0,0 @@
export class EventBus
{
static listeners = []
static addEventListener(eventName, callback)
{
EventBus.listeners.push({eventName, callback});
window.addEventListener(eventName, callback, false);
}
static dispatchEvent(event)
{
window.dispatchEvent(event);
}
static clear()
{
for (const listener of EventBus.listeners) {
window.removeEventListener(listener.eventName, listener.callback, false);
}
EventBus.listeners = [];
}
}

View File

@ -0,0 +1,9 @@
import InterfaceEvent from "./InterfaceEvent.js";
export default class FrameRateMeasuredEvent extends Event
{
constructor(frameRate) {
super(InterfaceEvent.FRAME_RATE_MEASURED);
this.frameRate = frameRate;
}
}

View File

@ -1,91 +1,147 @@
'use strict';
import Key from "./Key.js";
import MrCroc from "./MrCroc.js";
import RetroArchitecture from "./retro/RetroArchitecture.js";
import Camera from "./Camera.js";
import Gisela from "./Gisela.js";
import Setting from "./Setting.js";
import FrameRateMeasurer from "./FrameRateMeasurer.js";
import GraphicSet from "./GraphicSet.js";
import ImageLoader from "./ImageLoader.js";
import Level from "./Level.js";
import InterfaceEvent from "./events/InterfaceEvent.js";
import UrlParam from "./UrlParam.js";
import {LoadLevelDialog} from "./ui/LoadLevelDialog.js";
import {EventBus} from "./events/EventBus.js";
import {Game} from "./Game.js";
import UserInterface from "./ui/UserInterface.js";
import TextMessageGisela from "./ui/TextMessageGisela.js";
import TextMessageMrCroc from "./ui/TextMessageMrCroc.js";
function mainLoop(timestamp)
function MainLoop(timestamp)
{
if (game.isPaused) {
return;
if (lastRendered === undefined && lastTimestamp === undefined) {
lastRendered = timestamp;
lastTimestamp = timestamp;
}
if (game.lastRendered === undefined && game.lastTimestamp === undefined) {
game.lastRendered = timestamp;
game.lastTimestamp = timestamp;
}
let delta = (timestamp - lastTimestamp) / (10 / GAME_SPEED);
let delta = (timestamp - game.lastTimestamp) / (10 / Game.GAME_SPEED);
game.handlePhysics(delta, timestamp);
game.updateCamera();
game.render(timestamp);
game.lastTimestamp = timestamp;
if (game.canBeFinished()) {
game.finish();
}
if (game.KeyLoad.isPressed()) {
const dialog = new LoadLevelDialog();
dialog.onClose = () => {
dialog.close();
game.isPaused = false;
window.requestAnimationFrame(mainLoop);
}
dialog.onLoad = (data) => {
EventBus.clear();
for (const effect of game.level.fullscreenEffects) {
effect.destroy();
}
loadLevel(Level.createFromJson(data));
}
game.isPaused = true;
}
window.requestAnimationFrame(mainLoop);
}
function loadLevel(level)
{
const loader = new ImageLoader();
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right-christmas.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left-christmas.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-left.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-left.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'giesela-left-sleeping.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'giesela-right-sleeping.png');
for (const graphicSet of GraphicSet) {
loader.addImage(Setting.TILESET_LOCATION + graphicSet.tileset);
if (graphicSet.backgroundImage !== null) {
loader.addImage(Setting.GRAPHICS_LOCATION + graphicSet.backgroundImage);
}
}
loader.load();
EventBus.addEventListener(
'imagesloaded',
() => {
game = new Game(level);
game.init(mainLoop);
}
let ceilingHeight = Math.max(
architecture.getCeilingHeight(mrCroc.getPositionHeadLeft()),
architecture.getCeilingHeight(mrCroc.getPositionHeadRight()),
);
let groundHeight = Math.min(
architecture.getGroundHeight(mrCroc.getPositionFootLeft()),
architecture.getGroundHeight(mrCroc.getPositionFootRight())
);
/* Handle falling */
mrCroc.position.y += mrCroc.fallSpeed;
mrCroc.fallSpeed += GRAVITY * delta;
/* Handle ground collision */
if (mrCroc.position.y > groundHeight && mrCroc.fallSpeed > 0) {
mrCroc.position.y = groundHeight;
mrCroc.fallSpeed = 0;
}
/* Handle ceiling collision */
if (mrCroc.position.y - mrCroc.getHeight() <= ceilingHeight) {
mrCroc.fallSpeed = 0;
mrCroc.position.y = ceilingHeight + mrCroc.getHeight() + 1;
}
/* Handle jumping */
if (!mrCroc.isJumping && mrCroc.fallSpeed === 0 && mrCroc.position.y === groundHeight && KeyJump.isPressed()) {
mrCroc.jump();
} else if (!KeyJump.isPressed()) {
mrCroc.isJumping = false;
}
/* Movement left and right */
if (!hasPlayerLeftArchitecture && KeyLeft.isPressed()) {
let lastWallLeft = Math.min(
architecture.getWallLeft(mrCroc.getPositionHeadLeft()),
architecture.getWallLeft(mrCroc.getPositionFootLeft())
);
mrCroc.moveLeft(timestamp, delta);
if (mrCroc.position.x <= lastWallLeft + mrCroc.getWidth() * 0.5) {
mrCroc.position.x = lastWallLeft + mrCroc.getWidth() * 0.5 + 1;
}
} else if (!hasPlayerLeftArchitecture && KeyRight.isPressed()) {
let lastWallRight = Math.max(
architecture.getWallRight(mrCroc.getPositionHeadRight()),
architecture.getWallRight(mrCroc.getPositionFootRight())
);
mrCroc.moveRight(timestamp, delta);
if (mrCroc.position.x >= lastWallRight - mrCroc.getWidth() * 0.5) {
mrCroc.position.x = lastWallRight - mrCroc.getWidth() * 0.5 - 1;
}
}
if (!hasPlayerLeftArchitecture && !architecture.isInsideArchitecture(mrCroc.position)) {
hasPlayerLeftArchitecture = true;
setTimeout(
function () {
architecture.setMovableToStartPosition(mrCroc);
hasPlayerLeftArchitecture = false;
}, 2000
);
}
camera.focusPosition(
mrCroc.position.x - mrCroc.getWidth() * 0.5,
mrCroc.position.y - mrCroc.getHeight() * 0.5,
20
);
camera.lockCameraIntoBorders();
/* Drawing */
if (timestamp - lastRendered >= frameDuration) {
lastRendered = timestamp;
if (gisela.currentAnimation !== 'LOOK_LEFT' && mrCroc.position.x < gisela.position.x) {
gisela.currentAnimation = 'LOOK_LEFT';
} else if (gisela.currentAnimation !== 'LOOK_RIGHT' && mrCroc.position.x >= gisela.position.x) {
gisela.currentAnimation = 'LOOK_RIGHT';
}
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
switch (browser) {
case 'Chrome':
architecture.drawForChrome(context, camera);
break;
default:
architecture.drawForFirefox(context, camera);
}
mrCroc.draw(context, camera);
gisela.draw(context, camera);
userInterface.draw(context);
}
lastTimestamp = timestamp;
if (!gameFinished && mrCroc.isJumping === false && architecture.isMovableInsideTargetPosition(mrCroc)) {
gameFinished = true;
KeyLeft.pressed = false;
KeyRight.pressed = false;
KeyJump.pressed = false;
lastTimestamp = undefined;
lastRendered = undefined;
textBoxGameFinished.updateLines(window.innerWidth - 40, context);
textBoxGameFinished.animate(75);
userInterface.addTextBox(textBoxGameFinished);
}
window.requestAnimationFrame(MainLoop);
}
const LEVEL = [
@ -94,18 +150,93 @@ const LEVEL = [
'moonbase.json',
'terrain8.json',
'darius.json',
'imperial-prison.json',
'southpole.json',
];
let game;
let urlGetter = new UrlParam();
const urlGetter = new UrlParam();
const levelIndex = urlGetter.getInt('level');
let levelIndex = urlGetter.getInt('level');
Level.createFromFile(
Setting.LEVELS_LOCATION + LEVEL[levelIndex % LEVEL.length],
(level) => {
loadLevel(level);
if (levelIndex === undefined || levelIndex < 0 || levelIndex >= LEVEL.length) {
levelIndex = 0;
}
let level = Level.createFromFile(Setting.LEVELS_LOCATION + LEVEL[levelIndex]);
const GAME_SPEED = 1;
const GRAVITY = level.gravity;
let fps = 120;
const browser = navigator.userAgent.indexOf('Firefox') === -1 ? 'Chrome' : 'Firefox';
let frameDuration;
let lastRendered = undefined;
let lastTimestamp = undefined;
let context;
let mrCroc, gisela, architecture;
let camera = new Camera();
let gameFinished = false;
let hasPlayerLeftArchitecture = false;
let textBoxGameStart;
let textBoxGameFinished;
let userInterface = new UserInterface();
let KeyLeft = new Key('ArrowLeft');
let KeyRight = new Key('ArrowRight');
let KeyJump = new Key('Space');
let loader = new ImageLoader();
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png');
loader.addImage(Setting.TILESET_LOCATION + GraphicSet[level.getTilesetId()].tileset);
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-left.png');
window.addEventListener(
'imagesloaded',
() => {
let canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.backgroundAttachment = 'fixed';
canvas.style.backgroundSize = 'cover';
canvas.style.backgroundPosition = 'center center';
if (GraphicSet[level.getTilesetId()].backgroundImage !== null) {
canvas.style.backgroundImage = 'url("' + Setting.GRAPHICS_LOCATION + GraphicSet[level.getTilesetId()].backgroundImage +'")';
}
canvas.style.backgroundColor = level.getBackgroundColor();
window.addEventListener(
'resize',
function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
);
context = canvas.getContext('2d');
textBoxGameFinished = new TextMessageGisela(
'Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."',
context
);
textBoxGameStart = new TextMessageMrCroc('Mr. Croc: "Where is Gisela? I have to find her!"', context);
textBoxGameStart.animate(75, 1000);
textBoxGameStart.show(1000);
textBoxGameStart.hide(10000);
userInterface.addTextBox(textBoxGameStart);
architecture = RetroArchitecture.createFromData(level);
camera.borderRight = architecture.columns * architecture.tileWidth;
camera.borderBottom = architecture.rows * architecture.tileHeight;
mrCroc = new MrCroc();
architecture.setMovableToStartPosition(mrCroc);
gisela = new Gisela();
architecture.setMovableToTargetPosition(gisela);
frameDuration = 1000 / fps;
window.requestAnimationFrame(MainLoop);
}
);

View File

@ -62,5 +62,4 @@ export default class RetroAnimation extends RetroSprite
this.isPlaying = false;
}
}
}

View File

@ -5,6 +5,7 @@ import GeometryPoint from "../geometry/GeometryPoint.js";
import GeometryRect from "../geometry/GeometryRect.js";
import GraphicSet from "../GraphicSet.js";
import Setting from "../Setting.js";
import Camera from "../Camera.js";
export default class RetroArchitecture
{
@ -19,6 +20,10 @@ export default class RetroArchitecture
this.matrix = [];
this.tileWidth = this.tilesetSprite.getWidth() / this.tiles;
this.tileHeight = this.tilesetSprite.getHeight();
this.terrainCanvas = document.createElement('canvas');
this.terrainCanvas.width = this.tileWidth * this.columns;
this.terrainCanvas.height = this.tileHeight * this.rows;
this.terrainContext = this.terrainCanvas.getContext('2d');
this.startX = 0;
this.startY = 0;
this.targetX = 0;
@ -41,6 +46,23 @@ export default class RetroArchitecture
}
}
render()
{
const camera = new Camera();
for (let y = 0; y < this.rows; y++) {
for (let x = 0; x < this.columns; x++) {
const field = this.matrix[y][x];
if (field === null) {
continue;
}
this.drawField(this.terrainContext, x, y, camera, field);
}
}
}
setBackgroundColor(color)
{
this.backgroundColor = color;
@ -202,7 +224,7 @@ export default class RetroArchitecture
tileRect.isContainingPoint(movable.getPositionFootRight());
}
draw(context, camera = new Camera())
drawForFirefox(context, camera = new Camera())
{
const viewX = parseInt(Math.floor(Math.max(0, camera.position.x) / this.tileWidth));
const viewWidth = parseInt(Math.min(Math.ceil(camera.width), this.columns));
@ -211,7 +233,7 @@ export default class RetroArchitecture
for (let y = viewY; y < viewHeight; y++) {
for (let x = viewX; x < viewWidth; x++) {
let field = this.matrix[y][x];
const field = this.matrix[y][x];
if (field !== null) {
this.drawField(context, x, y, camera, field);
@ -220,26 +242,41 @@ export default class RetroArchitecture
}
}
/**
*
* @param context
* @param camera Camera
*/
drawForChrome(context, camera)
{
context.drawImage(
this.terrainCanvas,
camera.position.x,
camera.position.y,
camera.width,
camera.height,
0,
0,
camera.width,
camera.height
);
}
drawField(context, x, y, camera, field)
{
context.drawImage(
this.tilesetSprite.canvas,
(field.tile.index % this.tiles) * this.tileWidth,
field.tile.index * this.tileWidth,
0,
this.tileWidth,
this.tileHeight,
Math.round(x * this.tileWidth - camera.position.x),
Math.round(y * this.tileHeight - camera.position.y),
this.tileWidth,
this.tileHeight,
x * this.tileWidth - camera.position.x,
y * this.tileHeight - camera.position.y,
this.tileWidth + 1,
this.tileHeight + 1
);
}
getStartPosition()
{
return new GeometryPoint(this.startX * this.tileWidth, this.startY * this.tileHeight);
}
static createFromData(level)
{
let graphicSet = GraphicSet[level.getTilesetId()];
@ -279,6 +316,8 @@ export default class RetroArchitecture
}
}
architecture.render();
return architecture;
}
}

View File

@ -82,7 +82,7 @@ export default class RetroSprite
canvasTemp.width = this.image.width * this.scale;
canvasTemp.height = this.image.height * this.scale;
let contextTemp = canvasTemp.getContext('2d', {willReadFrequently: true});
let contextTemp = canvasTemp.getContext('2d');
contextTemp.drawImage(this.image, 0, 0);
this.canvas.width = this.image.width * this.scale;
@ -99,4 +99,4 @@ export default class RetroSprite
}
}
}
}
}

View File

@ -1,44 +0,0 @@
import Dialog from "../../tilorswift/js/dialog/Dialog.js";
export class LoadLevelDialog extends Dialog
{
constructor() {
super();
this.setMessage('Level laden');
this.fileInput = this.createFileInput(['json']);
this.fileInput.addEventListener(
'change',
() => {
if (this.fileInput.files.length === 0) {
return;
}
const reader = new FileReader();
reader.addEventListener(
'load',
(event) => {
this.onClose();
this.onLoad(event.target.result);
}
)
reader.readAsBinaryString(this.fileInput.files[0]);
}
)
this.onClose = () => {};
this.onLoad = () => {};
this.buttonCancel = this.createButton('Abbrechen');
this.buttonCancel.addEventListener(
'click',
() => {
this.onClose();
}
);
}
openFileBrowser()
{
this.fileInput.click();
}
}

View File

@ -4,12 +4,11 @@ import UserInterfaceElement from "./UserInterfaceElement.js";
export default class TextBox extends UserInterfaceElement
{
constructor(text, width, context, paused = false)
constructor(text, width, context)
{
super();
this.text = text;
this.width = width;
this.paused = paused;
this.colorText = 'red';
this.colorShadow = 'black';
this.colorBorder = 'black';
@ -116,4 +115,4 @@ export default class TextBox extends UserInterfaceElement
return line;
}
}
}

View File

@ -2,10 +2,9 @@ import TextAlignment from "./TextAlignment.js";
export default class TextLine
{
constructor(text, paused)
constructor(text)
{
this.text = text;
this.paused = paused;
this.estimatedTextWidth = null;
this.colorText = 'red';
this.colorShadow = 'black';
@ -25,10 +24,6 @@ export default class TextLine
let process = setInterval(
() => {
if (this.paused) {
return;
}
this.chars++;
if (this.chars === this.text.length) {
@ -88,4 +83,4 @@ export default class TextLine
context.fillText(this.text.substr(0, this.chars), x + 2, y + this.size + 2);
}
}
}
}

View File

@ -3,8 +3,8 @@ import GeometryPoint from "../geometry/GeometryPoint.js";
export default class TextMessage extends TextBox
{
constructor(text, context, paused = false) {
super(text, window.innerWidth - 40, context, paused);
constructor(text, context) {
super(text, window.innerWidth - 40, context);
this.update();
this.context = context;
}
@ -21,4 +21,4 @@ export default class TextMessage extends TextBox
this.setPosition(this.defaultPosition.x, this.defaultPosition.y);
this.updateLines(this.defaultWidth, this.context);
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"tileset":2,"rows":"30","columns":"30","startX":2,"startY":28,"targetX":2,"targetY":15,"gravity":9.806,"matrix":[[3,0,5,0,5,18,-1,30,5,0,5,0,21,-1,-1,33,5,0,0,5,0,0,5,0,0,3,21,-1,33,3],[2,0,24,0,24,72,-1,66,24,24,0,24,19,-1,-1,31,0,0,0,0,0,0,0,24,24,25,73,-1,31,1],[3,18,-1,92,-1,-1,-1,-1,-1,-1,92,-1,87,-1,-1,33,24,28,28,24,28,28,72,-1,-1,-1,-1,-1,33,3],[2,18,-1,-1,-1,8,-1,10,-1,-1,-1,-1,85,-1,-1,92,-1,-1,-1,-1,-1,-1,-1,-1,36,13,43,-1,31,1],[3,18,-1,39,57,75,-1,69,57,63,-1,51,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,30,3,21,-1,33,3],[2,18,-1,85,-1,-1,-1,-1,-1,-1,-1,-1,85,-1,-1,38,56,56,62,-1,-1,50,56,56,0,1,19,-1,31,1],[3,18,-1,87,-1,-1,50,56,56,56,56,56,21,-1,-1,84,-1,-1,-1,-1,-1,-1,-1,-1,30,3,21,-1,33,3],[2,18,-1,31,62,-1,-1,-1,-1,-1,-1,-1,85,-1,-1,86,-1,-1,50,62,-1,-1,-1,-1,30,1,19,-1,31,1],[3,18,-1,87,-1,-1,38,56,62,-1,50,56,21,-1,-1,86,-1,-1,-1,-1,-1,-1,-1,-1,30,3,21,-1,33,3],[2,18,-1,85,-1,37,19,-1,-1,-1,-1,-1,85,-1,-1,30,63,-1,-1,-1,-1,-1,-1,51,0,1,19,-1,1,1],[3,18,-1,69,56,26,20,-1,50,56,62,-1,93,-1,-1,86,-1,-1,-1,-1,-1,-1,-1,-1,30,3,21,-1,3,3],[2,18,-1,-1,-1,-1,89,-1,-1,-1,-1,-1,-1,-1,-1,84,-1,50,62,-1,-1,80,-1,-1,30,1,19,-1,1,1],[3,0,62,-1,50,14,26,56,14,56,15,56,44,-1,-1,86,-1,-1,-1,-1,-1,-1,-1,51,0,3,21,-1,3,3],[2,18,-1,-1,-1,86,-1,-1,89,-1,85,-1,89,-1,51,18,-1,-1,-1,-1,-1,-1,-1,-1,30,1,19,-1,31,1],[3,18,-1,-1,-1,86,-1,-1,95,-1,93,-1,95,-1,-1,92,-1,-1,7,-1,-1,-1,7,-1,30,3,21,-1,33,3],[2,18,-1,-1,-1,86,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,88,-1,-1,-1,88,-1,30,1,19,-1,31,1],[3,2,57,56,57,2,15,56,57,56,15,14,45,-1,-1,36,12,12,0,14,14,14,0,12,0,3,21,-1,33,3],[2,18,-1,-1,-1,30,18,-1,-1,-1,30,5,18,-1,80,0,5,5,0,5,5,5,0,5,0,1,19,-1,31,1],[3,18,-1,10,-1,32,20,-1,10,-1,30,5,18,-1,-1,66,24,24,0,26,26,26,24,24,24,27,75,-1,33,3],[2,0,14,0,14,0,0,14,0,14,0,2,0,80,-1,-1,-1,-1,92,-1,-1,-1,-1,-1,-1,-1,-1,-1,31,1],[3,0,5,0,5,0,0,5,0,5,0,5,18,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,36,15,45,-1,33,3],[2,0,2,0,2,0,0,2,0,2,0,2,0,14,44,-1,50,56,56,56,56,62,-1,-1,30,1,19,-1,31,1],[3,0,3,0,3,0,0,3,0,3,0,3,0,3,18,-1,33,3,3,3,21,-1,-1,-1,30,3,21,-1,33,3],[2,0,26,24,26,24,0,26,24,26,24,26,0,0,18,-1,30,0,0,0,18,-1,-1,80,0,1,19,-1,31,1],[3,18,-1,-1,-1,-1,86,-1,-1,-1,-1,-1,30,2,18,-1,30,2,0,2,18,-1,-1,-1,30,3,21,-1,33,3],[2,18,-1,-1,-1,-1,92,-1,-1,-1,-1,-1,30,2,18,-1,30,2,0,2,0,62,-1,-1,30,1,19,-1,31,1],[3,18,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,66,24,72,-1,66,24,24,24,72,-1,-1,-1,30,3,21,-1,33,3],[2,18,-1,-1,-1,-1,-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,0,1,19,-1,31,1],[3,18,-1,-1,-1,-1,8,-1,-1,87,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,30,3,21,-1,33,3],[2,0,12,17,16,17,0,12,17,0,17,12,14,44,-1,-1,38,44,-1,-1,38,14,14,14,0,1,19,-1,31,1]]}

View File

@ -3,7 +3,7 @@
"rows": 10,
"columns": 17,
"backgroundColor": "#6096ff",
"gravity": 9.806,
"gravity": 2.0,
"matrix": [
[6 ,6 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,4 ,4 ],
[6 ,6 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,-1 ,4 ,4 ],
@ -16,4 +16,4 @@
[4 ,4 ,0 ,0 ,0 ,-1 ,4 ,4 ,4 ,-1 ,-1 ,0 ,4 ,4 ,4 ,4 ,4 ],
[4 ,4 ,4 ,4 ,4 ,0 ,4 ,4 ,4 ,0 ,0 ,4 ,4 ,4 ,4 ,4 ,4 ]
]
}
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"tileset":1,"rows":"20","columns":51,"startX":2,"startY":16,"targetX":49,"targetY":16,"backgroundColor":"black","gravity":2.4515,"matrix":[[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,1,1,1,1,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,1],[1,1,0,0,1,1,1,1,1,1,1,0,0,-1,-1,-1,-1,-1,-1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,1,1,1,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]}
{"tileset":1,"rows":"20","columns":51,"startX":2,"startY":16,"targetX":49,"targetY":16,"backgroundColor":"black","gravity":0.5,"matrix":[[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1],[1,1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,1,1,1,1,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,1],[1,1,0,0,1,1,1,1,1,1,1,0,0,-1,-1,-1,-1,-1,-1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,1,1,1,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"tileset":5,"rows":"30","columns":"50","startX":2,"startY":23,"targetX":47,"targetY":5,"gravity":9.806,"matrix":[[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,81,32,0,0,0,0,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,81,32,0,0,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,81,0,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,43,15,50,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,43,15,15,15,64,71,-1,-1,-1,61,68,5,5,89,-1,-1,-1,43,50,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,57,29,29,29,85,-1,-1,-1,-1,-1,-1,-1,80,87,-1,-1,-1,-1,82,5,19,68,75,-1,-1,96,-1,-1,-1,96,-1,-1,61,75,-1,-1,-1,42,14,0,0],[-1,-1,-1,-1,-1,-1,96,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,87,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,81,32,4,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,0],[-1,-1,-1,-1,96,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35],[-1,-1,-1,-1,-1,43,15,50,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35],[-1,-1,-1,-1,-1,36,33,89,-1,-1,-1,62,16,16,51,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35],[-1,-1,-1,-1,61,89,-1,-1,-1,-1,-1,-1,83,34,34,55,-1,-1,-1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,108,-1,-1,-1,37,51,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,42,0],[-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,6,6,20,76,-1,-1,-1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,109,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,3,87,-1,-1,-1,62,34,76,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,109,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,108,-1,-1,-1,-1,-1,-1,-1,-1,-1,44,76,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,109,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,111,-1,-1,-1,93,-1,-1,-1,93,-1,-1,44,51,-1,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,83,6,51,-1,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,38,6,76,-1,-1,-1,35,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,80,87,-1,-1,-1,60,0,0],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[14,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,60,0,0],[0,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,35,0],[0,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,60,14,14,0,0],[0,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,81,4,0,0],[0,0,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,42,49,-1,-1,-1,-1,-1,-1,-1,42,14,14,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,42,14,49,-1,-1,-1,80,4,4],[0,0,0,14,14,49,-1,-1,-1,-1,-1,-1,-1,-1,42,0,0,49,-1,-1,-1,42,14,14,0,0,0,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,39,4,25,-1,-1,-1,-1,38,3],[0,0,0,0,0,0,14,14,14,49,-1,-1,46,18,4,4,4,4,53,-1,-1,39,4,4,4,4,4,25,-1,-1,-1,13,-1,-1,13,-1,-1,-1,13,-1,-1,38,3,24,-1,-1,-1,-1,38,3]],"effects":["snow"]}

View File

@ -1 +1 @@
{"tileset":0,"rows":"20","columns":"40","startX":0,"startY":18,"targetX":0,"targetY":8,"gravity":9.806,"matrix":[[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[7,-1,-1,-1,1,-1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[7,-1,4,-1,4,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,4,1,4,1,1,1,4,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[5,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,4,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[4,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[4,1,1,1,1,-1,-1,-1,1,1,1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,5,-1,-1,-1,4,4,1,-1,-1,-1,-1,-1,1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,4,4,-1,-1,1,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,1,5,5,-1,-1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,4,4,4,-1,-1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[1,1,1,1,1,4,4,4,1,1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]]}
{"tileset":0,"rows":"20","columns":"40","startX":0,"startY":18,"targetX":0,"targetY":8,"gravity":2.0,"matrix":[[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[7,-1,-1,-1,1,-1,-1,-1,1,1,1,1,1,1,1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[7,-1,4,-1,4,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,4,1,4,1,1,1,4,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[5,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,4,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[4,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[4,1,1,1,1,-1,-1,-1,1,1,1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,5,-1,-1,-1,4,4,1,-1,-1,-1,-1,-1,1,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,4,4,-1,-1,1,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,1,5,5,-1,-1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,4,4,4,-1,-1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[1,1,1,1,1,4,4,4,1,1,4,4,4,-1,-1,4,-1,-1,4,-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -4,10 +4,9 @@
<meta charset="UTF-8">
<title>Tilorswift</title>
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="shortcut icon" type="image/png" href="favicon.png">
<script type="module" src="js/module.js" defer></script>
<script type="module" src="js/module.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>
</html>

View File

@ -5,6 +5,5 @@ export default class Brush
constructor()
{
this.mode = BrushMode.TERRAIN;
this.isIntelligent = false;
}
}
}

View File

@ -5,7 +5,7 @@ export default class ButtonTile extends Field
{
constructor(tileset, index = 0)
{
super(tileset, 0, 0, index);
super(tileset, index);
}
initHtml() {
@ -22,4 +22,4 @@ export default class ButtonTile extends Field
}
)
}
}
}

View File

@ -3,12 +3,10 @@ import TilorswiftFieldEnteredEvent from "./events/TilorswiftFieldEnteredEvent.js
export default class Field
{
constructor(tileset, x = 0, y = 0, index = -1)
constructor(tileset, index = -1)
{
this.tileset = tileset;
this.index = index;
this.x = x;
this.y = y;
this.isEntrancePoint = false;
this.isTargetPoint = false;
this.initHtml();
@ -93,4 +91,4 @@ export default class Field
{
return this.htmlElement;
}
}
}

View File

@ -53,12 +53,12 @@ export default class Terrain
getWidth()
{
return this.tilesX * this.tileset.getTileWidth();
return this.tilesX * this.tilest.getTileWidth();
}
getHeight()
{
return this.tilesY * this.tileset.getTileHeight();
return this.tilesY * this.tilest.getTileHeight();
}
addRows(index, quantity = 1)
@ -70,26 +70,19 @@ export default class Terrain
this.targetTileY = this.targetTileY === undefined ? undefined : this.targetTileY + 1;
}
for (let y = index; y < this.tilesY; y++) {
for (let x = 0; x < this.tilesX; x++) {
// this.fields[y][x].index += quantity;
console.log(x, y);
this.fields[y][x].y += quantity;
}
}
this.htmlElement.style.height = this.tileset.getTileHeight() * this.tilesY + 'px';
}
_insertRow(index = undefined)
{
const row = [];
const tr = document.createElement('tr');
let row = [];
let tr = document.createElement('tr');
for (let col = 0; col < this.tilesX; col++) {
const field = new Field(this.tileset, col, this.fields.length);
let field = new Field(this.tileset);
let td = field.getElement();
row.push(field);
tr.appendChild(field.getElement());
tr.appendChild(td);
}
if (index === undefined || index >= this.tilesY - 1) {
@ -106,8 +99,6 @@ export default class Terrain
addColumns(index, quantity = 1)
{
console.log(this.fields);
for (let c = 0; c < quantity; c++) {
this._insertColumn(index);
this.tilesX++;
@ -115,15 +106,7 @@ export default class Terrain
this.targetTileX = this.targetTileX === undefined ? undefined : this.targetTileX + 1;
}
for (let y = 0; y < this.tilesY; y++) {
for (let x = index; x < this.tilesX; x++) {
this.fields[y][x].x += quantity;
}
}
this.htmlElement.style.width = this.tileset.getTileWidth() * this.tilesX + 'px';
console.log(this.fields);
}
_insertColumn(index = undefined)
@ -200,11 +183,10 @@ export default class Terrain
static createFromJson(levelData)
{
const graphicSet = GraphicSet[levelData.tileset];
let graphicSet = GraphicSet[levelData.tileset];
const tileset = new Tileset(levelData.tileset);
const terrain = new Terrain(tileset, levelData.columns, levelData.rows, graphicSet.backgroundColor);
terrain.backgroundImage = graphicSet.backgroundImage ?? undefined;
let tileset = new Tileset(levelData.tileset);
let terrain = new Terrain(tileset, levelData.columns, levelData.rows, graphicSet.backgroundColor);
for (let y = 0; y < levelData.rows; y++) {
for (let x = 0; x < levelData.columns; x++) {
@ -220,60 +202,4 @@ export default class Terrain
return terrain;
}
getFieldNeighbours(field)
{
const neighbours = [];
for (let x = Math.max(0, field.x - 1); x < Math.min(this.tilesX, field.x + 2); x++) {
for (let y = Math.max(0, field.y - 1); y < Math.min(this.tilesY, field.y + 2); y++) {
if (field.x === x && field.y === y) {
continue;
}
neighbours.push(this.fields[y][x]);
}
}
return neighbours;
}
hasFieldNeighbour(field, offsetX, offsetY)
{
const x = field.x + offsetX;
const y = field.y + offsetY;
if (x < 0 || x > this.tilesX - 1) {
return true;
}
if (y < 0 || y > this.tilesY - 1) {
return true;
}
return this.fields[y][x].index > -1;
}
getFieldNeighbourCode(field)
{
let code = '';
if (!this.hasFieldNeighbour(field, -1, 0)) {
code += 'l';
}
if (!this.hasFieldNeighbour(field, 0, -1)) {
code += 't';
}
if (!this.hasFieldNeighbour(field, 1, 0)) {
code += 'r';
}
if (!this.hasFieldNeighbour(field, 0, 1)) {
code += 'b';
}
return code;
}
}
}

View File

@ -10,7 +10,6 @@ export default class Tileset
this.image.src = '../' + Setting.TILESET_LOCATION + GraphicSet[this.setId].tileset;
this.tiles = GraphicSet[this.setId].tiles;
this.scale = GraphicSet[this.setId].scale;
this.primaryTiles = GraphicSet[this.setId].primaryTiles;
}
getWidth()
@ -32,16 +31,4 @@ export default class Tileset
{
return this.image.height * this.scale;
}
hasExtendedTiles()
{
return GraphicSet[this.setId].tiles > GraphicSet[this.setId].primaryTiles ;
}
getTileIndexFactor(code)
{
const CODES = ['ltr', 't', 'r', 'b', 'l', 'lt', 'tr', 'ltb', 'tb', 'trb', 'lb', 'rb', 'ltrb', 'lr', 'lrb'];
return CODES.indexOf(code) + 1;
}
}

View File

@ -1,171 +1,54 @@
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 {RainEffect} from "../../js/effects/RainEffect.js";
import {ThunderstormEffect} from "../../js/effects/ThunderstormEffect.js";
import {FullscreenEffectFactory} from "../../js/effects/FullscreenEffectFactory.js";
export default class Tilorswift
{
static EFFECT_NAMES = {
[SnowEffect.NAME]: 'Schnee',
[RainEffect.NAME]: 'Regen',
[ThunderstormEffect.NAME]: 'Gewitter',
}
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()
static getLevelAsJson(level)
{
let matrix = [];
for (let y = 0; y < this.level.terrain.fields.length; y++) {
for (let y = 0; y < 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);
for (let x = 0; x < level.terrain.fields[y].length; x++) {
row.push(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,
tileset: level.getTilesetId(),
rows: level.getRows(),
columns: level.getColumns(),
startX: level.getStartX(),
startY: level.getStartY(),
targetX: level.getTargetX(),
targetY: level.getTargetY(),
gravity: level.gravity,
matrix: matrix,
effects: this.level.fullscreenEffects.map((effect) => {return effect.getName()}),
};
return JSON.stringify(data);
}
openLevelFromFile()
static saveLevelToFile(level)
{
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()) {
if (!level.hasEntrancePoint()) {
alert('Es muss ein Startpunkt definiert sein!');
return false;
}
if (!this.level.hasTargetPoint()) {
if (!level.hasTargetPoint()) {
alert('Es muss ein Zielpunkt definiert sein!');
return false;
}
const filename = prompt('Dateiname', 'terrain.json');
let filename = prompt('Dateiname', 'terrain.json');
if (filename === null) {
return false;
}
const json = this.getLevelAsJson(level);
const download = document.createElement('a');
let json = Tilorswift.getLevelAsJson(level);
let download = document.createElement('a');
download.setAttribute('download', filename);
download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json));
@ -174,240 +57,4 @@ export default class Tilorswift
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,
Tilorswift.EFFECT_NAMES,
);
}
);
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());
}
}
);
}
}
}

View File

@ -1,7 +1,6 @@
import GraphicSet from "../../../js/GraphicSet.js";
import Setting from "../../../js/Setting.js";
import TilorswiftTilesetSelectedEvent from "../events/TilorswiftTilesetSelectedEvent.js";
import {Checkbox} from "./elements/Checkbox.js";
export default class Dialog
{
@ -67,16 +66,6 @@ export default class Dialog
return htmlElementInput;
}
createCheckbox(label, value, isChecked = false, onClick = () => {})
{
const checkbox = new Checkbox(label, value, isChecked);
checkbox.onClick = onClick;
this.inputAreaElement.appendChild(checkbox.htmlElement);
return checkbox;
}
createTilesetSelector()
{
let htmlElement = document.createElement('div');
@ -111,12 +100,7 @@ export default class Dialog
let htmlThumbnail = document.createElement('div');
htmlThumbnail.classList.add('tileset-thumbnail');
const image = new Image();
image.src = '../' + Setting.TILESET_LOCATION + graphicSet.tileset;
htmlThumbnail.style.backgroundImage = 'url(' + image.src + ')';
htmlThumbnail.style.backgroundPositionX = -(image.width / graphicSet.tiles) * graphicSet.tilePreview + 'px';
htmlThumbnail.style.backgroundImage = 'url("../' + Setting.TILESET_LOCATION + graphicSet.tileset + '")';
htmlTilesetElement.appendChild(htmlThumbnail);
let htmlTitleElement = document.createElement('div');
@ -128,9 +112,7 @@ export default class Dialog
'click',
() => {
htmlListElement.style.display = 'none';
htmlAvatarElement.style.backgroundImage = 'url(' + image.src + ')';
htmlAvatarElement.style.backgroundPositionX = -96 * graphicSet.tilePreview + 'px';
htmlAvatarElement.style.backgroundImage = 'url("../' + Setting.TILESET_LOCATION + GraphicSet[index].tileset + '")';
window.dispatchEvent(new TilorswiftTilesetSelectedEvent(index));
}
);
@ -144,33 +126,8 @@ export default class Dialog
return htmlElement;
}
createFileInput(types = [])
{
let input = document.createElement('input');
input.type = 'file';
if (types.length > 0) {
for (const t in types) {
types[t] = '.' + types[t]
}
input.accept = types.join(', ');
}
this.inputAreaElement.appendChild(input);
return input;
}
setMessage(message)
{
this.messageElement.innerText = message;
}
close()
{
this.htmlElement.remove();
}
}

View File

@ -1,45 +0,0 @@
import Dialog from "./Dialog.js";
import TilorswiftEffectsUpdatedEvent from "../events/TilorswiftEffectsUpdatedEvent.js";
export default class DialogEffects extends Dialog
{
constructor(effects, checked, translations)
{
super();
this.setMessage('Effekte');
this.effects = [];
for (const effect of effects) {
const checkbox = this.createCheckbox(
translations[effect],
effect,
checked.indexOf(effect) !== -1,
() => {
console.log(checkbox.name, 'is', checkbox.isChecked());
}
);
this.effects.push(checkbox);
this.inputAreaElement.appendChild(checkbox.htmlElement);
}
this.createButton('Abbrechen');
this.buttonOk = this.createButton('OK');
this.buttonOk.addEventListener(
'click',
() => {
const effectNames = [];
for (const effect of this.effects) {
if (effect.isChecked()) {
effectNames.push(effect.name);
}
}
window.dispatchEvent(
new TilorswiftEffectsUpdatedEvent(effectNames)
);
}
)
}
}

View File

@ -7,7 +7,7 @@ export default class DialogGravity extends Dialog
{
super();
this.setMessage('Gravitation einstellen');
this.inputGravity = this.createInputNumber('Stärke', gravity, 0, 10, 0.001);
this.inputGravity = this.createInputNumber('Stärke', gravity, 0, 10, 0.01);
this.createButton('Abbrechen');
this.buttonOk = this.createButton('OK');
this.buttonOk.addEventListener(
@ -19,4 +19,4 @@ export default class DialogGravity extends Dialog
}
)
}
}
}

View File

@ -1,29 +0,0 @@
export class Checkbox
{
constructor(label, name, isChecked = false)
{
this.name = name;
this.htmlElement = document.createElement('div');
this.onClick = () => {};
this.checkbox = document.createElement('input');
this.checkbox.type = 'checkbox';
this.checkbox.checked = isChecked;
this.checkbox.onclick = () => {
this.onClick();
}
this.htmlLabel = document.createElement('label');
this.htmlLabel.innerText = label;
this.htmlElement.appendChild(this.checkbox);
this.htmlElement.appendChild(this.htmlLabel);
}
isChecked()
{
return this.checkbox.checked;
}
}

View File

@ -1,9 +0,0 @@
import TilorswiftEvent from "./TilorswiftEvent.js";
export default class TilorswiftEffectsUpdatedEvent extends Event
{
constructor(effectNames) {
super(TilorswiftEvent.EFFECTS_UPDATED);
this.effectNames = effectNames;
}
}

View File

@ -3,7 +3,6 @@ const TilorswiftEvent = {
FIELD_ENTERED: 'fieldEntered',
BUTTON_TILE_CLICKED: 'buttonTileClicked',
MENU_SAVE_CLICKED: 'menuSaveClicked',
MENU_OPEN_CLICKED: 'menuOpenClicked',
DIALOG_BUTTON_OK_CLICKED: 'dialogButtonOkClicked',
MENU_EDIT_CLICKED: 'menuEditClicked',
SAVED: 'saved',
@ -17,7 +16,6 @@ const TilorswiftEvent = {
TILESET_SELECTED: 'tilesetSelected',
MENU_GRAVITY_CLICKED: 'menuGravityClicked',
GRAVITY_UPDATED: 'gravityUpdated',
MENU_EFFECTS_CLICKED: 'menuEffectsClicked',
};
export default TilorswiftEvent;
export default TilorswiftEvent;

View File

@ -1,9 +0,0 @@
import TilorswiftEvent from "./TilorswiftEvent.js";
export default class TilorswiftMenuEffectsClickedEvent extends Event
{
constructor()
{
super(TilorswiftEvent.MENU_EFFECTS_CLICKED);
}
}

View File

@ -1,8 +0,0 @@
import TilorswiftEvent from "./TilorswiftEvent.js";
export class TilorswiftMenuOpenCLickedEvent extends Event
{
constructor() {
super(TilorswiftEvent.MENU_OPEN_CLICKED);
}
}

View File

@ -1,58 +0,0 @@
import Widget from "./Widget.js";
import {Switch} from "./Switch.js";
export class IntelligentBrushSwitch extends Widget
{
constructor(tilesetPicker, brush) {
super('Intelligenter Pinsel');
this.tilesetPicker = tilesetPicker;
this.brush = brush;
this.switch = new Switch();
this.switch.onToggle = (status) => {
if (this.isActive) {
this.setIntelligentBrush(status);
}
}
this.htmlElement.appendChild(this.switch.htmlElement);
if (tilesetPicker.tileset.hasExtendedTiles()) {
this.setIntelligentBrush(true);
}
}
switchOn()
{
if (!this.switch.status) {
this.switch.toggle()
this.setIntelligentBrush(true);
}
}
switchOff()
{
if (this.switch.status) {
this.switch.toggle()
this.setIntelligentBrush(false);
}
}
setIntelligentBrush(status)
{
this.brush.isIntelligent = status;
this.tilesetPicker.updateExtendedTileVisibility();
}
enable() {
super.enable();
this.switch.enable();
}
disable() {
super.disable();
this.switch.disable();
}
}

View File

@ -1,50 +0,0 @@
export class Switch
{
constructor(status = false) {
this.htmlElement = document.createElement('div');
this.htmlElement.classList.add('switch');
this.slider = document.createElement('div');
this.slider.classList.add('switch-slider');
this.htmlElement.appendChild(this.slider);
this.status = status;
this.isEnabled = true;
this.updateSlider();
this.onToggle = () => {}
this.htmlElement.addEventListener(
'click',
() => {
if (!this.isEnabled) {
return;
}
this.toggle();
this.onToggle(this.status);
}
)
}
toggle()
{
this.status = !this.status;
this.updateSlider();
}
updateSlider()
{
this.slider.classList.add(this.status ? 'switch-slider-on' : 'switch-slider-off');
this.slider.classList.remove(this.status ? 'switch-slider-off' : 'switch-slider-on');
}
enable()
{
this.isEnabled = true;
}
disable()
{
this.isEnabled = false;
}
}

View File

@ -24,13 +24,13 @@ export default class TilesetPickerWidget extends Widget
this.brush.mode = BrushMode.TERRAIN;
}
}
);
)
}
loadTileset()
{
for (let t = 0; t < this.tileset.tiles; t++) {
const button = new ButtonTile(this.tileset, t);
let button = new ButtonTile(this.tileset, t);
this.htmlElementSelector.appendChild(button.getElement());
}
@ -48,7 +48,7 @@ export default class TilesetPickerWidget extends Widget
createElementPicker()
{
const htmlElement = document.createElement('div');
let htmlElement = document.createElement('div');
htmlElement.id = 'tileset-picker';
htmlElement.style.width = this.tileset.getTileWidth() + 'px';
htmlElement.style.height = this.tileset.getTileHeight() + 'px';
@ -59,9 +59,9 @@ export default class TilesetPickerWidget extends Widget
createElementSelector()
{
const htmlElementSelector = document.createElement('div');
let htmlElementSelector = document.createElement('div');
htmlElementSelector.id = 'tileset-selector-widget';
htmlElementSelector.style.width = Math.ceil(Math.sqrt(this.tileset.tiles)) * this.tileset.getTileWidth() + 'px';
htmlElementSelector.style.width = Math.ceil(Math.sqrt(this.tileset.tiles)) * this.tileset.getTileWidth() + 'px';
htmlElementSelector.style.left = String(this.tileset.getTileWidth() + 1) + 'px';
return htmlElementSelector;
@ -69,24 +69,12 @@ export default class TilesetPickerWidget extends Widget
setTile(index)
{
this.htmlElement.style.backgroundPosition = -this.tileset.getTileWidth() * index + 'px ' + this.tileset.getTileHeight() + 'px';
let position = -this.tileset.getTileWidth() * index + 'px ' + this.tileset.getTileHeight() + 'px';
this.htmlElement.style.backgroundPosition = position;
}
getElement()
{
return this.htmlElement;
}
updateExtendedTileVisibility()
{
const firstExtendedTileIndex = this.tileset.tiles - (this.tileset.tiles - this.tileset.primaryTiles);
for (const index of this.htmlElementSelector.childNodes.keys()) {
if (index >= firstExtendedTileIndex) {
this.htmlElementSelector.childNodes.item(index).style.display = this.brush.isIntelligent
? 'none'
: 'inline-flex';
}
}
}
}
}

View File

@ -1,23 +1,208 @@
import Terrain from "./Terrain.js";
import TilorswiftEvent from "./events/TilorswiftEvent.js";
import Mouse from "./Mouse.js";
import Tileset from "./Tileset.js";
import Tilorswift from "./Tilorswift.js";
import Level from "../../js/Level.js";
import ImageLoader from "../../js/ImageLoader.js";
import TilorswiftSavedEvent from "./events/TilorswiftSavedEvent.js";
import MainMenu from "./menu/MainMenu.js";
import MenuGroup from "./menu/MenuGroup.js";
import MainMenuEntry from "./menu/MainMenuEntry.js";
import TilorswiftMenuSaveClickedEvent from "./events/TilorswiftMenuSaveClickedEvent.js";
import TilesetPickerWidget from "./menu/TilesetPickerWidget.js";
import WidgetBar from "./menu/WidgetBar.js";
import EntrancePointWidget from "./menu/EntrancePointWidget.js";
import Brush from "./Brush.js";
import BrushMode from "./BrushMode.js";
import DialogAddRows from "./dialog/DialogAddRows.js";
import DialogAddColumns from "./dialog/DialogAddColumns.js";
import TilorswiftAddRowsClickedEvent from "./events/TilorswiftAddRowsClickedEvent.js";
import TilorswiftAddColumnsClickedEvent from "./events/TilorswiftAddColumnsClickedEvent.js";
import TilorswiftMenuNewTerrainClickedEvent from "./events/TilorswiftMenuNewTerrainClickedEvent.js";
import DialogNewTerrain from "./dialog/DialogNewTerrain.js";
import TargetPointWidget from "./menu/TargetPointWidget.js";
import GraphicSet from "../../js/GraphicSet.js";
import Setting from "../../js/Setting.js";
import Level from "../../js/Level.js";
import TilorswiftMenuGravityClickedEvent from "./events/TilorswiftMenuGravityClickedEvent.js";
import DialogGravity from "./dialog/DialogGravity.js";
const imageLoader = new ImageLoader();
let level = Level.createFromFile('../levels/moonbase.json');
for (const graphicSet of GraphicSet) {
imageLoader.addImage('../' + Setting.TILESET_LOCATION + graphicSet.tileset);
if (GraphicSet[level.terrain.tileset.setId].backgroundImage !== null) {
document.body.style.backgroundImage = 'url("../' + Setting.GRAPHICS_LOCATION + GraphicSet[level.getTilesetId()].backgroundImage + '")';
}
imageLoader.onLoad = () => {
Level.createFromFile(
'../levels/moonbase.json',
(level) => {
const tilorswift = new Tilorswift(level);
tilorswift.loadLevel();
tilorswift.init();
let image = new Image();
image.src = '../' + Setting.TILESET_LOCATION + GraphicSet[level.terrain.tileset.setId].tileset;
image.onload = function () {
document.body.style.backgroundColor = GraphicSet[level.terrain.tileset.setId].backgroundColor;
let map = document.getElementById('map');
map.appendChild(level.terrain.getElement());
let brush = new Brush();
let tileset = new Tileset(level.terrain.tileset.setId);
let widgetBar = new WidgetBar('widget-bar');
let tilesetPicker = new TilesetPickerWidget(tileset, brush);
widgetBar.addWidget(tilesetPicker);
let entrancePicker = new EntrancePointWidget(widgetBar, brush);
widgetBar.addWidget(entrancePicker);
let targetPicker = new TargetPointWidget(widgetBar, brush);
widgetBar.addWidget(targetPicker);
document.body.appendChild(widgetBar.getElement());
let mouse = new Mouse();
let mainbar = new MainMenu('mainbar');
let menuFile = new MenuGroup('Datei');
menuFile.addMenuEntry(new MainMenuEntry('Neu...', TilorswiftMenuNewTerrainClickedEvent));
menuFile.addMenuEntry(new MainMenuEntry('Speichern...', TilorswiftMenuSaveClickedEvent));
mainbar.addMenuGroup(menuFile);
let menuEdit = new MenuGroup('Bearbeiten');
menuEdit.addMenuEntry(new MainMenuEntry('Zeilen einfügen...', TilorswiftAddRowsClickedEvent));
menuEdit.addMenuEntry(new MainMenuEntry('Spalten einfügen...', TilorswiftAddColumnsClickedEvent));
mainbar.addMenuGroup(menuEdit);
let menuLevel = new MenuGroup('Level');
menuLevel.addMenuEntry(new MainMenuEntry('Gravitation...', TilorswiftMenuGravityClickedEvent));
mainbar.addMenuGroup(menuLevel);
document.body.appendChild(mainbar.getElement());
window.addEventListener(
TilorswiftEvent.FIELD_CLICKED,
(event) => {
if (brush.mode === BrushMode.TERRAIN && !event.getField().isEntrancePoint) {
switch (event.button) {
case 0:
event.getField().setIndex(level.terrain.brushTileIndex);
break;
case 2:
event.getField().setIndex(-1);
break;
}
} else if (brush.mode === BrushMode.ENTRANCE) {
if (event.getField().index === -1) {
let coordinates = level.terrain.getFieldCoordinates(event.getField());
level.terrain.setEntrancePoint(coordinates.x, coordinates.y);
brush.mode = BrushMode.TERRAIN;
widgetBar.enableWidgets();
}
} else if (brush.mode === BrushMode.EXIT) {
if (event.getField().index === -1) {
let coordinates = level.terrain.getFieldCoordinates(event.getField());
level.terrain.setTargetPoint(coordinates.x, coordinates.y);
brush.mode = BrushMode.TERRAIN;
widgetBar.enableWidgets();
}
}
}
);
}
imageLoader.load();
window.addEventListener(
'contextmenu',
(event) => {
event.preventDefault();
}
);
window.addEventListener(
TilorswiftEvent.FIELD_ENTERED,
(event) => {
if (mouse.isPressedLeft) {
event.getField().setIndex(level.terrain.brushTileIndex);
} else if (mouse.isPressedRight) {
event.getField().setIndex(-1);
}
}
);
window.addEventListener(
TilorswiftEvent.NEW_TERRAIN_CLICKED,
() => {
new DialogNewTerrain();
}
);
window.addEventListener(
TilorswiftEvent.MENU_GRAVITY_CLICKED,
() => {
new DialogGravity(level.gravity);
}
);
window.addEventListener(
TilorswiftEvent.ADD_ROWS_CLICKED,
() => {
new DialogAddRows();
}
);
window.addEventListener(
TilorswiftEvent.ADD_COLUMNS_CLICKED,
() => {
new DialogAddColumns();
}
);
window.addEventListener(
TilorswiftEvent.GRAVITY_UPDATED,
(event) => {
level.gravity = event.gravity;
}
);
window.addEventListener(
TilorswiftEvent.ADD_ROWS,
function (event) {
level.terrain.addRows(event.beforeRow, event.rowCount);
}
);
window.addEventListener(
TilorswiftEvent.ADD_COLUMNS,
function (event) {
level.terrain.addColumns(event.beforeColumn, event.columnCount);
}
);
window.addEventListener(
TilorswiftEvent.NEW_TERRAIN,
(event) => {
let tileset = new Tileset(event.tilesetIndex);
level.terrain = new Terrain(tileset, event.tilesX, event.tilesY, GraphicSet[event.tilesetIndex].backgroundColor);
document.body.style.backgroundColor = level.getBackgroundColor();
if (GraphicSet[event.tilesetIndex].backgroundImage !== null) {
document.body.style.backgroundImage = 'url("../' + Setting.GRAPHICS_LOCATION + GraphicSet[event.tilesetIndex].backgroundImage + '")';
} else {
document.body.style.backgroundImage = 'none';
}
map.innerHTML = '';
map.appendChild(level.terrain.getElement());
tilesetPicker.reloadTileset(tileset);
}
);
/* Prevents Firefox's annoying default drag and drop behavior for images */
document.addEventListener(
'dragstart',
function (event) {
event.preventDefault();
}
);
window.addEventListener(
TilorswiftEvent.MENU_SAVE_CLICKED,
function () {
if (Tilorswift.saveLevelToFile(level)) {
window.dispatchEvent(new TilorswiftSavedEvent());
}
}
);
};

View File

@ -3,16 +3,6 @@
to { width: 512px; }
}
@keyframes switch-toggle-on {
from {left: 0}
to {left: 50%}
}
@keyframes switch-toggle-off {
from {left: 50%}
to {left: 0}
}
body {
padding: 0;
margin: 0;
@ -122,9 +112,6 @@ body {
top: 0;
background-color: #cccccc;
box-shadow: 20px 20px 20px rgba(0, 0, 0, 0.5);
max-width: 1000%;
max-height: 500%;
overflow: auto;
}
#tileset-picker:hover > #tileset-selector-widget {
@ -249,10 +236,6 @@ body {
margin-bottom: 20px;
}
input[type="file"] {
margin-bottom: 20px;
}
.dialog-button {
padding: 5px 20px;
background-color: grey;
@ -294,7 +277,7 @@ input[type="file"] {
}
.tileset-thumbnail {
display: block;
display: table-cell;
width: 32px;
height: 32px;
background-size: auto 100%;
@ -309,34 +292,8 @@ input[type="file"] {
padding: 10px;
}
.switch {
position: relative;
border-radius: 16px;
border: 2px solid #333333;
width: 100%;
height: 32px;
cursor: pointer;
background-color: #777777;
}
.switch-slider {
position: absolute;
border-radius: 14px;
width: 50%;
height: 100%;
border: 1px solid white;
}
.switch-slider-on {
left: 50%;
background-color: #2222aa;
animation-name: switch-toggle-on;
animation-duration: 0.2s;
}
.switch-slider-off {
left: 0;
background-color: #888888;
animation-name: switch-toggle-off;
animation-duration: 0.2s;
/*
tr:hover > td > .selection {
opacity: 0.5;
}
*/