Compare commits

..

5 Commits

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

View File

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

View File

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

84
js/FrameRateMeasurer.js Normal file
View File

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

View File

@ -1,242 +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);
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;
window.requestAnimationFrame(loopFunction);
}
isChromeBrowser()
{
return navigator.userAgent.match('Chrome') !== null;
}
}

View File

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

View File

@ -5,10 +5,7 @@ let GraphicSet = [
tiles: 8, tiles: 8,
scale: 3, scale: 3,
backgroundColor: '#6096ff', backgroundColor: '#6096ff',
backgroundImage: null, backgroundImage: null
tilePreview: 5,
primaryTiles: 8,
gravity: 9.806,
}, },
{ {
name: 'Moon', name: 'Moon',
@ -16,44 +13,8 @@ let GraphicSet = [
tiles: 2, tiles: 2,
scale: 3, scale: 3,
backgroundColor: 'black', backgroundColor: 'black',
backgroundImage: 'background_earth.jpg', 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,
}
]; ];
export default GraphicSet; export default GraphicSet;

View File

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

View File

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

View File

@ -3,8 +3,6 @@ import Terrain from "../tilorswift/js/Terrain.js";
export default class Level export default class Level
{ {
static FACTOR_GRAVITY = 4.903;
constructor(terrain) constructor(terrain)
{ {
this.terrain = terrain; this.terrain = terrain;
@ -76,27 +74,14 @@ export default class Level
this.gravity = gravity; this.gravity = gravity;
} }
static createFromFile(filename, callback = () => {}) static createFromFile(filename)
{ {
let loader = new FileLoader(filename); let loader = new FileLoader(filename);
loader.onLoad = (data) => { let levelData = JSON.parse(loader.getContent());
const json = JSON.parse(data); let terrain = Terrain.createFromJson(levelData);
const level = new Level(Terrain.createFromJson(json)); let level = new Level(terrain);
level.setGravity(json.gravity / Level.FACTOR_GRAVITY); level.setGravity(levelData.gravity);
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);
return level; return level;
} }
} }

View File

@ -23,4 +23,4 @@ export default class MrCroc extends Movable
this.playAnimation('WALK_LEFT', timestamp); this.playAnimation('WALK_LEFT', timestamp);
super.moveLeft(delta); super.moveLeft(delta);
} }
} }

View File

@ -44,15 +44,15 @@ export default class UrlParam
getInt(name) 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) getFloat(name)
{ {
const value = parseFloat(this.get(name)); let value = parseFloat(this.get(name));
return isNaN(value) ? 0.0 : value; return isNaN(value) ? undefined : value;
} }
} }

View File

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

View File

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

View File

