LayeredTile abstraction
This commit is contained in:
42
ts/layered_tile.ts
Normal file
42
ts/layered_tile.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { AnimateDetail, Tile } from './tile.js';
|
||||
|
||||
export class LayeredTile extends Tile {
|
||||
tiles: Tile[];
|
||||
|
||||
constructor(tiles: Tile[]) {
|
||||
super('', tiles[0].width, tiles[0].height);
|
||||
this.tiles = tiles;
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
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}`;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
19
ts/tile.ts
19
ts/tile.ts
@@ -1,12 +1,23 @@
|
||||
export interface AnimateDetail {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class Tile {
|
||||
name: string;
|
||||
width: number;
|
||||
height: number;
|
||||
animations: Map<string, [Keyframe[], object]>;
|
||||
|
||||
constructor(name: string, width: number, height: number) {
|
||||
this.name = name;
|
||||
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 {
|
||||
@@ -15,6 +26,14 @@ export class Tile {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
125
ts/tiles.ts
125
ts/tiles.ts
@@ -1,3 +1,4 @@
|
||||
import { LayeredTile } from './layered_tile.js';
|
||||
import { Tile } from './tile.js';
|
||||
|
||||
// Straight
|
||||
@@ -34,101 +35,47 @@ export const RIVER_TL = new Tile('river-tl', 6, 6);
|
||||
|
||||
export const BRIDGE_LR = new Tile('bridge-lr', 6, 4);
|
||||
|
||||
class Tower extends Tile {
|
||||
get_elem(_: string): HTMLElement {
|
||||
const elem = document.createElement('div');
|
||||
elem.style.gridColumnEnd = `span ${this.width}`;
|
||||
elem.style.gridRowEnd = `span ${this.height}`;
|
||||
elem.style.position = 'relative';
|
||||
const tower_fireball1_back = new Tile('fireball1-back', 4, 4);
|
||||
const tower_fireball1 = new Tile('fireball1', 4, 4);
|
||||
const tower_fireball1_front = new Tile('fireball1-front', 4, 4);
|
||||
|
||||
const base = document.createElement('div');
|
||||
elem.appendChild(base);
|
||||
base.style.width = '100%';
|
||||
base.style.height = '100%';
|
||||
base.style.position = 'absolute';
|
||||
base.style.top = '0';
|
||||
base.style.left = '0';
|
||||
base.style.backgroundImage = `url("images/tower/${this.name}.svg")`;
|
||||
base.style.backgroundSize = 'cover';
|
||||
base.style.zIndex = '2';
|
||||
for (const tile of [tower_fireball1_back, tower_fireball1_front]) {
|
||||
tile.add_animation(
|
||||
'fire',
|
||||
[
|
||||
{
|
||||
'offset': 0.0,
|
||||
'easing': 'cubic-bezier(0.02, 1.07, 0.73, 0.99)',
|
||||
|
||||
const back = document.createElement('div');
|
||||
elem.appendChild(back);
|
||||
back.style.width = '100%';
|
||||
back.style.height = '100%';
|
||||
back.style.position = 'absolute';
|
||||
back.style.top = '0';
|
||||
back.style.left = '0';
|
||||
back.style.backgroundImage = `url("images/tower/${this.name}-back.svg")`;
|
||||
back.style.backgroundSize = 'cover';
|
||||
back.style.zIndex = '1';
|
||||
'top': '0',
|
||||
},
|
||||
{
|
||||
'offset': 0.3,
|
||||
'easing': 'linear',
|
||||
|
||||
const front = document.createElement('div');
|
||||
elem.appendChild(front);
|
||||
front.style.width = '100%';
|
||||
front.style.height = '100%';
|
||||
front.style.position = 'absolute';
|
||||
front.style.top = '0';
|
||||
front.style.left = '0';
|
||||
front.style.backgroundImage = `url("images/tower/${this.name}-front.svg")`;
|
||||
front.style.backgroundSize = 'cover';
|
||||
front.style.zIndex = '3';
|
||||
'top': '20%',
|
||||
},
|
||||
{
|
||||
'offset': 1.0,
|
||||
|
||||
setInterval(() => {
|
||||
back.animate([
|
||||
{
|
||||
'offset': 0.0,
|
||||
'easing': 'cubic-bezier(0.02, 1.07, 0.73, 0.99)',
|
||||
|
||||
'top': '0',
|
||||
},
|
||||
{
|
||||
'offset': 0.3,
|
||||
'easing': 'linear',
|
||||
|
||||
'top': '20%',
|
||||
},
|
||||
{
|
||||
'offset': 1.0,
|
||||
|
||||
'top': '0',
|
||||
},
|
||||
], {
|
||||
'duration': 3000,
|
||||
'iterations': 1,
|
||||
});
|
||||
|
||||
front.animate([
|
||||
{
|
||||
'offset': 0.0,
|
||||
'easing': 'cubic-bezier(0.02, 1.07, 0.73, 0.99)',
|
||||
|
||||
'top': '0',
|
||||
},
|
||||
{
|
||||
'offset': 0.3,
|
||||
'easing': 'linear',
|
||||
|
||||
'top': '20%',
|
||||
},
|
||||
{
|
||||
'offset': 1.0,
|
||||
|
||||
'top': '0',
|
||||
},
|
||||
], {
|
||||
'duration': 3000,
|
||||
'iterations': 1,
|
||||
});
|
||||
}, 3250);
|
||||
|
||||
return elem;
|
||||
}
|
||||
'top': '0',
|
||||
},
|
||||
],
|
||||
{
|
||||
'duration': 3000,
|
||||
'iterations': 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
export const FIREBALL1 = new Tower('fireball1', 4, 4);
|
||||
|
||||
export const TOWER_FIREBALL1 = new LayeredTile([
|
||||
tower_fireball1_back,
|
||||
tower_fireball1,
|
||||
tower_fireball1_front,
|
||||
]);
|
||||
|
||||
class Fireball extends Tile {
|
||||
get_elem(_: string): HTMLElement {
|
||||
get_elem(tileset: string): HTMLElement {
|
||||
const elem = document.createElement('div');
|
||||
elem.style.gridColumnEnd = `span ${this.width}`;
|
||||
elem.style.gridRowEnd = `span ${this.height}`;
|
||||
@@ -141,7 +88,7 @@ class Fireball extends Tile {
|
||||
base.style.position = 'absolute';
|
||||
base.style.top = '0';
|
||||
base.style.left = '0';
|
||||
base.style.backgroundImage = `url("images/tower/${this.name}.svg")`;
|
||||
base.style.backgroundImage = `url("images/${tileset}/${this.name}.svg")`;
|
||||
base.style.backgroundSize = 'cover';
|
||||
base.style.visibility = 'hidden';
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ export function main() {
|
||||
grid.add_tile('bridge', tiles.BRIDGE_LR, 46, 18);
|
||||
grid.add_tile('bridge', tiles.BRIDGE_LR, 46, 10);
|
||||
|
||||
grid.add_tile('tower', tiles.FIREBALL1, 30, 18);
|
||||
grid.add_tile('tower', tiles.TOWER_FIREBALL1, 30, 18);
|
||||
grid.add_tile('tower', tiles.FIREBALL, 31, 17);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user