Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
83c1ae8119 | |||
e476e689e1 | |||
2fe9b63c70 | |||
598dbc67ac | |||
46c584d9ee |
@ -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
|
||||
}
|
||||
]
|
||||
]
|
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 106 KiB |
@ -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>
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
}
|
252
js/Game.js
@ -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;
|
||||
}
|
||||
}
|
10
js/Gisela.js
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
49
js/Level.js
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
13
js/MrCroc.js
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 83 KiB |
@ -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 = [];
|
||||
}
|
||||
}
|
9
js/events/FrameRateMeasuredEvent.js
Normal 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;
|
||||
}
|
||||
}
|
299
js/module.js
@ -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);
|
||||
}
|
||||
);
|
||||
|
@ -62,5 +62,4 @@ export default class RetroAnimation extends RetroSprite
|
||||
|
||||
this.isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
15113
levels/darius.json
@ -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]]}
|
@ -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 ]
|
||||
]
|
||||
}
|
||||
}
|
@ -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]]}
|
@ -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"]}
|
@ -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]]}
|
Before Width: | Height: | Size: 4.2 KiB |
@ -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>
|
@ -5,6 +5,5 @@ export default class Brush
|
||||
constructor()
|
||||
{
|
||||
this.mode = BrushMode.TERRAIN;
|
||||
this.isIntelligent = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import TilorswiftEvent from "./TilorswiftEvent.js";
|
||||
|
||||
export default class TilorswiftEffectsUpdatedEvent extends Event
|
||||
{
|
||||
constructor(effectNames) {
|
||||
super(TilorswiftEvent.EFFECTS_UPDATED);
|
||||
this.effectNames = effectNames;
|
||||
}
|
||||
}
|
@ -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;
|
@ -1,9 +0,0 @@
|
||||
import TilorswiftEvent from "./TilorswiftEvent.js";
|
||||
|
||||
export default class TilorswiftMenuEffectsClickedEvent extends Event
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
super(TilorswiftEvent.MENU_EFFECTS_CLICKED);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import TilorswiftEvent from "./TilorswiftEvent.js";
|
||||
|
||||
export class TilorswiftMenuOpenCLickedEvent extends Event
|
||||
{
|
||||
constructor() {
|
||||
super(TilorswiftEvent.MENU_OPEN_CLICKED);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
*/
|