@ -1,83 +1,147 @@
'use strict'; '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 Setting from "./Setting.js";
import FrameRateMeasurer from "./FrameRateMeasurer.js";
import GraphicSet from "./GraphicSet.js"; import GraphicSet from "./GraphicSet.js";
import ImageLoader from "./ImageLoader.js"; import ImageLoader from "./ImageLoader.js";
import Level from "./Level.js"; import Level from "./Level.js";
import InterfaceEvent from "./events/InterfaceEvent.js";
import UrlParam from "./UrlParam.js"; import UrlParam from "./UrlParam.js";
import {LoadLevelDialog} from "./ui/LoadLevelDialog.js"; import UserInterface from "./ui/UserInterface.js";
import {EventBus} from "./events/EventBus.js"; import TextMessageGisela from "./ui/TextMessageGisela.js";
import {Game} from "./Game.js"; import TextMessageMrCroc from "./ui/TextMessageMrCroc.js";
function MainLoop(timestamp)
function mainLoop(timestamp)
{ {
if (game.isPaused) { if (lastRendered === undefined && lastTimestamp === undefined) {
return; lastRendered = timestamp;
lastTimestamp = timestamp;
} }
if (game.lastRendered === undefined && game.lastTimestamp === undefined) { let delta = (timestamp - lastTimestamp) / (10 / GAME_SPEED);
game.lastRendered = timestamp;
game.lastTimestamp = timestamp;
}
let delta = (timestamp - game.lastTimestamp) / (10 / Game.GAME_SPEED); let ceilingHeight = Math.max(
architecture.getCeilingHeight(mrCroc.getPositionHeadLeft()),
game.handlePhysics(delta, timestamp); architecture.getCeilingHeight(mrCroc.getPositionHeadRight()),
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();
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 + '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 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 = [ const LEVEL = [
@ -86,17 +150,93 @@ const LEVEL = [
'moonbase.json', 'moonbase.json',
'terrain8.json', 'terrain8.json',
'darius.json', 'darius.json',
'imperial-prison.json',
]; ];
let game; let urlGetter = new UrlParam();
const urlGetter = new UrlParam(); let levelIndex = urlGetter.getInt('level');
const levelIndex = urlGetter.getInt('level');
Level.createFromFile( if (levelIndex === undefined || levelIndex < 0 || levelIndex >= LEVEL.length) {
Setting.LEVELS_LOCATION + LEVEL[levelIndex % LEVEL.length], levelIndex = 0;
(level) => { }
loadLevel(level);
let level = Level.createFromFile(Setting.LEVELS_LOCATION + LEVEL[levelIndex]);
const GAME_SPEED = 1;
const GRAVITY = level.gravity;
let fps = 120;
const browser = navigator.userAgent.indexOf('Firefox') === -1 ? 'Chrome' : 'Firefox';
let frameDuration;
let lastRendered = undefined;
let lastTimestamp = undefined;
let context;
let mrCroc, gisela, architecture;
let camera = new Camera();
let gameFinished = false;
let hasPlayerLeftArchitecture = false;
let textBoxGameStart;
let textBoxGameFinished;
let userInterface = new UserInterface();
let KeyLeft = new Key('ArrowLeft');
let KeyRight = new Key('ArrowRight');
let KeyJump = new Key('Space');
let loader = new ImageLoader();
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png');
loader.addImage(Setting.TILESET_LOCATION + GraphicSet[level.getTilesetId()].tileset);
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png');
loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-left.png');
window.addEventListener(
'imagesloaded',
() => {
let canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.backgroundAttachment = 'fixed';
canvas.style.backgroundSize = 'cover';
canvas.style.backgroundPosition = 'center center';
if (GraphicSet[level.getTilesetId()].backgroundImage !== null) {
canvas.style.backgroundImage = 'url("' + Setting.GRAPHICS_LOCATION + GraphicSet[level.getTilesetId()].backgroundImage +'")';
}
canvas.style.backgroundColor = level.getBackgroundColor();
window.addEventListener(
'resize',
function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
);
context = canvas.getContext('2d');
textBoxGameFinished = new TextMessageGisela(
'Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."',
context
);
textBoxGameStart = new TextMessageMrCroc('Mr. Croc: "Where is Gisela? I have to find her!"', context);
textBoxGameStart.animate(75, 1000);
textBoxGameStart.show(1000);
textBoxGameStart.hide(10000);
userInterface.addTextBox(textBoxGameStart);
architecture = RetroArchitecture.createFromData(level);
camera.borderRight = architecture.columns * architecture.tileWidth;
camera.borderBottom = architecture.rows * architecture.tileHeight;
mrCroc = new MrCroc();
architecture.setMovableToStartPosition(mrCroc);
gisela = new Gisela();
architecture.setMovableToTargetPosition(gisela);
frameDuration = 1000 / fps;
window.requestAnimationFrame(MainLoop);
} }
); );

View File

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

View File

@ -5,6 +5,7 @@ import GeometryPoint from "../geometry/GeometryPoint.js";
import GeometryRect from "../geometry/GeometryRect.js"; import GeometryRect from "../geometry/GeometryRect.js";
import GraphicSet from "../GraphicSet.js"; import GraphicSet from "../GraphicSet.js";
import Setting from "../Setting.js"; import Setting from "../Setting.js";
import Camera from "../Camera.js";
export default class RetroArchitecture export default class RetroArchitecture
{ {
@ -19,6 +20,10 @@ export default class RetroArchitecture
this.matrix = []; this.matrix = [];
this.tileWidth = this.tilesetSprite.getWidth() / this.tiles; this.tileWidth = this.tilesetSprite.getWidth() / this.tiles;
this.tileHeight = this.tilesetSprite.getHeight(); 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.startX = 0;
this.startY = 0; this.startY = 0;
this.targetX = 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) setBackgroundColor(color)
{ {
this.backgroundColor = color; this.backgroundColor = color;
@ -202,7 +224,7 @@ export default class RetroArchitecture
tileRect.isContainingPoint(movable.getPositionFootRight()); 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 viewX = parseInt(Math.floor(Math.max(0, camera.position.x) / this.tileWidth));
const viewWidth = parseInt(Math.min(Math.ceil(camera.width), this.columns)); 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 y = viewY; y < viewHeight; y++) {
for (let x = viewX; x < viewWidth; x++) { for (let x = viewX; x < viewWidth; x++) {
let field = this.matrix[y][x]; const field = this.matrix[y][x];
if (field !== null) { if (field !== null) {
this.drawField(context, x, y, camera, field); 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) drawField(context, x, y, camera, field)
{ {
context.drawImage( context.drawImage(
this.tilesetSprite.canvas, this.tilesetSprite.canvas,
(field.tile.index % this.tiles) * this.tileWidth, field.tile.index * this.tileWidth,
0, 0,
this.tileWidth, this.tileWidth,
this.tileHeight, this.tileHeight,
x * this.tileWidth - camera.position.x - 1, x * this.tileWidth - camera.position.x,
y * this.tileHeight - camera.position.y - 1, y * this.tileHeight - camera.position.y,
this.tileWidth + 1, this.tileWidth + 1,
this.tileHeight + 1 this.tileHeight + 1
); );
} }
getStartPosition()
{
return new GeometryPoint(this.startX * this.tileWidth, this.startY * this.tileHeight);
}
static createFromData(level) static createFromData(level)
{ {
let graphicSet = GraphicSet[level.getTilesetId()]; let graphicSet = GraphicSet[level.getTilesetId()];
@ -279,6 +316,8 @@ export default class RetroArchitecture
} }
} }
architecture.render();
return architecture; return architecture;
} }
} }

View File

@ -82,7 +82,7 @@ export default class RetroSprite
canvasTemp.width = this.image.width * this.scale; canvasTemp.width = this.image.width * this.scale;
canvasTemp.height = this.image.height * 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); contextTemp.drawImage(this.image, 0, 0);
this.canvas.width = this.image.width * this.scale; this.canvas.width = this.image.width * this.scale;
@ -99,4 +99,4 @@ export default class RetroSprite
} }
} }
} }
} }

