import { Vec3, Mat4, Vec4 } from "./common.js"; import { DrawTag, Sprite } from "./graphics.js"; import { TileEdge } from "./world.js"; import * as Assets from "./assets.js"; // Attrib format // position color uv // (3) (4) (3) => 3 + 4 + 3 = 10 <=> vertexSize == 10 export class Rectangle { attribs = ["a_position", "a_color", "a_tex"]; tags = []; data = []; vertexSize = 10; sprites = Assets.assets.get("sprites"); constructor(tags, sprites, attribs) { if (sprites !== undefined) { this.sprites = sprites; } if (attribs !== undefined) { this.attribs = attribs; } if (tags !== undefined) { this.tags = tags; } } commit(gfx) { gfx.toRender.push(this); } draw(corners, fill) { if (fill instanceof Sprite) { let uvs = Assets.assets.get("sprites").getUVs(fill.id); let data = [ corners[0].x, corners[0].y, corners[0].z, 0, 0, 0, 0, uvs[0].x, uvs[0].y, 1, corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, uvs[1].x, uvs[1].y, 1, corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, uvs[3].x, uvs[3].y, 1, corners[2].x, corners[2].y, corners[2].z, 0, 0, 0, 0, uvs[2].x, uvs[2].y, 1, corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, uvs[1].x, uvs[1].y, 1, corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, uvs[3].x, uvs[3].y, 1, ]; for (let i = 0; i < data.length; ++i) { this.data.push(data[i]); } } else { let color = fill; let data = [ corners[0].x, corners[0].y, corners[0].z, color[0], color[1], color[2], color[3], 0, 0, 0, corners[1].x, corners[1].y, corners[1].z, color[0], color[1], color[2], color[3], 0, 0, 0, corners[3].x, corners[3].y, corners[3].z, color[0], color[1], color[2], color[3], 0, 0, 0, corners[2].x, corners[2].y, corners[2].z, color[0], color[1], color[2], color[3], 0, 0, 0, corners[1].x, corners[1].y, corners[1].z, color[0], color[1], color[2], color[3], 0, 0, 0, corners[3].x, corners[3].y, corners[3].z, color[0], color[1], color[2], color[3], 0, 0, 0, ]; for (let i = 0; i < data.length; ++i) { this.data.push(data[i]); } } } drawExts(position, exts, fill) { if (fill instanceof Sprite) { let uvs = Assets.assets.get("sprites").getUVs(fill.id); let data = [ position.x, position.y, position.z, 0, 0, 0, 0, uvs[0].x, uvs[0].y, 1, position.x + exts.x, position.y, position.z, 0, 0, 0, 0, uvs[1].x, uvs[1].y, 1, position.x, position.y + exts.y, position.z, 0, 0, 0, 0, uvs[3].x, uvs[3].y, 1, position.x + exts.x, position.y + exts.y, position.z, 0, 0, 0, 0, uvs[2].x, uvs[2].y, 1, position.x + exts.x, position.y, position.z, 0, 0, 0, 0, uvs[1].x, uvs[1].y, 1, position.x, position.y + exts.y, position.z, 0, 0, 0, 0, uvs[3].x, uvs[3].y, 1, ]; for (let i = 0; i < data.length; ++i) { this.data.push(data[i]); } } else { let color = fill; let data = [ position.x, position.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, position.x + exts.x, position.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, position.x, position.y + exts.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, position.x + exts.x, position.y + exts.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, position.x + exts.x, position.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, position.x, position.y + exts.y, position.z, color[0], color[1], color[2], color[3], 0, 0, 0, ]; for (let i = 0; i < data.length; ++i) { this.data.push(data[i]); } } } } export function drawIsometricCube(position, exts, r, fill, edge) { let points = [ // Left Top position, //Top new Vec3(position.x, position.y + exts.y, position.z), //Mid new Vec3(position.x + exts.x, position.y, position.z), //Right Top new Vec3(position.x + exts.x, position.y + exts.y, position.z), //Bottom new Vec3(position.x + 1.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), new Vec3(position.x + 1.5 * exts.x, position.y + 0.5 * exts.y, position.z + 0.25 * exts.z), new Vec3(position.x + 0.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), ]; // Top r.draw([ points[0], points[1], points[3], points[2], ], fill.top); // Right Edge if (edge == TileEdge.Right || edge == TileEdge.Both) { r.draw([ points[3], points[2], points[4], points[5], ], fill.right); } // Left Edge if (edge == TileEdge.Left || edge == TileEdge.Both) { r.draw([ points[0], points[2], points[4], points[6], ], fill.left); } } // TODO: Optimize the shit out of this function export function drawIsometricGrid(gfx, camera, grid) { let position = grid.position.copy(); let exts = new Vec3(grid.tileSize, grid.tileSize, 0); let tileCoord = new Vec3(0, 0, 0); let rect = new Rectangle([ DrawTag.ISO, ]); let mt = Mat4.translate(camera.position.multScalarNew(-1.0)); let mi = Mat4.isometric(); let bias = 4 * grid.tileSize; let bb = [ new Vec3(-bias, -bias, 0), new Vec3(gfx.width() + bias, -bias, 0), new Vec3(gfx.width() + bias, gfx.height() + bias, 0), new Vec3(-bias, gfx.height() + bias, 0), ]; for (let i = 0; i < bb.length; ++i) { bb[i] = mt.transformNew(bb[i].extend(1.0)).reduce(); } for (let k = 0; k < grid.topHeight; ++k) { for (let j = 0; j < grid.breadth; ++j) { for (let i = 0; i < grid.width; ++i) { tileCoord.x = i; tileCoord.y = j; tileCoord.z = k; let tile = grid.getTile(tileCoord); if (tile === null) { position.x += grid.tileSize; continue; } const ipos = mi.transformNew(new Vec4(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, 1.0, 1.0)).reduce(); if (ipos.x >= bb[2].x || ipos.x <= bb[0].x || ipos.y >= bb[2].y || ipos.y <= bb[0].y) { position.x += grid.tileSize; continue; } drawIsometricCube(new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, rect, tile.fill, tile.edge); position.x += grid.tileSize; } position.y -= grid.tileSize; position.x = grid.position.x; } position.y = grid.position.y; } rect.commit(gfx); }