mirror of
https://git.sfja.dk/sfja/h6-logicirc.git
synced 2025-05-16 01:08:07 +01:00
place switches and leds
This commit is contained in:
parent
0db1c3b90a
commit
505e869e1f
@ -1,5 +1,5 @@
|
|||||||
import { EvHandler, EvHandlerRes, Mouse } from "./input.ts";
|
import { EvHandler, EvHandlerRes, Mouse } from "./input.ts";
|
||||||
import { Renderer } from "./renderer.ts";
|
import { Renderer, RendererImage } from "./renderer.ts";
|
||||||
|
|
||||||
export class CanvasRenderer implements Renderer {
|
export class CanvasRenderer implements Renderer {
|
||||||
constructor(
|
constructor(
|
||||||
@ -34,9 +34,15 @@ export class CanvasRenderer implements Renderer {
|
|||||||
g.fill();
|
g.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
putImageData(data: ImageData, x: number, y: number, _hash = 0n): void {
|
putImage(
|
||||||
|
data: RendererImage,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w = data.width,
|
||||||
|
h = data.height,
|
||||||
|
): void {
|
||||||
const { g } = this;
|
const { g } = this;
|
||||||
g.putImageData(data, x, y);
|
g.drawImage(data, x, y, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
88
src/grid.ts
88
src/grid.ts
@ -1,14 +1,18 @@
|
|||||||
import { Mouse } from "./input.ts";
|
import { EvHandler, Mouse } from "./input.ts";
|
||||||
import { Renderer } from "./renderer.ts";
|
import { Renderer, RendererImage } from "./renderer.ts";
|
||||||
|
|
||||||
export class Grid {
|
export class Grid {
|
||||||
private t: Transformation = { s: 2, ox: 0, oy: 0 };
|
private t: Transformation = { s: 2, ox: 0, oy: 0 };
|
||||||
private transformer = new Transformer(this.t);
|
private transformer = new Transformer(this.t);
|
||||||
private tr = new TransformingRenderer(this.t);
|
private tr = new TransformingRenderer(this.t);
|
||||||
|
|
||||||
|
private _transformingMouse: TransformingMouse;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private mouse: Mouse,
|
private mouse: Mouse,
|
||||||
) {
|
) {
|
||||||
|
this._transformingMouse = new TransformingMouse(this.mouse, this.t);
|
||||||
|
|
||||||
this.mouse.addOnPress(() => {
|
this.mouse.addOnPress(() => {
|
||||||
this.transformer.startPan();
|
this.transformer.startPan();
|
||||||
return "stop";
|
return "stop";
|
||||||
@ -28,11 +32,14 @@ export class Grid {
|
|||||||
} else {
|
} else {
|
||||||
this.transformer.zoomOut();
|
this.transformer.zoomOut();
|
||||||
}
|
}
|
||||||
this.tr.clearCache();
|
|
||||||
return "stop";
|
return "stop";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformingMouse(): Mouse {
|
||||||
|
return this._transformingMouse;
|
||||||
|
}
|
||||||
|
|
||||||
render(r: Renderer, renderTransformed: (r: Renderer) => void) {
|
render(r: Renderer, renderTransformed: (r: Renderer) => void) {
|
||||||
this.transformer.updateCanvas(r.width, r.height);
|
this.transformer.updateCanvas(r.width, r.height);
|
||||||
this.drawGrid(r);
|
this.drawGrid(r);
|
||||||
@ -138,7 +145,6 @@ class Transformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TransformingRenderer implements Renderer {
|
class TransformingRenderer implements Renderer {
|
||||||
private imageDataCache = new Map<bigint, ImageData>();
|
|
||||||
private r!: Renderer;
|
private r!: Renderer;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -150,10 +156,6 @@ class TransformingRenderer implements Renderer {
|
|||||||
renderTransformed(this);
|
renderTransformed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCache() {
|
|
||||||
this.imageDataCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
get width(): number {
|
get width(): number {
|
||||||
return this.r.width / this.t.s;
|
return this.r.width / this.t.s;
|
||||||
}
|
}
|
||||||
@ -171,49 +173,47 @@ class TransformingRenderer implements Renderer {
|
|||||||
const { r, t: { s, ox, oy } } = this;
|
const { r, t: { s, ox, oy } } = this;
|
||||||
r.fillCirc(x * s + ox, y * s + oy, radius * s, color);
|
r.fillCirc(x * s + ox, y * s + oy, radius * s, color);
|
||||||
}
|
}
|
||||||
putImageData(data: ImageData, x: number, y: number, hash = 0n): void {
|
putImage(
|
||||||
|
data: RendererImage,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w = data.width,
|
||||||
|
h = data.width,
|
||||||
|
): void {
|
||||||
const { r, t: { s, ox, oy } } = this;
|
const { r, t: { s, ox, oy } } = this;
|
||||||
|
|
||||||
if (hash === 0n || !this.imageDataCache.has(hash)) {
|
r.putImage(
|
||||||
const scaledWidth = data.width * s;
|
data,
|
||||||
const scaledHeight = data.height * s;
|
|
||||||
|
|
||||||
const canvas = new OffscreenCanvas(
|
|
||||||
Math.max(data.width, scaledWidth),
|
|
||||||
Math.max(data.height, scaledHeight),
|
|
||||||
);
|
|
||||||
const ctx = canvas.getContext("2d")!;
|
|
||||||
ctx.putImageData(data, 0, 0);
|
|
||||||
ctx.scale(s, s);
|
|
||||||
|
|
||||||
const scaledData = ctx.getImageData(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
scaledWidth,
|
|
||||||
scaledHeight,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hash === 0n) {
|
|
||||||
r.putImageData(
|
|
||||||
scaledData,
|
|
||||||
x * s + ox,
|
x * s + ox,
|
||||||
y * s + oy,
|
y * s + oy,
|
||||||
);
|
w * s,
|
||||||
return;
|
h * s,
|
||||||
}
|
|
||||||
if (this.imageDataCache.size > 128) {
|
|
||||||
this.imageDataCache.delete(
|
|
||||||
this.imageDataCache.keys().take(1).toArray()[0],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.imageDataCache.set(hash, scaledData);
|
|
||||||
console.log(this.imageDataCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.putImageData(
|
class TransformingMouse implements Mouse {
|
||||||
this.imageDataCache.get(hash)!,
|
constructor(
|
||||||
x * s + ox,
|
private mouse: Mouse,
|
||||||
y * s + oy,
|
private t: Transformation,
|
||||||
);
|
) {}
|
||||||
|
|
||||||
|
get x(): number {
|
||||||
|
return (this.mouse.x - this.t.ox) / this.t.s;
|
||||||
|
}
|
||||||
|
get y(): number {
|
||||||
|
return (this.mouse.y - this.t.oy) / this.t.s;
|
||||||
|
}
|
||||||
|
addOnPress(handler: EvHandler): void {
|
||||||
|
this.mouse.addOnPress(handler);
|
||||||
|
}
|
||||||
|
addOnRelease(handler: EvHandler): void {
|
||||||
|
this.mouse.addOnRelease(handler);
|
||||||
|
}
|
||||||
|
addOnMove(handler: EvHandler): void {
|
||||||
|
this.mouse.addOnMove(handler);
|
||||||
|
}
|
||||||
|
addOnScroll(handler: EvHandler<["up" | "down"]>): void {
|
||||||
|
this.mouse.addOnScroll(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ const g = c.getContext("2d", { alpha: false })!;
|
|||||||
c.width = document.body.clientWidth;
|
c.width = document.body.clientWidth;
|
||||||
c.height = document.body.clientHeight;
|
c.height = document.body.clientHeight;
|
||||||
c.style.position = "absolute";
|
c.style.position = "absolute";
|
||||||
|
g.imageSmoothingEnabled = false;
|
||||||
|
|
||||||
const r = new CanvasRenderer(c, g);
|
const r = new CanvasRenderer(c, g);
|
||||||
const mouse = new CanvasMouse(c);
|
const mouse = new CanvasMouse(c);
|
||||||
|
@ -1,30 +1,22 @@
|
|||||||
import { CanvasRenderer } from "./canvas.ts";
|
import { CanvasRenderer } from "./canvas.ts";
|
||||||
import { Renderer } from "./renderer.ts";
|
import { Renderer, RendererImage } from "./renderer.ts";
|
||||||
|
|
||||||
export class Painter implements Renderer {
|
export class Painter implements Renderer {
|
||||||
private c: OffscreenCanvas;
|
private c: OffscreenCanvas;
|
||||||
private g: OffscreenCanvasRenderingContext2D;
|
private g: OffscreenCanvasRenderingContext2D;
|
||||||
private r: Renderer;
|
private r: Renderer;
|
||||||
|
|
||||||
private hash: bigint = 0n;
|
|
||||||
|
|
||||||
constructor(width: number, height: number) {
|
constructor(width: number, height: number) {
|
||||||
this.c = new OffscreenCanvas(width, height);
|
this.c = new OffscreenCanvas(width, height);
|
||||||
this.g = this.c.getContext("2d", { alpha: false })!;
|
this.g = this.c.getContext("2d")!;
|
||||||
this.r = new CanvasRenderer(
|
this.r = new CanvasRenderer(
|
||||||
this.c as unknown as HTMLCanvasElement,
|
this.c as unknown as HTMLCanvasElement,
|
||||||
this.g as unknown as CanvasRenderingContext2D,
|
this.g as unknown as CanvasRenderingContext2D,
|
||||||
);
|
);
|
||||||
this.rehash();
|
|
||||||
}
|
|
||||||
|
|
||||||
private rehash() {
|
|
||||||
this.hash = BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(r: Renderer, x: number, y: number) {
|
render(r: Renderer, x: number, y: number) {
|
||||||
const data = this.g.getImageData(0, 0, this.c.width, this.c.height);
|
r.putImage(this.c, x, y, this.c.width, this.c.height);
|
||||||
r.putImageData(data, x, y, this.hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get width(): number {
|
get width(): number {
|
||||||
@ -34,19 +26,21 @@ export class Painter implements Renderer {
|
|||||||
return this.r.height;
|
return this.r.height;
|
||||||
}
|
}
|
||||||
clear(color: string): void {
|
clear(color: string): void {
|
||||||
this.rehash();
|
|
||||||
this.r.clear(color);
|
this.r.clear(color);
|
||||||
}
|
}
|
||||||
fillRect(x: number, y: number, w: number, h: number, color: string): void {
|
fillRect(x: number, y: number, w: number, h: number, color: string): void {
|
||||||
this.rehash();
|
|
||||||
this.r.fillRect(x, y, w, h, color);
|
this.r.fillRect(x, y, w, h, color);
|
||||||
}
|
}
|
||||||
fillCirc(x: number, y: number, radius: number, color: string): void {
|
fillCirc(x: number, y: number, radius: number, color: string): void {
|
||||||
this.rehash();
|
|
||||||
this.r.fillCirc(x, y, radius, color);
|
this.r.fillCirc(x, y, radius, color);
|
||||||
}
|
}
|
||||||
putImageData(data: ImageData, x: number, y: number, hash?: bigint): void {
|
putImage(
|
||||||
this.rehash();
|
data: RendererImage,
|
||||||
this.r.putImageData(data, x, y, hash);
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w = data.width,
|
||||||
|
h = data.height,
|
||||||
|
): void {
|
||||||
|
this.r.putImage(data, x, y, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
type N = number;
|
type N = number;
|
||||||
|
|
||||||
|
export type RendererImage =
|
||||||
|
| HTMLCanvasElement
|
||||||
|
| OffscreenCanvas
|
||||||
|
| HTMLImageElement;
|
||||||
|
|
||||||
export interface Renderer {
|
export interface Renderer {
|
||||||
get width(): N;
|
get width(): N;
|
||||||
get height(): N;
|
get height(): N;
|
||||||
clear(color: string): void;
|
clear(color: string): void;
|
||||||
fillRect(x: N, y: N, w: N, h: N, color: string): void;
|
fillRect(x: N, y: N, w: N, h: N, color: string): void;
|
||||||
fillCirc(x: N, y: N, radius: N, color: string): void;
|
fillCirc(x: N, y: N, radius: N, color: string): void;
|
||||||
putImageData(data: ImageData, x: N, y: N, hash?: bigint): void;
|
putImage(data: RendererImage, x: N, y: N, w?: N, h?: N): void;
|
||||||
}
|
}
|
||||||
|
247
src/simulator.ts
247
src/simulator.ts
@ -5,35 +5,260 @@ import { Renderer } from "./renderer.ts";
|
|||||||
|
|
||||||
export class Simulator {
|
export class Simulator {
|
||||||
private grid: Grid;
|
private grid: Grid;
|
||||||
|
private circuit: Circuit;
|
||||||
private myComponent = new Component();
|
private tooltip: Tooltip;
|
||||||
|
private toolbar: Toolbar;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private mouse: Mouse,
|
private mouse: Mouse,
|
||||||
) {
|
) {
|
||||||
this.grid = new Grid(this.mouse);
|
this.grid = new Grid(this.mouse);
|
||||||
|
this.circuit = new Circuit(this.grid.transformingMouse());
|
||||||
|
this.tooltip = new Tooltip(this.circuit, this.grid.transformingMouse());
|
||||||
|
this.toolbar = new Toolbar(this.mouse, this.tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(r: Renderer) {
|
render(r: Renderer) {
|
||||||
|
hover: {
|
||||||
|
if (this.toolbar.hover(this.mouse.x, this.mouse.y) === "break") {
|
||||||
|
break hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r.clear("black");
|
r.clear("black");
|
||||||
this.grid.render(r, (r) => {
|
this.grid.render(r, (tr) => {
|
||||||
this.myComponent.render(r);
|
this.circuit.render(tr);
|
||||||
|
this.toolbar.render(r);
|
||||||
|
this.tooltip.render(tr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Circuit {
|
class Toolbar {
|
||||||
private components: Component[] = [];
|
private tools: ComponentFactory[] = [
|
||||||
|
new SwitchComponent(),
|
||||||
|
new LedComponent(),
|
||||||
|
];
|
||||||
|
private previews: Component[] = [];
|
||||||
|
|
||||||
|
private lastWidth = 0;
|
||||||
|
private lastHeight = 0;
|
||||||
|
|
||||||
|
private hoveringComponentIdx?: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private mouse: Mouse,
|
||||||
|
private tooltip: Tooltip,
|
||||||
|
) {
|
||||||
|
this.fillPreviews();
|
||||||
|
|
||||||
|
this.mouse.addOnPress(() => {
|
||||||
|
const { x, y } = this.mouse;
|
||||||
|
for (const [i, component] of this.previews.entries()) {
|
||||||
|
if (
|
||||||
|
x >= i * 128 + 96 - 48 &&
|
||||||
|
y >= this.lastHeight - 100 - 48 &&
|
||||||
|
x < i * 128 + 96 + component.width * 32 + 32 &&
|
||||||
|
y < this.lastHeight - 100 + component.height * 32 + 32
|
||||||
|
) {
|
||||||
|
this.tooltip.select(this.tools[i].newInstance());
|
||||||
|
return "stop";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "bubble";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class Component {
|
private fillPreviews(): void {
|
||||||
private p = new Painter(64, 64);
|
// this.previews = this.tools.map((tool) => tool.newInstance());
|
||||||
|
this.previews = this.tools as unknown as Component[];
|
||||||
|
}
|
||||||
|
|
||||||
|
hover(x: number, y: number): "continue" | "break" {
|
||||||
|
for (const [i, component] of this.previews.entries()) {
|
||||||
|
if (
|
||||||
|
x >= i * 128 + 96 - 48 &&
|
||||||
|
y >= this.lastHeight - 100 - 48 &&
|
||||||
|
x < i * 128 + 96 + component.width * 32 + 32 &&
|
||||||
|
y < this.lastHeight - 100 + component.height * 32 + 32
|
||||||
|
) {
|
||||||
|
this.hoveringComponentIdx = i;
|
||||||
|
return "break";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.hoveringComponentIdx = undefined;
|
||||||
|
return "continue";
|
||||||
|
}
|
||||||
|
|
||||||
|
render(r: Renderer): void {
|
||||||
|
this.lastWidth = r.width;
|
||||||
|
this.lastHeight = r.height;
|
||||||
|
|
||||||
|
r.fillRect(0, r.height - 200, r.width, 200, "#aaa");
|
||||||
|
for (const [i, component] of this.previews.entries()) {
|
||||||
|
if (i === this.hoveringComponentIdx) {
|
||||||
|
r.fillRect(
|
||||||
|
i * 128 + 96 - 48,
|
||||||
|
r.height - 100 - 48,
|
||||||
|
component.height * 32 + 64,
|
||||||
|
component.width * 32 + 64,
|
||||||
|
"#00000088",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
component.render(r, i * 128 + 96, r.height - 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tooltip {
|
||||||
|
private selectedComponent?: Component;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private circuit: Circuit,
|
||||||
|
public mouse: Mouse,
|
||||||
|
) {
|
||||||
|
this.mouse.addOnPress(() => {
|
||||||
|
if (!this.selectedComponent) {
|
||||||
|
return "bubble";
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = Math.floor(this.mouse.x / 32);
|
||||||
|
const y = Math.floor(this.mouse.y / 32);
|
||||||
|
this.circuit.place(this.selectedComponent, x, y);
|
||||||
|
this.selectedComponent = undefined;
|
||||||
|
return "stop";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(r: Renderer): void {
|
||||||
|
this.selectedComponent?.render(r, this.mouse.x, this.mouse.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
select(component: Component): void {
|
||||||
|
this.selectedComponent = component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlacedComponent = {
|
||||||
|
component: Component;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circuit {
|
||||||
|
private components: PlacedComponent[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private mouse: Mouse,
|
||||||
|
) {
|
||||||
|
this.mouse.addOnPress(() => {
|
||||||
|
for (const { component, x, y } of this.components) {
|
||||||
|
if (!component.click) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.mouse.x >= x * 32 &&
|
||||||
|
this.mouse.y >= y * 32 &&
|
||||||
|
this.mouse.x < x * 32 + component.width * 32 &&
|
||||||
|
this.mouse.y < y * 32 + component.height * 32
|
||||||
|
) {
|
||||||
|
component.click(
|
||||||
|
this.mouse.x - x * 32,
|
||||||
|
this.mouse.y - y * 32,
|
||||||
|
);
|
||||||
|
return "stop";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "bubble";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
place(component: Component, x: number, y: number): void {
|
||||||
|
this.components.push({ component, x, y });
|
||||||
|
}
|
||||||
|
|
||||||
|
render(r: Renderer): void {
|
||||||
|
for (const { component, x, y } of this.components) {
|
||||||
|
component.render(r, x * 32 + 16, y * 32 + 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Component {
|
||||||
|
get width(): number;
|
||||||
|
get height(): number;
|
||||||
|
render(r: Renderer, x: number, y: number): void;
|
||||||
|
click?(x: number, y: number): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComponentFactory {
|
||||||
|
newInstance(): Component;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SwitchComponent implements Component, ComponentFactory {
|
||||||
|
private graphicOn = new Painter(96, 64);
|
||||||
|
private graphicOff = new Painter(96, 64);
|
||||||
|
|
||||||
|
private switchOn = false;
|
||||||
|
|
||||||
|
public width = 1;
|
||||||
|
public height = 1;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.p.clear("black");
|
this.graphicOff.fillRect(64, 30, 16, 4, "black");
|
||||||
|
this.graphicOff.fillCirc(48 + 32, 32, 8, "black");
|
||||||
|
this.graphicOff.fillCirc(48, 32, 16, "black");
|
||||||
|
|
||||||
|
this.graphicOn.fillRect(64, 30, 16, 4, "black");
|
||||||
|
this.graphicOn.fillCirc(48 + 32, 32, 8, "black");
|
||||||
|
this.graphicOn.fillCirc(48, 32, 16, "red");
|
||||||
}
|
}
|
||||||
|
|
||||||
render(r: Renderer) {
|
newInstance(): Component {
|
||||||
this.p.render(r, 0, 0);
|
return new SwitchComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(r: Renderer, x: number, y: number): void {
|
||||||
|
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||||
|
graphic.render(r, x - 48, y - 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
click(x: number, y: number): void {
|
||||||
|
const onButton = Math.sqrt(
|
||||||
|
(x - 16) ** 2 + (y - 16) ** 2,
|
||||||
|
) <= 16;
|
||||||
|
|
||||||
|
if (onButton) {
|
||||||
|
this.switchOn = !this.switchOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LedComponent implements Component, ComponentFactory {
|
||||||
|
private graphicOn = new Painter(96, 64);
|
||||||
|
private graphicOff = new Painter(96, 64);
|
||||||
|
|
||||||
|
private switchOn = false;
|
||||||
|
|
||||||
|
public width = 1;
|
||||||
|
public height = 1;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.graphicOff.fillRect(16, 30, 16, 4, "black");
|
||||||
|
this.graphicOff.fillCirc(16, 32, 8, "black");
|
||||||
|
this.graphicOff.fillCirc(48, 32, 16, "black");
|
||||||
|
|
||||||
|
this.graphicOn.fillRect(16, 30, 16, 4, "black");
|
||||||
|
this.graphicOn.fillCirc(16, 32, 8, "black");
|
||||||
|
this.graphicOn.fillCirc(48, 32, 16, "red");
|
||||||
|
}
|
||||||
|
|
||||||
|
newInstance(): Component {
|
||||||
|
return new LedComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(r: Renderer, x: number, y: number): void {
|
||||||
|
const graphic = this.switchOn ? this.graphicOn : this.graphicOff;
|
||||||
|
graphic.render(r, x - 48, y - 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
<title>LogiCirc</title>
|
<title>LogiCirc</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<script>0</script>
|
||||||
<canvas id="editor"></canvas>
|
<canvas id="editor"></canvas>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user