View File

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

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

@ -3,7 +3,7 @@
"rows": 10, "rows": 10,
"columns": 17, "columns": 17,
"backgroundColor": "#6096ff", "backgroundColor": "#6096ff",
"gravity": 9.806, "gravity": 2.0,
"matrix": [ "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 ],
[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 ,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 ] [4 ,4 ,4 ,4 ,4 ,0 ,4 ,4 ,4 ,0 ,0 ,4 ,4 ,4 ,4 ,4 ,4 ]
] ]
} }

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -4,10 +4,9 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Tilorswift</title> <title>Tilorswift</title>
<link rel="stylesheet" type="text/css" href="style.css"> <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"></script>
<script type="module" src="js/module.js" defer></script>
</head> </head>
<body> <body>
<div id="map"></div> <div id="map"></div>
</body> </body>
</html> </html>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,156 +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 TilorswiftEvent from "./events/TilorswiftEvent.js";
import BrushMode from "./BrushMode.js";
import DialogNewTerrain from "./dialog/DialogNewTerrain.js";
import DialogGravity from "./dialog/DialogGravity.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";
export default class Tilorswift export default class Tilorswift
{ {
constructor(level) { static getLevelAsJson(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));
this.mainbar.addMenuGroup(menuLevel);
document.body.appendChild(this.mainbar.getElement());
this.addEventListeners();
}
getLevelAsJson()
{ {
let matrix = []; 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 = []; let row = [];
for (let x = 0; x < this.level.terrain.fields[y].length; x++) { for (let x = 0; x < level.terrain.fields[y].length; x++) {
row.push(this.level.terrain.fields[y][x].index); row.push(level.terrain.fields[y][x].index);
} }
matrix.push(row); matrix.push(row);
} }
let data = { let data = {
tileset: this.level.getTilesetId(), tileset: level.getTilesetId(),
rows: this.level.getRows(), rows: level.getRows(),
columns: this.level.getColumns(), columns: level.getColumns(),
startX: this.level.getStartX(), startX: level.getStartX(),
startY: this.level.getStartY(), startY: level.getStartY(),
targetX: this.level.getTargetX(), targetX: level.getTargetX(),
targetY: this.level.getTargetY(), targetY: level.getTargetY(),
gravity: this.level.gravity, gravity: level.gravity,
matrix: matrix, matrix: matrix,
}; };
return JSON.stringify(data); return JSON.stringify(data);
} }
openLevelFromFile() static saveLevelToFile(level)
{ {
const dialog = new LoadLevelDialog(); if (!level.hasEntrancePoint()) {
dialog.onLoad = (json) => {
this.tileset = new Tileset(JSON.parse(json).tileset);
this.level = Level.createFromJson(json);
this.loadLevel();
dialog.close();
}
dialog.openFileBrowser();
}
loadLevel()
{
this.tileset = new Tileset(this.level.terrain.tileset.setId);
document.body.style.backgroundColor = this.level.getBackgroundColor();
if (GraphicSet[this.level.terrain.tileset.setId].backgroundImage !== null) {
document.body.style.backgroundImage = 'url("../' + Setting.GRAPHICS_LOCATION + GraphicSet[this.level.terrain.tileset.setId].backgroundImage + '")';
} else {
document.body.style.backgroundImage = 'none';
}
this.map.innerHTML = '';
this.map.appendChild(this.level.terrain.getElement());
this.tilesetPicker.reloadTileset(this.tileset);
this.initializeIntelligentBrushWidget();
}
saveLevelToFile()
{
if (!this.level.hasEntrancePoint()) {
alert('Es muss ein Startpunkt definiert sein!'); alert('Es muss ein Startpunkt definiert sein!');
return false; return false;
} }
if (!this.level.hasTargetPoint()) { if (!level.hasTargetPoint()) {
alert('Es muss ein Zielpunkt definiert sein!'); alert('Es muss ein Zielpunkt definiert sein!');
return false; return false;
} }
const filename = prompt('Dateiname', 'terrain.json'); let filename = prompt('Dateiname', 'terrain.json');
if (filename === null) { if (filename === null) {
return false; return false;
} }
const json = this.getLevelAsJson(level); let json = Tilorswift.getLevelAsJson(level);
const download = document.createElement('a'); let download = document.createElement('a');
download.setAttribute('download', filename); download.setAttribute('download', filename);
download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json)); download.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json));
@ -159,208 +57,4 @@ export default class Tilorswift
return true; 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.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.ADD_ROWS,
(event) => {
this.level.terrain.addRows(event.beforeRow, event.rowCount);
}
);
window.addEventListener(
TilorswiftEvent.ADD_COLUMNS,
(event) => {
this.level.terrain.addColumns(event.beforeColumn, event.columnCount);
}
);
window.addEventListener(
TilorswiftEvent.NEW_TERRAIN,
(event) => {
this.createNewTerrain(event.tilesetIndex, event.tilesX, event.tilesY);
}
);
/* Prevents Firefox's annoying default drag and drop behavior for images */
document.addEventListener(
'dragstart',
(event) => {
event.preventDefault();
}
);
window.addEventListener(
TilorswiftEvent.MENU_OPEN_CLICKED,
() => {
this.openLevelFromFile();
}
);
window.addEventListener(
TilorswiftEvent.MENU_SAVE_CLICKED,
() => {
if (this.saveLevelToFile()) {
window.dispatchEvent(new TilorswiftSavedEvent());
}
}
);
}
}

