Tower class hierarchy

This commit is contained in:
Ian Gulliver
2021-05-11 02:57:17 +00:00
parent 495aeb6204
commit 0ff24fe806
28 changed files with 346 additions and 279 deletions

View File

@@ -13,7 +13,7 @@ export class Layer {
}
add_tile(tile_factory: TileFactory): HTMLElement {
const elem = tile_factory.get_elem(this.#tileset);
const elem = tile_factory.build(this.#tileset).get_elem();
elem.style.zIndex = `${this.#level}`;
return elem;
}

23
ts/layered_tile.ts Normal file
View File

@@ -0,0 +1,23 @@
import { Tile } from './tile.js';
export class LayeredTile extends Tile {
elem: HTMLElement;
constructor(width: number, height: number, tiles: Tile[]) {
super(width, height);
this.elem.style.position = 'relative';
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i];
const sub = tile.get_elem();
this.elem.appendChild(sub);
sub.style.width = '100%';
sub.style.height = '100%';
sub.style.position = 'absolute';
sub.style.top = '0';
sub.style.left = '0';
sub.style.zIndex = `${i}`;
}
}
}

View File

@@ -1,42 +1,21 @@
import { AnimateDetail, TileFactory } from './tile_factory.js';
import { LayeredTile } from './layered_tile.js';
import { TileFactory } from './tile_factory.js';
export class LayeredTileFactory extends TileFactory {
tiles: TileFactory[];
tile_factories: TileFactory[];
constructor(tiles: TileFactory[]) {
super('', tiles[0].width, tiles[0].height);
this.tiles = tiles;
constructor(tile_factories: TileFactory[]) {
super(tile_factories[0].width, tile_factories[0].height);
this.tile_factories = tile_factories;
}
get_elem(tileset: string): HTMLElement {
const elem = document.createElement('div');
elem.style.gridColumnEnd = `span ${this.width}`;
elem.style.gridRowEnd = `span ${this.height}`;
elem.style.position = 'relative';
build(tileset: string): LayeredTile {
const tiles = [];
for (let i = 0; i < this.tiles.length; i++) {
const tile = this.tiles[i];
const sub = tile.get_elem(tileset);
elem.appendChild(sub);
sub.style.width = '100%';
sub.style.height = '100%';
sub.style.position = 'absolute';
sub.style.top = '0';
sub.style.left = '0';
sub.style.zIndex = `${i}`;
for (const tile_factory of this.tile_factories) {
tiles.push(tile_factory.build(tileset));
}
elem.addEventListener('animate', (e: CustomEvent<AnimateDetail>) => {
for (const sub of elem.children) {
sub.dispatchEvent(new CustomEvent('animate', {'detail': e.detail}));
}
});
// XXX removeme
setInterval(() => {
elem.dispatchEvent(new CustomEvent('animate', {'detail': {'name': 'fire'}}));
}, 3250);
return elem;
return new LayeredTile(this.width, this.height, tiles);
}
}

15
ts/simple_tile.ts Normal file
View File

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

51
ts/simple_tile_factory.ts Normal file
View File

@@ -0,0 +1,51 @@
import { SimpleTile } from './simple_tile.js';
import { TileFactory } from './tile_factory.js';
export class SimpleTileFactory extends TileFactory {
name: string;
animations: Map<string, [Keyframe[], object]>;
constructor(width: number, height: number, name: string) {
super(width, height);
this.name = name;
this.animations = new Map();
}
add_animation(name: string, keyframes: Keyframe[], options: object) {
this.animations.set(name, [keyframes, options]);
}
build(tileset: string): SimpleTile {
return new SimpleTile(
this.width,
this.height,
`images/${tileset}/${this.name}.svg`,
this.animations,
);
}
}
/*
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;
}
*/

13
ts/tile.ts Normal file
View File

@@ -0,0 +1,13 @@
export abstract class Tile {
elem: HTMLElement;
constructor(width: number, height: number) {
this.elem = document.createElement('div');
this.elem.style.gridColumnEnd = `span ${width}`;
this.elem.style.gridRowEnd = `span ${height}`;
}
get_elem(): HTMLElement {
return this.elem;
}
}

View File

@@ -1,64 +1,13 @@
export interface AnimateDetail {
name: string;
}
import { Tile } from './tile.js';
export class TileFactory {
name: string;
export abstract class TileFactory {
width: number;
height: number;
animations: Map<string, [Keyframe[], object]>;
constructor(name: string, width: number, height: number) {
this.name = name;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
this.animations = new Map();
}
add_animation(name: string, keyframes: Keyframe[], options: object) {
this.animations.set(name, [keyframes, options]);
}
get_elem(tileset: string): HTMLElement {
const elem = document.createElement('div');
elem.style.backgroundImage = `url("images/${tileset}/${this.name}.svg")`;
elem.style.backgroundSize = 'cover';
elem.style.gridColumnEnd = `span ${this.width}`;
elem.style.gridRowEnd = `span ${this.height}`;
elem.addEventListener('animate', (e: CustomEvent<AnimateDetail>) => {
const animation = this.animations.get(e.detail.name);
if (animation) {
elem.animate(animation[0], animation[1]);
}
});
return elem;
}
abstract build(tileset: string): Tile;
}
/*
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,46 +1,46 @@
import { LayeredTileFactory } from './layered_tile_factory.js';
import { TileFactory } from './tile_factory.js';
import { SimpleTileFactory } from './simple_tile_factory.js';
// Straight
export const ROAD_LR = new TileFactory('road-lr', 6, 4);
export const ROAD_TB = new TileFactory('road-tb', 4, 6);
// Straig
export const ROAD_LR = new SimpleTileFactory(6, 4, 'road-lr');
export const ROAD_TB = new SimpleTileFactory(4, 6, 'road-tb');
// Elbow
export const ROAD_BL = new TileFactory('road-bl', 6, 6);
export const ROAD_BR = new TileFactory('road-br', 6, 6);
export const ROAD_TL = new TileFactory('road-tl', 6, 6);
export const ROAD_TR = new TileFactory('road-tr', 6, 6);
export const ROAD_BL = new SimpleTileFactory(6, 6, 'road-bl');
export const ROAD_BR = new SimpleTileFactory(6, 6, 'road-br');
export const ROAD_TL = new SimpleTileFactory(6, 6, 'road-tl');
export const ROAD_TR = new SimpleTileFactory(6, 6, 'road-tr');
// T
export const ROAD_BLR = new TileFactory('road-blr', 8, 6);
export const ROAD_TLR = new TileFactory('road-tlr', 8, 6);
export const ROAD_LTB = new TileFactory('road-ltb', 6, 8);
export const ROAD_RTB = new TileFactory('road-rtb', 6, 8);
export const ROAD_BLR = new SimpleTileFactory(8, 6, 'road-blr');
export const ROAD_TLR = new SimpleTileFactory(8, 6, 'road-tlr');
export const ROAD_LTB = new SimpleTileFactory(6, 8, 'road-ltb');
export const ROAD_RTB = new SimpleTileFactory(6, 8, 'road-rtb');
// +
export const ROAD_TBLR = new TileFactory('road-tblr', 8, 8);
export const ROAD_TBLR = new SimpleTileFactory(8, 8, 'road-tblr');
// Tower base
export const EMPTY = new TileFactory('empty', 4, 2);
export const EMPTY = new SimpleTileFactory(4, 2, 'empty');
// Straight
export const RIVER_LR = new TileFactory('river-lr', 6, 4);
export const RIVER_TB = new TileFactory('river-tb', 4, 6);
export const RIVER_LR = new SimpleTileFactory(6, 4, 'river-lr');
export const RIVER_TB = new SimpleTileFactory(4, 6, 'river-tb');
// Elbow
export const RIVER_BR = new TileFactory('river-br', 6, 6);
export const RIVER_BL = new TileFactory('river-bl', 6, 6);
export const RIVER_TR = new TileFactory('river-tr', 6, 6);
export const RIVER_TL = new TileFactory('river-tl', 6, 6);
export const RIVER_BR = new SimpleTileFactory(6, 6, 'river-br');
export const RIVER_BL = new SimpleTileFactory(6, 6, 'river-bl');
export const RIVER_TR = new SimpleTileFactory(6, 6, 'river-tr');
export const RIVER_TL = new SimpleTileFactory(6, 6, 'river-tl');
export const BRIDGE_LR = new TileFactory('bridge-lr', 6, 4);
export const BRIDGE_LR = new SimpleTileFactory(6, 4, 'bridge-lr');
const tower_fireball1_back = new TileFactory('fireball1-back', 4, 4);
const tower_fireball1 = new TileFactory('fireball1', 4, 4);
const tower_fireball1_front = new TileFactory('fireball1-front', 4, 4);
const tower_fireball1_back = new SimpleTileFactory(4, 4, 'fireball1-back');
const tower_fireball1 = new SimpleTileFactory(4, 4, 'fireball1');
const tower_fireball1_front = new SimpleTileFactory(4, 4, 'fireball1-front');
for (const tile of [tower_fireball1_back, tower_fireball1_front]) {
tile.add_animation(
for (const tile_factory of [tower_fireball1_back, tower_fireball1_front]) {
tile_factory.add_animation(
'fire',
[
{
@@ -74,7 +74,8 @@ export const TOWER_FIREBALL1 = new LayeredTileFactory([
tower_fireball1_front,
]);
class Fireball extends TileFactory {
/*
class Fireball extends SimpleTileFactory {
get_elem(tileset: string): HTMLElement {
const elem = document.createElement('div');
elem.style.gridColumnEnd = `span ${this.width}`;
@@ -142,3 +143,4 @@ class Fireball extends TileFactory {
}
}
export const FIREBALL = new Fireball('fireball', 2, 2);
*/

View File

@@ -82,7 +82,6 @@ export function main() {
grid.add_tile('bridge', tiles.BRIDGE_LR, 46, 10);
grid.add_tile('tower', tiles.TOWER_FIREBALL1, 30, 18);
grid.add_tile('tower', tiles.FIREBALL, 31, 17);
};
main();