webgl_game/src/js/draw.js

177 lines
7.2 KiB
JavaScript

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);
}