View File

@ -100,12 +100,7 @@ export default class Dialog
let htmlThumbnail = document.createElement('div'); let htmlThumbnail = document.createElement('div');
htmlThumbnail.classList.add('tileset-thumbnail'); htmlThumbnail.classList.add('tileset-thumbnail');
htmlThumbnail.style.backgroundImage = 'url("../' + Setting.TILESET_LOCATION + graphicSet.tileset + '")';
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';
htmlTilesetElement.appendChild(htmlThumbnail); htmlTilesetElement.appendChild(htmlThumbnail);
let htmlTitleElement = document.createElement('div'); let htmlTitleElement = document.createElement('div');
@ -117,9 +112,7 @@ export default class Dialog
'click', 'click',
() => { () => {
htmlListElement.style.display = 'none'; htmlListElement.style.display = 'none';
htmlAvatarElement.style.backgroundImage = 'url(' + image.src + ')'; htmlAvatarElement.style.backgroundImage = 'url("../' + Setting.TILESET_LOCATION + GraphicSet[index].tileset + '")';
htmlAvatarElement.style.backgroundPositionX = -96 * graphicSet.tilePreview + 'px';
window.dispatchEvent(new TilorswiftTilesetSelectedEvent(index)); window.dispatchEvent(new TilorswiftTilesetSelectedEvent(index));
} }
); );
@ -133,31 +126,8 @@ export default class Dialog
return htmlElement; 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) setMessage(message)
{ {
this.messageElement.innerText = message; this.messageElement.innerText = message;
} }
close()
{
this.htmlElement.remove();
}
} }

