@storiny/obelisk
Version:
Build isometrics elements with canvas
180 lines (156 loc) • 4.8 kB
text/typescript
import { PyramidDimension } from "../dimensions";
import { PyramidColor } from "../colors";
import { Matrix } from "../geom";
import { BitmapData } from "../display/BitmapData";
import { AbstractPrimitive } from "./AbstractPrimitive";
export class Pyramid extends AbstractPrimitive {
private readonly hSize: number;
private readonly hOffset: number;
constructor(
dimension?: PyramidDimension,
color?: PyramidColor,
border?: boolean,
useDefaultCanvas?: boolean
) {
super();
this.useDefaultCanvas = useDefaultCanvas || false;
this.border = border || border === undefined;
this.dimension =
dimension === undefined ? new PyramidDimension() : dimension;
this.color = color === undefined ? new PyramidColor() : color;
this.hSize = this.dimension.tall
? this.dimension!.xAxis! * 2
: this.dimension!.xAxis!;
this.hOffset = this.dimension.tall ? -3 : -2;
this.initRectangle();
this.initBitmapData();
this.build();
this.renderBitmapDataForCanvas();
}
private initRectangle(): void {
this.w = this.dimension!.xAxis! + this.dimension!.yAxis!;
this.h = this.hSize + this.dimension!.xAxis! / 2;
// 22.6 degrees implementation
this.w -= 2;
this.h += this.hOffset;
// The matrix offset between the bitmap and the 3d pixel coordinate zero point
this.matrix = new Matrix();
this.matrix.tx = -this.dimension!.xAxis! + 2;
this.matrix.ty =
-this.hSize / 2 +
2 -
(this.dimension!.tall ? this.dimension!.xAxis! / 2 : 1);
}
private initBitmapData(): void {
this.bitmapData = new BitmapData(
this.w!,
this.h!,
this.useDefaultCanvas || undefined
);
}
private renderBitmapDataForCanvas(): void {
this.bitmapData!.context!.putImageData(this.bitmapData!.imageData!, 0, 0);
this.canvas = this.bitmapData!.canvas;
}
private build(): void {
const colorBorderLeft = this.border
? this.color!.border!
: this.color!.left!;
const colorBorderRight = this.border
? this.color!.border!
: this.color!.right!;
const colorBorderHighlight = this.border
? this.color!.borderHighlight!
: colorBorderLeft;
// Z axis highlight
for (let k = 0; k < this.hSize + this.dimension!.xAxis! / 2 - 4; k += 1) {
this.bitmapData!.setPixel(
this.dimension!.xAxis! - 2,
k + 3 + this.hOffset,
colorBorderHighlight
);
}
// X axis
for (let i = 0; i < this.dimension!.xAxis!; i += 1) {
this.bitmapData!.setPixel(
i,
this.hSize + Math.floor(i / 2) + this.hOffset,
colorBorderLeft
);
}
// Y axis
for (let j = 0; j < this.dimension!.xAxis!; j += 1) {
this.bitmapData!.setPixel(
j + this.dimension!.xAxis! - 2,
this.hSize +
this.dimension!.xAxis! / 2 -
Math.floor(j / 2) -
1 +
this.hOffset,
colorBorderRight
);
}
if (!this.dimension!.tall) {
// Left edge
for (let l = 0; l < this.hSize; l += 1) {
this.bitmapData!.setPixel(
l,
this.hSize - l + this.hOffset,
colorBorderLeft
);
}
// Right edge
for (let m = 0; m < this.hSize; m += 1) {
this.bitmapData!.setPixel(
m + this.hSize - 2,
m + 1 + this.hOffset,
colorBorderRight
);
}
} else {
// Left edge
for (let l = 0; l < this.hSize - 2; l += 1) {
this.bitmapData!.setPixel(
Math.floor(l / 2),
this.hSize - l + this.hOffset,
colorBorderLeft
);
}
// Right edge
for (let m = 2; m < this.hSize; m += 1) {
this.bitmapData!.setPixel(
Math.floor(m / 2) + this.dimension!.xAxis! - 2,
m + 1 + this.hOffset,
colorBorderRight
);
}
}
if (!this.border) {
this.bitmapData!.setPixel(
this.dimension!.xAxis! - 2,
this.hSize + this.dimension!.xAxis! / 2 - 1 + this.hOffset,
colorBorderLeft
);
}
// floodFill
this.bitmapData!.floodFill(
this.dimension!.xAxis! - 1,
this.hSize +
Math.floor((this.dimension!.xAxis! - 1) / 2) +
this.hOffset -
1,
this.color!.right!
);
this.bitmapData!.floodFill(
this.dimension!.xAxis! - 3,
this.hSize +
Math.floor((this.dimension!.xAxis! - 1) / 2) +
this.hOffset -
2,
this.color!.left!
);
}
public static override toString(): string {
return "[Pyramid]";
}
}