Walkable mask painting

This commit is contained in:
Ian Gulliver
2021-05-17 04:26:18 +00:00
parent 0030b63e3a
commit 9d681291cc
43 changed files with 577 additions and 362 deletions

View File

@@ -1,10 +1,11 @@
import { Mask } from './mask.js';
import { Tile } from './tile.js';
export abstract class AnimatableTile extends Tile {
animations: Map<string, [Keyframe[], object]>;
constructor(width: number, height: number, animations: Map<string, [Keyframe[], object]>) {
super(width, height);
constructor(width: number, height: number, masks: Map<string, Mask>, animations: Map<string, [Keyframe[], object]>) {
super(width, height, masks);
this.animations = animations;
}

View File

@@ -1,3 +1,4 @@
import { Mask } from './mask.js';
import { TileFactory } from './tile_factory.js';
export abstract class AnimatableTileFactory extends TileFactory {
@@ -7,5 +8,12 @@ export abstract class AnimatableTileFactory extends TileFactory {
this.animations.set(name, [keyframes, options]);
}
animatable_tile_args(): [number, number, Map<string, Mask>, Map<string, [Keyframe[], object]>] {
return [
...super.tile_args(),
this.animations,
];
}
abstract copy(): AnimatableTileFactory;
}

View File

@@ -1,53 +1,28 @@
import { Layer } from './layer.js';
import { Mask } from './mask.js';
import { Tile } from './tile.js';
import { TileFactory } from './tile_factory.js';
export class Grid {
prnt: HTMLElement;
tileset: string;
layers: Map<string, Layer> = new Map<string, Layer>();
height: number;
masks: Map<string, Mask> = new Map<string, Mask>();
constructor(prnt: HTMLElement) {
constructor(prnt: HTMLElement, width: number, height: number, tileset: string, layers: string[], masks: string[]) {
this.prnt = prnt;
this.prnt.style.display = 'grid';
}
this.prnt.style.gridTemplateColumns = `repeat(${width}, 1fr)`;
this.prnt.style.gridTemplateRows = `repeat(${height}, 1fr)`;
this.prnt.style.backgroundImage = `url("images/${tileset}/land.svg")`;
set_size(x: number, y: number) {
this.height = y;
this.prnt.style.gridTemplateColumns = `repeat(${x}, 1fr)`;
this.prnt.style.gridTemplateRows = `repeat(${y}, 1fr)`;
}
set_tileset(set: string) {
this.tileset = set;
this.prnt.style.backgroundImage = `url("images/${this.tileset}/land.svg")`;
// TODO: Notify layers
}
set_layers(layers: string[]) {
const newNames: Set<string> = new Set<string>(layers);
for (const name of newNames) {
if (!this.layers.has(name)) {
const layer = new Layer();
layer.set_tileset(this.tileset);
this.layers.set(name, layer);
}
for (let i = 0; i <= layers.length; i++) {
const name = layers[i];
this.layers.set(name, new Layer(i * height, tileset));
}
for (const name of this.layers.keys()) {
if (!newNames.has(name)) {
// TODO: Notify layer to tear down
this.layers.delete(name);
}
}
for (let i = 0; i < layers.length; i++) {
const layer = this.layers.get(layers[i])!;
layer.set_level(i * this.height);
for (const name of masks) {
this.masks.set(name, new Mask(width, height));
}
}
@@ -59,6 +34,10 @@ export class Grid {
tile.elem.style.gridRowStart = `${y + 1}`;
this.prnt.appendChild(tile.elem);
for (const [name, mask] of tile.masks) {
this.masks.get(name)!.update(x, y, mask);
}
return tile;
}
}

View File

@@ -5,11 +5,8 @@ export class Layer {
level: number;
tileset: string;
set_level(level: number) {
constructor(level: number, tileset: string) {
this.level = level;
}
set_tileset(tileset: string) {
this.tileset = tileset;
}

View File

@@ -1,10 +1,11 @@
import { Mask } from './mask.js';
import { Tile } from './tile.js';
export class LayeredTile extends Tile {
tiles: Tile[];
constructor(width: number, height: number, tiles: Tile[]) {
super(width, height);
constructor(width: number, height: number, masks: Map<string, Mask>, tiles: Tile[]) {
super(width, height, masks);
this.tiles = [];
this.elem.style.position = 'relative';

View File

@@ -20,7 +20,7 @@ export class LayeredTileFactory extends TileFactory {
tiles.push(tile_factory.build(tileset));
}
return new LayeredTile(this.width, this.height, tiles);
return new LayeredTile(...this.tile_args(), tiles);
}
copy(): LayeredTileFactory {

View File

@@ -1,9 +1,10 @@
import { AnimatableTile } from './animatable_tile.js';
import { Mask } from './mask.js';
import { Tile } from './tile.js';
export class SequenceTile extends AnimatableTile {
constructor(width: number, height: number, animations: Map<string, [Keyframe[], object]>, tiles: Tile[], delay: number, repeat: boolean) {
super(width, height, animations);
constructor(width: number, height: number, masks: Map<string, Mask>, animations: Map<string, [Keyframe[], object]>, tiles: Tile[], delay: number, repeat: boolean) {
super(width, height, masks, animations);
this.elem.style.position = 'relative';

View File

@@ -25,7 +25,7 @@ export class SequenceTileFactory extends AnimatableTileFactory {
tiles.push(tile_factory.build(tileset));
}
return new SequenceTile(this.width, this.height, this.animations, tiles, this.delay, this.repeat);
return new SequenceTile(...this.animatable_tile_args(), tiles, this.delay, this.repeat);
}
copy(): SequenceTileFactory {

View File

@@ -1,8 +1,9 @@
import { AnimatableTile } from './animatable_tile.js';
import { Mask } from './mask.js';
export class SimpleTile extends AnimatableTile {
constructor(width: number, height: number, image_url: string, animations: Map<string, [Keyframe[], object]>) {
super(width, height, animations);
constructor(width: number, height: number, masks: Map<string, Mask>, animations: Map<string, [Keyframe[], object]>, image_url: string) {
super(width, height, masks, animations);
this.elem.style.backgroundImage = `url('${encodeURIComponent(image_url)}')`;
this.elem.style.backgroundSize = 'cover';

View File

@@ -11,10 +11,8 @@ export class SimpleTileFactory extends AnimatableTileFactory {
build(tileset: string): SimpleTile {
return new SimpleTile(
this.width,
this.height,
...this.animatable_tile_args(),
`images/${this.name.replace('{tileset}', tileset)}`,
this.animations,
);
}
@@ -26,28 +24,3 @@ export class SimpleTileFactory extends AnimatableTileFactory {
return stf;
}
}
/*
function string_to_mask(mask_string: string): boolean[][] {
// mask_string: '\n+++\n+++\n'
const rows = mask_string.trim().split('\n');
// rows: ['+++', '+++']
const mask = [];
for (let x = 0; x < rows[0].length; x++) {
mask[x] = Array(rows.length);
}
// mask: [ [ empty, empty ], [ empty, empty ], [ empty, empty ] ]
for (let y = 0; y < rows.length; y++) {
const row = rows[y];
for (let x = 0; x < row.length; x++) {
const cell = row[x];
mask[x][y] = (cell.toUpperCase() == 'X');
}
}
return mask;
}
*/

View File

@@ -1,10 +1,18 @@
import { Mask } from './mask.js';
export abstract class Tile {
elem: HTMLElement;
masks: Map<string, Mask>;
constructor(width: number, height: number, masks: Map<string, Mask>) {
this.masks = masks;
constructor(width: number, height: number) {
this.elem = document.createElement('div');
this.elem.style.gridColumnEnd = `span ${width}`;
this.elem.style.gridRowEnd = `span ${height}`;
// Hack to avoid floating point stitching gaps
this.elem.style.width = 'calc(100% + 1px)';
this.elem.style.height = 'calc(100% + 1px)';
}
abstract play(name: string): Animation | undefined;

View File

@@ -1,9 +1,11 @@
import { Mask } from './mask.js';
import { Tile } from './tile.js';
export abstract class TileFactory {
layer_name: string;
width: number;
height: number;
masks: Map<string, Mask> = new Map<string, Mask>();
constructor(layer_name: string, width: number, height: number) {
this.layer_name = layer_name;
@@ -11,6 +13,18 @@ export abstract class TileFactory {
this.height = height;
}
add_mask(name: string, mask: Mask) {
this.masks.set(name, mask);
}
tile_args(): [number, number, Map<string, Mask>] {
return [
this.width,
this.height,
this.masks,
];
}
abstract build(tileset: string): Tile;
abstract copy(): TileFactory;

View File

@@ -1,44 +1,152 @@
import { LayeredTileFactory } from './layered_tile_factory.js';
import { Mask } from './mask.js';
import { SequenceTileFactory } from './sequence_tile_factory.js';
import { SimpleTileFactory } from './simple_tile_factory.js';
// Straig
export const ROAD_LR = new SimpleTileFactory('road', 6, 4, '{tileset}/road-lr.svg');
export const ROAD_TB = new SimpleTileFactory('road', 4, 6, '{tileset}/road-tb.svg');
export const ROAD_LR = new SimpleTileFactory('road', 12, 8, '{tileset}/road-lr.svg');
ROAD_LR.add_mask('walkable', Mask.from_string(`
............
............
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXX
............
............
`));
export const ROAD_TB = new SimpleTileFactory('road', 8, 12, '{tileset}/road-tb.svg');
ROAD_TB.add_mask('walkable', Mask.from_string(`
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
..XXXX..
`));
// Elbow
export const ROAD_BL = new SimpleTileFactory('road', 6, 6, '{tileset}/road-bl.svg');
export const ROAD_BR = new SimpleTileFactory('road', 6, 6, '{tileset}/road-br.svg');
export const ROAD_TL = new SimpleTileFactory('road', 6, 6, '{tileset}/road-tl.svg');
export const ROAD_TR = new SimpleTileFactory('road', 6, 6, '{tileset}/road-tr.svg');
export const ROAD_BL = new SimpleTileFactory('road', 12, 12, '{tileset}/road-bl.svg');
ROAD_BL.add_mask('walkable', Mask.from_string(`
............
............
XXX.........
XXXXX.......
XXXXXXX.....
XXXXXXXX....
..XXXXXX....
....XXXXX...
.....XXXX...
.....XXXXX..
......XXXX..
......XXXX..
`));
export const ROAD_BR = new SimpleTileFactory('road', 12, 12, '{tileset}/road-br.svg');
ROAD_BR.add_mask('walkable', Mask.from_string(`
............
............
.........XXX
.......XXXXX
.....XXXXXXX
....XXXXXXXX
....XXXXXX..
...XXXXX....
...XXXX.....
..XXXXX.....
..XXXX......
..XXXX......
`));
export const ROAD_TL = new SimpleTileFactory('road', 12, 12, '{tileset}/road-tl.svg');
ROAD_TL.add_mask('walkable', Mask.from_string(`
......XXXX..
......XXXX..
.....XXXXX..
.....XXXX...
....XXXXX...
..XXXXXX....
XXXXXXXX....
XXXXXXX.....
XXXXX.......
XXX.........
............
............
`));
export const ROAD_TR = new SimpleTileFactory('road', 12, 12, '{tileset}/road-tr.svg');
ROAD_TR.add_mask('walkable', Mask.from_string(`
..XXXX......
..XXXX......
..XXXXX.....
...XXXX.....
...XXXXX....
....XXXXXX..
....XXXXXXXX
.....XXXXXXX
.......XXXXX
.........XXX
............
............
`));
// T
export const ROAD_BLR = new SimpleTileFactory('road', 8, 6, '{tileset}/road-blr.svg');
export const ROAD_TLR = new SimpleTileFactory('road', 8, 6, '{tileset}/road-tlr.svg');
export const ROAD_LTB = new SimpleTileFactory('road', 6, 8, '{tileset}/road-ltb.svg');
export const ROAD_RTB = new SimpleTileFactory('road', 6, 8, '{tileset}/road-rtb.svg');
export const ROAD_BLR = new SimpleTileFactory('road', 16, 12, '{tileset}/road-blr.svg');
// TODO: add_mask(walkable)
export const ROAD_TLR = new SimpleTileFactory('road', 16, 12, '{tileset}/road-tlr.svg');
// TODO: add_mask(walkable)
export const ROAD_LTB = new SimpleTileFactory('road', 12, 16, '{tileset}/road-ltb.svg');
// TODO: add_mask(walkable)
export const ROAD_RTB = new SimpleTileFactory('road', 12, 16, '{tileset}/road-rtb.svg');
// TODO: add_mask(walkable)
// +
export const ROAD_TBLR = new SimpleTileFactory('road', 8, 8, '{tileset}/road-tblr.svg');
export const ROAD_TBLR = new SimpleTileFactory('road', 16, 16, '{tileset}/road-tblr.svg');
ROAD_TBLR.add_mask('walkable', Mask.from_string(`
......XXXX......
......XXXX......
......XXXX......
.....XXXXXX.....
....XXXXXXXX....
...XXXXXXXXXX...
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
...XXXXXXXXXX...
....XXXXXXXX....
.....XXXXXX.....
......XXXX......
......XXXX......
......XXXX......
`));
// Tower base
export const EMPTY = new SimpleTileFactory('road', 4, 2, '{tileset}/empty.svg');
export const EMPTY = new SimpleTileFactory('road', 8, 4, '{tileset}/empty.svg');
// Straight
export const RIVER_LR = new SimpleTileFactory('water', 6, 4, '{tileset}/river-lr.svg');
export const RIVER_TB = new SimpleTileFactory('water', 4, 6, '{tileset}/river-tb.svg');
export const RIVER_LR = new SimpleTileFactory('water', 12, 8, '{tileset}/river-lr.svg');
export const RIVER_TB = new SimpleTileFactory('water', 8, 12, '{tileset}/river-tb.svg');
// Elbow
export const RIVER_BR = new SimpleTileFactory('water', 6, 6, '{tileset}/river-br.svg');
export const RIVER_BL = new SimpleTileFactory('water', 6, 6, '{tileset}/river-bl.svg');
export const RIVER_TR = new SimpleTileFactory('water', 6, 6, '{tileset}/river-tr.svg');
export const RIVER_TL = new SimpleTileFactory('water', 6, 6, '{tileset}/river-tl.svg');
export const RIVER_BR = new SimpleTileFactory('water', 12, 12, '{tileset}/river-br.svg');
export const RIVER_BL = new SimpleTileFactory('water', 12, 12, '{tileset}/river-bl.svg');
export const RIVER_TR = new SimpleTileFactory('water', 12, 12, '{tileset}/river-tr.svg');
export const RIVER_TL = new SimpleTileFactory('water', 12, 12, '{tileset}/river-tl.svg');
export const BRIDGE_LR = new SimpleTileFactory('bridge', 6, 4, '{tileset}/bridge-lr.svg');
export const BRIDGE_LR = new SimpleTileFactory('bridge', 12, 8, '{tileset}/bridge-lr.svg');
const tower_fireball1_back = new SimpleTileFactory('surface', 4, 4, 'tower/fireball1-back.svg');
const tower_fireball1 = new SimpleTileFactory('surface', 4, 4, 'tower/fireball1.svg');
const tower_fireball1_front = new SimpleTileFactory('surface', 4, 4, 'tower/fireball1-front.svg');
const tower_fireball1_back = new SimpleTileFactory('surface', 8, 8, 'tower/fireball1-back.svg');
const tower_fireball1 = new SimpleTileFactory('surface', 8, 8, 'tower/fireball1.svg');
const tower_fireball1_front = new SimpleTileFactory('surface', 8, 8, 'tower/fireball1-front.svg');
for (const tile_factory of [tower_fireball1_back, tower_fireball1_front]) {
tile_factory.add_animation(
@@ -75,20 +183,20 @@ export const TOWER_FIREBALL1 = new LayeredTileFactory([
tower_fireball1_front,
]);
export const FIREBALL = new SimpleTileFactory('projectile', 2, 2, 'tower/fireball.svg');
export const FIREBALL = new SimpleTileFactory('projectile', 4, 4, 'tower/fireball.svg');
export const FIREBALL_IMPACT = new SequenceTileFactory([
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact1.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact2.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact3.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact4.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact5.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact6.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact7.svg'),
new SimpleTileFactory('surface', 2, 2, 'tower/fireball-impact8.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact1.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact2.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact3.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact4.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact5.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact6.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact7.svg'),
new SimpleTileFactory('surface', 4, 4, 'tower/fireball-impact8.svg'),
], 50, false);
const greenaxe_axe = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/axe.svg');
const greenaxe_axe = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/axe.svg');
greenaxe_axe.add_animation(
'walk',
[
@@ -118,7 +226,7 @@ greenaxe_axe.add_animation(
},
);
const greenaxe_rightleg = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/rightleg.svg');
const greenaxe_rightleg = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/rightleg.svg');
greenaxe_rightleg.add_animation(
'walk',
[
@@ -148,7 +256,7 @@ greenaxe_rightleg.add_animation(
},
);
const greenaxe_leftleg = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/leftleg.svg');
const greenaxe_leftleg = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/leftleg.svg');
greenaxe_leftleg.add_animation(
'walk',
[
@@ -178,7 +286,7 @@ greenaxe_leftleg.add_animation(
},
);
const greenaxe_torso = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/torso.svg');
const greenaxe_torso = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/torso.svg');
greenaxe_torso.add_animation(
'walk',
[
@@ -208,7 +316,7 @@ greenaxe_torso.add_animation(
},
);
const greenaxe_head = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/head.svg');
const greenaxe_head = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/head.svg');
greenaxe_head.add_animation(
'walk',
[
@@ -238,7 +346,7 @@ greenaxe_head.add_animation(
},
);
const greenaxe_rightarm = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/rightarm.svg');
const greenaxe_rightarm = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/rightarm.svg');
greenaxe_rightarm.add_animation(
'walk',
[
@@ -268,7 +376,7 @@ greenaxe_rightarm.add_animation(
},
);
const greenaxe_leftarm = new SimpleTileFactory('surface', 3, 3, 'monster/greenaxe/leftarm.svg');
const greenaxe_leftarm = new SimpleTileFactory('surface', 6, 6, 'monster/greenaxe/leftarm.svg');
greenaxe_leftarm.add_animation(
'walk',
[

View File

@@ -22,83 +22,106 @@ export function main() {
real.style.top = 'calc((-8 / 70) * min(140vw, 175vh))';
real.style.left = 'calc((-10 / 70) * min(140vw, 175vh))';
const grid = new Grid(real);
grid.set_size(70, 56);
grid.set_tileset('wasteland');
grid.set_layers(['road', 'water', 'bridge', 'surface', 'projectile']);
const grid = new Grid(
real,
140, 112,
'wasteland',
['road', 'water', 'bridge', 'surface', 'projectile'],
['walkable', 'not-flyable'],
);
grid.add_tile(tiles.ROAD_TB, 20, 46);
grid.add_tile(tiles.ROAD_BL, 18, 40);
grid.add_tile(tiles.ROAD_TR, 12, 38);
grid.add_tile(tiles.ROAD_BR, 12, 32);
grid.add_tile(tiles.ROAD_TL, 18, 30);
grid.add_tile(tiles.ROAD_BL, 18, 24);
grid.add_tile(tiles.ROAD_TR, 12, 22);
grid.add_tile(tiles.ROAD_BR, 12, 16);
grid.add_tile(tiles.ROAD_LR, 18, 16);
grid.add_tile(tiles.ROAD_TBLR, 24, 14);
grid.add_tile(tiles.ROAD_TB, 26, 2);
grid.add_tile(tiles.ROAD_TB, 26, 8);
grid.add_tile(tiles.ROAD_TB, 26, 22);
grid.add_tile(tiles.ROAD_TB, 26, 28);
grid.add_tile(tiles.ROAD_TB, 26, 34);
grid.add_tile(tiles.ROAD_TB, 26, 40);
grid.add_tile(tiles.ROAD_TB, 26, 46);
grid.add_tile(tiles.ROAD_BL, 32, 16);
grid.add_tile(tiles.ROAD_TB, 34, 22);
grid.add_tile(tiles.ROAD_TB, 34, 28);
grid.add_tile(tiles.ROAD_TB, 34, 34);
grid.add_tile(tiles.ROAD_TR, 34, 40);
grid.add_tile(tiles.ROAD_LR, 40, 42);
grid.add_tile(tiles.ROAD_LR, 46, 42);
grid.add_tile(tiles.ROAD_TL, 52, 40);
grid.add_tile(tiles.ROAD_BL, 52, 34);
grid.add_tile(tiles.ROAD_LR, 46, 34);
grid.add_tile(tiles.ROAD_TR, 40, 32);
grid.add_tile(tiles.ROAD_BR, 40, 26);
grid.add_tile(tiles.ROAD_LR, 46, 26);
grid.add_tile(tiles.ROAD_TL, 52, 24);
grid.add_tile(tiles.ROAD_BL, 52, 18);
grid.add_tile(tiles.ROAD_LR, 46, 18);
grid.add_tile(tiles.ROAD_TR, 40, 16);
grid.add_tile(tiles.ROAD_BR, 40, 10);
grid.add_tile(tiles.ROAD_LR, 46, 10);
grid.add_tile(tiles.ROAD_LR, 52, 10);
grid.add_tile(tiles.ROAD_LR, 58, 10);
grid.add_tile(tiles.EMPTY, 30, 20);
grid.add_tile(tiles.ROAD_TB, 40, 92);
grid.add_tile(tiles.ROAD_BL, 36, 80);
grid.add_tile(tiles.ROAD_TR, 24, 76);
grid.add_tile(tiles.ROAD_BR, 24, 64);
grid.add_tile(tiles.ROAD_TL, 36, 60);
grid.add_tile(tiles.ROAD_BL, 36, 48);
grid.add_tile(tiles.ROAD_TR, 24, 44);
grid.add_tile(tiles.ROAD_BR, 24, 32);
grid.add_tile(tiles.ROAD_LR, 36, 32);
grid.add_tile(tiles.ROAD_TBLR, 48, 28);
grid.add_tile(tiles.ROAD_TB, 52, 4);
grid.add_tile(tiles.ROAD_TB, 52, 16);
grid.add_tile(tiles.ROAD_TB, 52, 44);
grid.add_tile(tiles.ROAD_TB, 52, 56);
grid.add_tile(tiles.ROAD_TB, 52, 68);
grid.add_tile(tiles.ROAD_TB, 52, 80);
grid.add_tile(tiles.ROAD_TB, 52, 92);
grid.add_tile(tiles.ROAD_BL, 64, 32);
grid.add_tile(tiles.ROAD_TB, 68, 44);
grid.add_tile(tiles.ROAD_TB, 68, 56);
grid.add_tile(tiles.ROAD_TB, 68, 68);
grid.add_tile(tiles.ROAD_TR, 68, 80);
grid.add_tile(tiles.ROAD_LR, 80, 84);
grid.add_tile(tiles.ROAD_LR, 92, 84);
grid.add_tile(tiles.ROAD_TL, 104, 80);
grid.add_tile(tiles.ROAD_BL, 104, 68);
grid.add_tile(tiles.ROAD_LR, 92, 68);
grid.add_tile(tiles.ROAD_TR, 80, 64);
grid.add_tile(tiles.ROAD_BR, 80, 52);
grid.add_tile(tiles.ROAD_LR, 92, 52);
grid.add_tile(tiles.ROAD_TL, 104, 48);
grid.add_tile(tiles.ROAD_BL, 104, 36);
grid.add_tile(tiles.ROAD_LR, 92, 36);
grid.add_tile(tiles.ROAD_TR, 80, 32);
grid.add_tile(tiles.ROAD_BR, 80, 20);
grid.add_tile(tiles.ROAD_LR, 92, 20);
grid.add_tile(tiles.ROAD_LR, 104, 20);
grid.add_tile(tiles.ROAD_LR, 116, 20);
grid.add_tile(tiles.EMPTY, 60, 40);
grid.add_tile(tiles.RIVER_TB, 47, 46);
grid.add_tile(tiles.RIVER_TB, 47, 40);
grid.add_tile(tiles.RIVER_TB, 47, 34);
grid.add_tile(tiles.RIVER_TB, 47, 28);
grid.add_tile(tiles.RIVER_TB, 47, 22);
grid.add_tile(tiles.RIVER_TB, 47, 16);
grid.add_tile(tiles.RIVER_TB, 47, 10);
grid.add_tile(tiles.RIVER_TB, 47, 4);
grid.add_tile(tiles.RIVER_TB, 94, 92);
grid.add_tile(tiles.RIVER_TB, 94, 80);
grid.add_tile(tiles.RIVER_TB, 94, 68);
grid.add_tile(tiles.RIVER_TB, 94, 56);
grid.add_tile(tiles.RIVER_TB, 94, 44);
grid.add_tile(tiles.RIVER_TB, 94, 32);
grid.add_tile(tiles.RIVER_TB, 94, 20);
grid.add_tile(tiles.RIVER_TB, 94, 8);
grid.add_tile(tiles.BRIDGE_LR, 46, 42);
grid.add_tile(tiles.BRIDGE_LR, 46, 34);
grid.add_tile(tiles.BRIDGE_LR, 46, 26);
grid.add_tile(tiles.BRIDGE_LR, 46, 18);
grid.add_tile(tiles.BRIDGE_LR, 46, 10);
grid.add_tile(tiles.BRIDGE_LR, 92, 84);
grid.add_tile(tiles.BRIDGE_LR, 92, 68);
grid.add_tile(tiles.BRIDGE_LR, 92, 52);
grid.add_tile(tiles.BRIDGE_LR, 92, 36);
grid.add_tile(tiles.BRIDGE_LR, 92, 20);
{
const m = grid.masks.get('walkable')!.mask;
for (let x = 0; x < m.length; x++) {
for (let y = 0; y < m[x].length; y++) {
if (!m[x][y]) {
continue;
}
const div = document.createElement('div');
real.appendChild(div);
div.style.gridColumnStart = `${x + 1}`;
div.style.gridRowStart = `${y + 1}`;
div.style.gridColumnEnd = 'span 1';
div.style.gridRowEnd = 'span 1';
div.style.backgroundColor = 'orange';
div.style.opacity = '0.3';
div.style.zIndex = '1000000';
}
}
}
function rand(min: number, max: number): number {
return Math.round(Math.random() * (max - min) + min);
}
const tower = grid.add_tile(tiles.TOWER_FIREBALL1, 30, 28);
const tower = grid.add_tile(tiles.TOWER_FIREBALL1, 60, 56);
setInterval(() => {
tower.play('fire');
const target_relative_x = rand(-20, 20);
const target_relative_y = rand(-10, 20);
const target_relative_x = rand(-40, 40);
const target_relative_y = rand(-20, 40);
const factory = new ProjectileTileFactory(tiles.FIREBALL, target_relative_x, target_relative_y, 5, 1.5, 5);
grid.add_tile(factory, 31, 27);
grid.add_tile(factory, 62, 54);
setTimeout(() => {
grid.add_tile(tiles.FIREBALL_IMPACT, 31 + target_relative_x, 27 + target_relative_y);
grid.add_tile(tiles.FIREBALL_IMPACT, 62 + target_relative_x, 54 + target_relative_y);
}, factory.duration);
}, 3250);
const greenaxe = grid.add_tile(tiles.GREENAXE, 30, 16);
const greenaxe = grid.add_tile(tiles.GREENAXE, 60, 32);
greenaxe.play('walk');
greenaxe.elem.style.transitionProperty = 'top,left';
greenaxe.elem.style.transitionDuration = '25s';