class IsometricEngine {
constructor(canvas) {
this.ctx = canvas.getContext('2d');
this.tileWidth = 64;
this.tileHeight = 32;
this.voxels = new Map();
}
project(x, y, z) {
const screenX = (x - y) * this.tileWidth / 2;
const screenY = (x + y) * this.tileHeight / 2 - z * this.tileHeight;
return { x: screenX, y: screenY };
}
drawVoxel(vx, vy, vz, type) {
const pos = this.project(vx, vy, vz);
const colors = this.getPalette(type);
this.ctx.fillStyle = colors.top;
this.ctx.beginPath();
this.ctx.moveTo(pos.x, pos.y);
this.ctx.lineTo(pos.x + 32, pos.y - 16);
this.ctx.lineTo(pos.x, pos.y - 32);
this.ctx.lineTo(pos.x - 32, pos.y - 16);
this.ctx.closePath();
this.ctx.fill();
this.ctx.fillStyle = colors.left;
this.ctx.beginPath();
this.ctx.moveTo(pos.x - 32, pos.y - 16);
this.ctx.lineTo(pos.x, pos.y - 32);
this.ctx.lineTo(pos.x, pos.y);
this.ctx.lineTo(pos.x - 32, pos.y + 16);
this.ctx.closePath();
this.ctx.fill();
this.ctx.fillStyle = colors.right;
this.ctx.beginPath();
this.ctx.moveTo(pos.x, pos.y - 32);
this.ctx.lineTo(pos.x + 32, pos.y - 16);
this.ctx.lineTo(pos.x + 32, pos.y + 16);
this.ctx.lineTo(pos.x, pos.y);
this.ctx.closePath();
this.ctx.fill();
}
render() {
const sorted = [...this.voxels.values()]
.sort((a, b) => (a.x + a.y + a.z) - (b.x + b.y + b.z));
for (const v of sorted) {
this.drawVoxel(v.x, v.y, v.z, v.type);
}
}
}