Remove decorators in favor of declarative initialization
This commit is contained in:
parent
a1900a4daa
commit
4212952abc
5 changed files with 72 additions and 56 deletions
|
@ -1,40 +1,48 @@
|
||||||
import { KeyControl } from "./Keyboard";
|
import { KeyControl } from "./Keyboard";
|
||||||
|
|
||||||
/**
|
|
||||||
* A class decorator for automatically constructing
|
|
||||||
* class instances around elements on page load.
|
|
||||||
*/
|
|
||||||
export function Bind(selector: string) {
|
|
||||||
return (appletType: AppletConstructor) => {
|
|
||||||
const elements = document.querySelectorAll(selector);
|
|
||||||
for(let i = 0; i < elements.length; i++) {
|
|
||||||
const element = elements[i] as HTMLElement;
|
|
||||||
new appletType(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export interface AppletConstructor {
|
|
||||||
new(element: HTMLElement): any
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class decorator for automatically constructing
|
|
||||||
* a KeyControl around a canvas on page load & fetching the render context.
|
|
||||||
*/
|
|
||||||
export function Game(selector: string, tabIndex = -1) {
|
|
||||||
return (gameType: GameConstructor) => {
|
|
||||||
const elements = document.querySelectorAll(selector);
|
|
||||||
for(let i = 0; i < elements.length; i++) {
|
|
||||||
const element = elements[i] as HTMLCanvasElement;
|
|
||||||
if(!(element instanceof HTMLCanvasElement)) continue;
|
|
||||||
|
|
||||||
const cx = element.getContext("2d") as CanvasRenderingContext2D;
|
|
||||||
const keys = new KeyControl(element, tabIndex);
|
|
||||||
|
|
||||||
new gameType(element, cx, keys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export interface GameConstructor {
|
export interface GameConstructor {
|
||||||
new(canvas: HTMLCanvasElement, cx: CanvasRenderingContext2D, keys: KeyControl): any
|
new(canvas: HTMLCanvasElement, cx: CanvasRenderingContext2D, keys: KeyControl): any
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Selection {
|
||||||
|
constructor(private elements: HTMLElement[]) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a callback for every selected item.
|
||||||
|
*/
|
||||||
|
public forEach(callback: (e: HTMLElement) => {}) {
|
||||||
|
this.elements.forEach(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a callback for selected canvases, with a 2d context & KeyControl established for use.
|
||||||
|
*/
|
||||||
|
public forEachCanvas(callback: (canvas: HTMLCanvasElement, cx: CanvasRenderingContext2D, keys: KeyControl) => {}, tabIndex = -1) {
|
||||||
|
this.elements.forEach(e => {
|
||||||
|
if(e instanceof HTMLCanvasElement) {
|
||||||
|
const cx = e.getContext("2d") as CanvasRenderingContext2D;
|
||||||
|
const keys = new KeyControl(e, tabIndex);
|
||||||
|
|
||||||
|
callback(e, cx, keys);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap an HTML element or list of elements to bind them to behavior.
|
||||||
|
*
|
||||||
|
* @param selector A CSS selector or a literal Element
|
||||||
|
*/
|
||||||
|
export function Select(selector: string): Selection;
|
||||||
|
export function Select(selector: HTMLElement): Selection;
|
||||||
|
export function Select(selector: string | HTMLElement): Selection {
|
||||||
|
if(typeof selector === "string") {
|
||||||
|
const elementList = document.querySelectorAll(selector);
|
||||||
|
const elements: HTMLElement[] = Array.prototype.slice.call(elementList);
|
||||||
|
return new Selection(elements);
|
||||||
|
} else {
|
||||||
|
const elements = [selector];
|
||||||
|
return new Selection(elements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { Bind } from "./Init";
|
import { Select } from "./Init";
|
||||||
import { KeyControl, KeyHandler, KeyName } from "./Keyboard";
|
import { KeyControl, KeyHandler, KeyName } from "./Keyboard";
|
||||||
import { Loop } from "./Loop";
|
import { Loop } from "./Loop";
|
||||||
|
|
||||||
@Bind("#KeyTest")
|
class Test implements KeyHandler {
|
||||||
export class Test implements KeyHandler {
|
|
||||||
private keys: KeyControl;
|
private keys: KeyControl;
|
||||||
|
|
||||||
constructor(public div: HTMLElement) {
|
constructor(public div: HTMLElement) {
|
||||||
|
@ -29,8 +28,7 @@ export class Test implements KeyHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind("#LoopTest")
|
class LoopTest {
|
||||||
export class LoopTest {
|
|
||||||
frames: number = 0;
|
frames: number = 0;
|
||||||
|
|
||||||
constructor(public div: HTMLElement) {
|
constructor(public div: HTMLElement) {
|
||||||
|
@ -45,3 +43,8 @@ export class LoopTest {
|
||||||
loop.start();
|
loop.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function BindDemos(): void {
|
||||||
|
Select("#KeyTest").forEach(e => new Test(e));
|
||||||
|
Select("#LoopTest").forEach(e => new LoopTest(e));
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Bind, Game } from "../Applet/Init";
|
import { Select } from "../Applet/Init";
|
||||||
import { KeyControl } from "../Applet/Keyboard";
|
import { KeyControl } from "../Applet/Keyboard";
|
||||||
import { Loop } from "../Applet/Loop";
|
import { Loop } from "../Applet/Loop";
|
||||||
import { DrawSet, Layer } from "../Applet/Render";
|
import { DrawSet, Layer } from "../Applet/Render";
|
||||||
|
@ -45,8 +45,7 @@ class TestData extends Data {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind("#EcsJoinTest")
|
class EcsJoinTest {
|
||||||
export class EcsJoinTest {
|
|
||||||
constructor(pre: HTMLElement) {
|
constructor(pre: HTMLElement) {
|
||||||
const data = new TestData();
|
const data = new TestData();
|
||||||
pre.innerText = JSON.stringify({
|
pre.innerText = JSON.stringify({
|
||||||
|
@ -58,8 +57,7 @@ export class EcsJoinTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind("#EcsLookupTest")
|
class EcsLookupTest {
|
||||||
export class EcsLookupTest {
|
|
||||||
constructor(pre: HTMLElement) {
|
constructor(pre: HTMLElement) {
|
||||||
const data = new TestData();
|
const data = new TestData();
|
||||||
const applesMaybeCarrots = Join(data, "apple", "id").map(([apple, id]) => ({
|
const applesMaybeCarrots = Join(data, "apple", "id").map(([apple, id]) => ({
|
||||||
|
@ -70,8 +68,7 @@ export class EcsLookupTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind("#EcsRemoveTest")
|
class EcsRemoveTest {
|
||||||
export class EcsRemoveTest {
|
|
||||||
constructor(pre: HTMLElement) {
|
constructor(pre: HTMLElement) {
|
||||||
const data = new TestData();
|
const data = new TestData();
|
||||||
const beforeDelete = Join(data, "apple", "carrot", "id",);
|
const beforeDelete = Join(data, "apple", "carrot", "id",);
|
||||||
|
@ -84,8 +81,7 @@ export class EcsRemoveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind("#EcsCreateTest")
|
class EcsCreateTest {
|
||||||
export class EcsCreateTest {
|
|
||||||
constructor(pre: HTMLElement) {
|
constructor(pre: HTMLElement) {
|
||||||
const data = new TestData();
|
const data = new TestData();
|
||||||
const beforeCreate = Join(data, "apple", "banana", "carrot", "id");
|
const beforeCreate = Join(data, "apple", "banana", "carrot", "id");
|
||||||
|
@ -103,8 +99,7 @@ export class EcsCreateTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Game("#RenderTest")
|
class LoopTest {
|
||||||
export class LoopTest {
|
|
||||||
data = new Data();
|
data = new Data();
|
||||||
|
|
||||||
constructor(public canvas: HTMLCanvasElement, cx: CanvasRenderingContext2D, keys: KeyControl) {
|
constructor(public canvas: HTMLCanvasElement, cx: CanvasRenderingContext2D, keys: KeyControl) {
|
||||||
|
@ -174,3 +169,11 @@ export class LoopTest {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function BindTests(): void {
|
||||||
|
Select("#EcsJoinTest").forEach(e => new EcsJoinTest(e));
|
||||||
|
Select("#EcsLookupTest").forEach(e => new EcsLookupTest(e));
|
||||||
|
Select("#EcsRemoveTest").forEach(e => new EcsRemoveTest(e));
|
||||||
|
Select("#EcsCreateTest").forEach(e => new EcsCreateTest(e));
|
||||||
|
Select("#RenderTest").forEachCanvas((c, cx, keys) => new LoopTest(c, cx, keys));
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import subscribe from "callbag-subscribe";
|
import subscribe from "callbag-subscribe";
|
||||||
|
|
||||||
import { Game } from "../Applet/Init";
|
|
||||||
import { KeyControl, KeyName } from "../Applet/Keyboard";
|
import { KeyControl, KeyName } from "../Applet/Keyboard";
|
||||||
import { DrawSet } from "../Applet/Render";
|
import { DrawSet } from "../Applet/Render";
|
||||||
import { Location, Polygon, RenderBounds } from "../Ecs/Components";
|
import { Location, Polygon, RenderBounds } from "../Ecs/Components";
|
||||||
import { Create } from "../Ecs/Data";
|
import { Create } from "../Ecs/Data";
|
||||||
import {} from "../Ecs/Lockstep";
|
|
||||||
import { RunRenderBounds } from "../Ecs/Renderers";
|
import { RunRenderBounds } from "../Ecs/Renderers";
|
||||||
import { LockstepClient } from "../Net/LockstepClient";
|
import { LockstepClient } from "../Net/LockstepClient";
|
||||||
import { Loopback } from "../Net/LoopbackServer";
|
import { Loopback } from "../Net/LoopbackServer";
|
||||||
import { Data, Engine } from "./GameComponents";
|
import { Data, Engine } from "./GameComponents";
|
||||||
import { Buttons } from "./Input";
|
import { Buttons } from "./Input";
|
||||||
|
|
||||||
@Game("#GameCanvas")
|
|
||||||
export class Main extends LockstepClient<KeyName[], Data> {
|
export class Main extends LockstepClient<KeyName[], Data> {
|
||||||
|
|
||||||
buttons = new Buttons();
|
buttons = new Buttons();
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
import "./Game/Main";
|
import { Select } from "./Applet/Init";
|
||||||
import "./Ecs/test";
|
import { BindTests } from "./Ecs/test";
|
||||||
|
import { Main } from "./Game/Main";
|
||||||
|
|
||||||
|
Select("#GameCanvas").forEachCanvas((c, cx, keys) => new Main(c, cx, keys));
|
||||||
|
|
||||||
|
BindTests();
|
||||||
|
|
Loading…
Reference in a new issue