View File

@ -7,7 +7,7 @@ export default class DialogGravity extends Dialog
{ {
super(); super();
this.setMessage('Gravitation einstellen'); 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.createButton('Abbrechen');
this.buttonOk = this.createButton('OK'); this.buttonOk = this.createButton('OK');
this.buttonOk.addEventListener( this.buttonOk.addEventListener(
@ -19,4 +19,4 @@ export default class DialogGravity extends Dialog
} }
) )
} }
} }

View File

@ -3,7 +3,6 @@ const TilorswiftEvent = {
FIELD_ENTERED: 'fieldEntered', FIELD_ENTERED: 'fieldEntered',
BUTTON_TILE_CLICKED: 'buttonTileClicked', BUTTON_TILE_CLICKED: 'buttonTileClicked',
MENU_SAVE_CLICKED: 'menuSaveClicked', MENU_SAVE_CLICKED: 'menuSaveClicked',
MENU_OPEN_CLICKED: 'menuOpenClicked',
DIALOG_BUTTON_OK_CLICKED: 'dialogButtonOkClicked', DIALOG_BUTTON_OK_CLICKED: 'dialogButtonOkClicked',
MENU_EDIT_CLICKED: 'menuEditClicked', MENU_EDIT_CLICKED: 'menuEditClicked',
SAVED: 'saved', SAVED: 'saved',
@ -19,4 +18,4 @@ const TilorswiftEvent = {
GRAVITY_UPDATED: 'gravityUpdated', GRAVITY_UPDATED: 'gravityUpdated',
}; };
export default TilorswiftEvent; export default TilorswiftEvent;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,16 +3,6 @@
to { width: 512px; } to { width: 512px; }
} }
@keyframes switch-toggle-on {
from {left: 0}
to {left: 50%}
}
@keyframes switch-toggle-off {
from {left: 50%}
to {left: 0}
}
body { body {
padding: 0; padding: 0;
margin: 0; margin: 0;
@ -122,9 +112,6 @@ body {
top: 0; top: 0;
background-color: #cccccc; background-color: #cccccc;
box-shadow: 20px 20px 20px rgba(0, 0, 0, 0.5); 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 { #tileset-picker:hover > #tileset-selector-widget {
@ -249,10 +236,6 @@ body {
margin-bottom: 20px; margin-bottom: 20px;
} }
input[type="file"] {
margin-bottom: 20px;
}
.dialog-button { .dialog-button {
padding: 5px 20px; padding: 5px 20px;
background-color: grey; background-color: grey;
@ -294,7 +277,7 @@ input[type="file"] {
} }
.tileset-thumbnail { .tileset-thumbnail {
display: block; display: table-cell;
width: 32px; width: 32px;
height: 32px; height: 32px;
background-size: auto 100%; background-size: auto 100%;
@ -309,34 +292,8 @@ input[type="file"] {
padding: 10px; padding: 10px;
} }
.switch { /*
position: relative; tr:hover > td > .selection {
border-radius: 16px; opacity: 0.5;
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;
} }
*/