1
0
Fork 0

BrickDisplay system

This commit is contained in:
Pabloader 2026-05-03 15:38:40 +00:00
parent 32927d5623
commit 4a5f0b3757
3 changed files with 63 additions and 25 deletions

View File

@ -1,7 +1,6 @@
import { render } from "preact";
import type { ReactElement } from "preact/compat";
import { clamp, range } from "@common/utils";
import clsx from "clsx";
import { render, type ComponentChildren } from "preact";
import styles from './assets/brick.module.css';
import "./assets/lcd.font.css";
@ -12,10 +11,16 @@ const FIELD_HEIGHT = 20;
const MINI_FIELD_WIDTH = 4;
const MINI_FIELD_HEIGHT = 4;
export interface BrickDisplayImage {
image: boolean[];
width: number;
height: number;
export class BrickDisplayImage {
public image: boolean[];
public width: number;
public height: number;
constructor(image: boolean[] = [], width: number = 0, height: number = 0) {
this.image = image;
this.width = width;
this.height = height;
}
}
export class BrickDisplay {
@ -26,7 +31,7 @@ export class BrickDisplay {
#level: number = 1;
public pause: boolean = false;
public gameOver: boolean = false;
public helpText: string | ReactElement = '';
public helpText: ComponentChildren = '';
init() {
this.update();
@ -37,7 +42,7 @@ export class BrickDisplay {
}
set score(value) {
this.#score = Math.max(0, (value | 0) % 1000000000);
this.#score = Math.max(0, (value | 0) % 1_000_000_000);
}
get speed() {
@ -243,11 +248,7 @@ export class BrickDisplay {
}
static convertImage(image: HTMLImageElement): BrickDisplayImage {
const result: BrickDisplayImage = {
image: [],
width: 0,
height: 0,
}
const result = new BrickDisplayImage();
const canvas = document.createElement('canvas');
result.width = canvas.width = image.naturalWidth;
@ -267,7 +268,7 @@ export class BrickDisplay {
static extractSprite(image: BrickDisplayImage, x: number, y: number, w: number, h: number): BrickDisplayImage {
if (w <= 0 || h <= 0 || x >= image.width || y >= image.height) {
return { image: [], width: 0, height: 0 };
return new BrickDisplayImage();
}
x = clamp(x | 0, 0, image.width);
@ -276,11 +277,7 @@ export class BrickDisplay {
w = clamp(w | 0, 1, image.width - x);
h = clamp(h | 0, 1, image.height - y);
const result: BrickDisplayImage = {
image: new Array(w * h),
width: w,
height: h,
}
const result = new BrickDisplayImage(new Array(w * h), w, h);
for (let j = 0; j < h; j++) {
for (let i = 0; i < w; i++) {
@ -320,11 +317,11 @@ export class BrickDisplay {
static rotateSprite(image: BrickDisplayImage, angle: 0 | 90 | 180 | 270): BrickDisplayImage {
if (angle === 0) return this.copySprite(image);
const newImage: BrickDisplayImage = {
image: new Array(image.width * image.height),
width: angle === 180 ? image.width : image.height,
height: angle === 180 ? image.height : image.width,
}
const newImage = new BrickDisplayImage(
new Array(image.width * image.height),
angle === 180 ? image.width : image.height,
angle === 180 ? image.height : image.width,
);
for (let j = 0; j < image.height; j++) {
for (let i = 0; i < image.width; i++) {
@ -351,4 +348,4 @@ export class BrickDisplay {
return newImage;
}
}
}

View File

@ -0,0 +1,9 @@
import { Component } from "@common/rpg/core/world";
import { component } from "@common/rpg/utils/decorators";
@component
export class BrickSprite extends Component<{ xor: boolean, miniDisplay: boolean }> {
constructor(miniDisplay: boolean, xor: boolean) {
super({ xor, miniDisplay });
}
}

View File

@ -0,0 +1,32 @@
import { BrickDisplay, BrickDisplayImage } from "@common/display/brick";
import { Position } from "@common/rpg/components/position";
import { BrickSprite } from "@common/rpg/components/render/brick";
import { Hidden, Sprite } from "@common/rpg/components/sprite";
import { System, World } from "@common/rpg/core/world";
import { Resources } from "@common/rpg/utils/resources";
export class BrickDisplaySystem extends System {
public readonly display: BrickDisplay;
constructor(display?: BrickDisplay) {
super();
this.display = display ?? new BrickDisplay();
}
override update(world: World) {
const sprites = Array.from(world.query(Sprite, Position)).sort((a, b) => a[2].state.z - b[2].state.z);
for (const [e, sprite, pos] of sprites) {
if (e.has(Hidden)) continue;
const { xor = false, miniDisplay = false } = e.get(BrickSprite)?.state ?? {};
const { x, y } = pos.state;
const data = Resources.get(BrickDisplayImage, sprite.image);
if (!data) {
throw new Error('No image data found for sprite');
}
this.display.drawImage(data, x, y, miniDisplay, xor);
}
}
}