the-world-engine
Version:
three.js based, unity like game engine for browser
240 lines (235 loc) • 7.91 kB
JavaScript
import { Vector2 } from "three/src/Three";
import { Transform } from "../../hierarchy_object/Transform";
import { CssRenderer } from "./CssRenderer";
import { ImageRenderingMode } from "./CssSpriteRenderer";
export class TileAtlasItem {
tl;
xa;
Ra;
constructor(t, i = 1, s = 1) {
if (!t.complete) {
throw new Error(`Image {${t.src}} is not loaded.`);
}
this.tl = t;
this.Ra = s;
this.xa = i;
}
get htmlImageElement() {
return this.tl;
}
get columnCount() {
return this.xa;
}
get rowCount() {
return this.Ra;
}
}
export class CssTilemapRenderer extends CssRenderer {
xa=10;
Ra=10;
tn=1;
en=1;
sn=16;
rn=16;
nn=null;
cn=ImageRenderingMode.Pixelated;
$h=[];
renderInitialize() {
this.il();
const t = this.$h;
for (let i = 0; i < t.length; ++i) {
t[i]();
}
this.$h.length = 0;
}
updateCenterOffset(t) {
if (!this.css3DObject) return;
const i = this.xa * this.tn;
const s = this.Ra * this.en;
this.css3DObject.position.set(i * this.centerOffset.x, s * this.centerOffset.y, 0);
if (t) {
Transform.updateRawObject3DWorldMatrixRecursively(this.css3DObject);
this.transform.enqueueRenderAttachedObject3D(this.css3DObject);
}
}
updateViewScale(t) {
if (!this.css3DObject) return;
const i = this.viewScale;
const s = this.htmlElement;
const e = this.xa * this.tn;
const h = this.Ra * this.en;
s.style.width = e / i + "px";
s.style.height = h / i + "px";
this.css3DObject.scale.set(i, i, i);
if (t) {
Transform.updateRawObject3DWorldMatrixRecursively(this.css3DObject);
this.transform.enqueueRenderAttachedObject3D(this.css3DObject);
}
}
il() {
const t = this.xa * this.tn;
const i = this.Ra * this.en;
const s = this.xa * this.sn;
const e = this.Ra * this.rn;
this.htmlElement = document.createElement("canvas");
this.htmlElement.width = s;
this.htmlElement.height = e;
this.htmlElement.style.imageRendering = this.cn;
this.htmlElement.style.width = t / this.viewScale + "px";
this.htmlElement.style.height = i / this.viewScale + "px";
const h = this.initializeBaseComponents(false);
Transform.updateRawObject3DWorldMatrixRecursively(h);
this.transform.enqueueRenderAttachedObject3D(h);
}
drawTile(t, i, s, e) {
if (!this.readyToDraw) {
this.$h.push((() => this.drawTile(t, i, s, e)));
return;
}
const h = this.htmlElement.getContext("2d");
const r = this.nn[s];
if (r.rowCount === 1 && r.columnCount === 1) {
h.drawImage(r.htmlImageElement, 0, 0, this.sn, this.rn, t * this.sn, i * this.rn, this.sn, this.rn);
} else if (e !== undefined) {
const s = Math.floor(e / r.columnCount);
const n = e % r.columnCount;
const o = r.htmlImageElement.width / r.columnCount;
const l = r.htmlImageElement.height / r.rowCount;
h.drawImage(r.htmlImageElement, n * o, s * l, o, l, t * this.sn, i * this.rn, this.sn, this.rn);
} else {
throw new Error("Atlas index is required.");
}
}
drawTileFromTwoDimensionalArray(t, i, s) {
if (!this.readyToDraw) {
this.$h.push((() => this.drawTileFromTwoDimensionalArray(t, i, s)));
return;
}
const e = this.htmlElement.getContext("2d");
for (let h = 0; h < t.length; h++) {
const r = t[h];
for (let t = 0; t < r.length; t++) {
const n = r[t];
if (n === null) continue;
const o = this.nn[n.i];
if (o.rowCount === 1 && o.columnCount === 1) {
e.drawImage(o.htmlImageElement, 0, 0, this.sn, this.rn, t * this.sn + i * this.sn, h * this.rn + s * this.rn, this.sn, this.rn);
} else if (n.a !== undefined) {
const r = n.a % o.columnCount;
const l = Math.floor(n.a / o.columnCount);
const c = o.htmlImageElement.width / o.columnCount;
const u = o.htmlImageElement.height / o.rowCount;
e.drawImage(o.htmlImageElement, r * c, l * u, c, u, t * this.sn + i * this.sn, h * this.rn + s * this.rn, this.sn, this.rn);
} else {
throw new Error("Atlas index is required.");
}
}
}
}
clearTile(t, i) {
if (!this.readyToDraw) {
this.$h.push((() => this.clearTile(t, i)));
return;
}
const s = this.htmlElement.getContext("2d");
s.clearRect(t * this.sn, i * this.rn, this.sn, this.rn);
}
set imageSources(t) {
if (!this.readyToDraw) {
this.$h.push((() => this.imageSources = t));
return;
}
this.nn = t;
for (let i = 0; i < t.length; ++i) {
if (!t[i].htmlImageElement.complete) throw new Error(`Image ${t[i].htmlImageElement.src} is not loaded.`);
}
}
get columnCount() {
return this.xa;
}
set columnCount(t) {
this.xa = t;
if (this.htmlElement) {
const t = this.xa * this.tn;
const i = this.xa * this.sn;
this.htmlElement.width = i;
this.htmlElement.style.width = t / this.viewScale + "px";
this.updateCenterOffset(true);
}
}
get rowCount() {
return this.Ra;
}
set rowCount(t) {
this.Ra = t;
if (this.htmlElement) {
const t = this.Ra * this.en;
const i = this.Ra * this.rn;
this.htmlElement.height = i;
this.htmlElement.style.height = t / this.viewScale + "px";
this.updateCenterOffset(true);
}
}
get gridCellWidth() {
return this.tn;
}
set gridCellWidth(t) {
this.tn = t;
if (this.htmlElement) {
const t = this.xa * this.tn;
this.htmlElement.style.width = t / this.viewScale + "px";
this.updateCenterOffset(true);
}
}
get gridCellHeight() {
return this.en;
}
set gridCellHeight(t) {
this.en = t;
if (this.htmlElement) {
const t = this.Ra * this.en;
this.htmlElement.style.height = t / this.viewScale + "px";
this.updateCenterOffset(true);
}
}
get tileResolutionX() {
return this.sn;
}
set tileResolutionX(t) {
this.sn = t;
if (this.htmlElement) {
const t = this.xa * this.sn;
this.htmlElement.width = t;
}
}
get tileResolutionY() {
return this.rn;
}
set tileResolutionY(t) {
this.rn = t;
if (this.htmlElement) {
const t = this.Ra * this.rn;
this.htmlElement.height = t;
}
}
get gridCenter() {
const t = this.columnCount % 2 === 1 ? 0 : this.tn / 2;
const i = this.rowCount % 2 === 1 ? 0 : this.en / 2;
return new Vector2(this.transform.position.x + t, this.transform.position.y + i);
}
get gridCenterX() {
return this.transform.position.x + (this.columnCount % 2 === 1 ? 0 : this.tn / 2);
}
get gridCenterY() {
return this.transform.position.y + (this.rowCount % 2 === 1 ? 0 : this.en / 2);
}
get imageRenderingMode() {
return this.cn;
}
set imageRenderingMode(t) {
this.cn = t;
if (this.htmlElement) {
this.htmlElement.style.imageRendering = this.cn;
}
}
}