UNPKG

@storiny/obelisk

Version:

Build isometrics elements with canvas

180 lines (156 loc) 4.8 kB
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]"; } }