Compare commits
No commits in common. "87ad6fbd9dc60e135b313d15ed3f68cb0b86a341" and "3e9bdcc46900a2150faaa428be99ee25b0409b80" have entirely different histories.
87ad6fbd9d
...
3e9bdcc469
Before Width: | Height: | Size: 1.0 KiB |
|
@ -1,3 +0,0 @@
|
||||||
For a description of the contents of this pack, usage rights, and other useful details, go here:
|
|
||||||
|
|
||||||
http://blog.spiralgraphics.biz/2011/02/nine-cartoon-backdrops.html
|
|
Before Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 82 KiB |
BIN
assets/grass.png
Before Width: | Height: | Size: 368 B |
Before Width: | Height: | Size: 511 B |
Before Width: | Height: | Size: 411 B |
BIN
assets/log.png
Before Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 1.1 KiB |
BIN
assets/wall.png
Before Width: | Height: | Size: 4.2 KiB |
|
@ -1,36 +0,0 @@
|
||||||
import { Texture } from "./graphics.js";
|
|
||||||
export const Colors = {
|
|
||||||
Red: [1, 0, 0, 1],
|
|
||||||
Green: [0, 1, 0, 1],
|
|
||||||
Blue: [0, 0, 1, 1],
|
|
||||||
Brown: [0.341, 0.337, 0.204, 1],
|
|
||||||
};
|
|
||||||
export function AssetToTileFill(name) {
|
|
||||||
let asset = assets.get(name);
|
|
||||||
return {
|
|
||||||
left: asset,
|
|
||||||
top: asset,
|
|
||||||
right: asset,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export class Assets {
|
|
||||||
assets = new Map();
|
|
||||||
loaded = false;
|
|
||||||
push(name, asset) {
|
|
||||||
if (this.assets.get(name) !== undefined)
|
|
||||||
throw new Error("Asset name occupied!");
|
|
||||||
this.assets.set(name, asset);
|
|
||||||
}
|
|
||||||
get(name) {
|
|
||||||
if (!this.loaded)
|
|
||||||
throw new Error("Tried to assess assets without loading them!");
|
|
||||||
return this.assets.get(name);
|
|
||||||
}
|
|
||||||
async load(gfx) {
|
|
||||||
assets.push("grass", await Texture.load(gfx, "../../assets/grass2.png"));
|
|
||||||
assets.push("leaves", await Texture.load(gfx, "../../assets/greenary.png"));
|
|
||||||
assets.push("log", await Texture.load(gfx, "../../assets/log.png"));
|
|
||||||
this.loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const assets = new Assets();
|
|
|
@ -1,52 +0,0 @@
|
||||||
import {Graphics, Texture} from "./graphics.js";
|
|
||||||
import {TileFill} from "./world.js";
|
|
||||||
|
|
||||||
export type Color = [number, number, number, number]
|
|
||||||
|
|
||||||
export const Colors = {
|
|
||||||
Red : [1, 0, 0, 1] as Color,
|
|
||||||
Green : [0, 1, 0, 1] as Color,
|
|
||||||
Blue : [0, 0, 1, 1] as Color,
|
|
||||||
Brown : [0.341, 0.337, 0.204, 1] as Color,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Asset = Texture;
|
|
||||||
|
|
||||||
export function AssetToTileFill(name: string): TileFill {
|
|
||||||
let asset = assets.get(name);
|
|
||||||
|
|
||||||
return {
|
|
||||||
left: asset,
|
|
||||||
top: asset,
|
|
||||||
right: asset,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Assets {
|
|
||||||
assets: Map<string, Asset> = new Map();
|
|
||||||
loaded: boolean = false;
|
|
||||||
|
|
||||||
push(name: string, asset: Asset) {
|
|
||||||
if (this.assets.get(name) !== undefined)
|
|
||||||
throw new Error("Asset name occupied!");
|
|
||||||
|
|
||||||
this.assets.set(name, asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
get(name: string): Asset {
|
|
||||||
if (!this.loaded)
|
|
||||||
throw new Error("Tried to assess assets without loading them!");
|
|
||||||
|
|
||||||
return this.assets.get(name)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
async load(gfx: Graphics) {
|
|
||||||
assets.push("grass", await Texture.load(gfx, "../../assets/grass2.png"));
|
|
||||||
assets.push("leaves", await Texture.load(gfx, "../../assets/greenary.png"));
|
|
||||||
assets.push("log", await Texture.load(gfx, "../../assets/log.png"));
|
|
||||||
|
|
||||||
this.loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const assets = new Assets();
|
|
344
src/js/common.js
|
@ -10,9 +10,6 @@ class Vec2 {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
copy() {
|
|
||||||
return new Vec2(this.x, this.y);
|
|
||||||
}
|
|
||||||
add(other) {
|
add(other) {
|
||||||
this.x += other.x;
|
this.x += other.x;
|
||||||
this.y += other.y;
|
this.y += other.y;
|
||||||
|
@ -31,43 +28,13 @@ class Vec2 {
|
||||||
this.x -= other.x;
|
this.x -= other.x;
|
||||||
this.y -= other.y;
|
this.y -= other.y;
|
||||||
}
|
}
|
||||||
subNew(other) {
|
mult(scalar) {
|
||||||
let vec = this.copy();
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
multScalar(scalar) {
|
|
||||||
this.x *= scalar;
|
this.x *= scalar;
|
||||||
this.y *= scalar;
|
this.y *= scalar;
|
||||||
}
|
}
|
||||||
multScalarNew(scalar) {
|
multNew(scalar) {
|
||||||
return new Vec2(this.x * scalar, this.y * scalar);
|
return new Vec2(this.x * scalar, this.y * scalar);
|
||||||
}
|
}
|
||||||
div(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
}
|
|
||||||
divNew(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
reduce() {
|
|
||||||
throw new Error("Can't reduce Vec2!");
|
|
||||||
}
|
|
||||||
extend(value) {
|
|
||||||
return new Vec3(this.x, this.y, value);
|
|
||||||
}
|
|
||||||
splatToArray() {
|
splatToArray() {
|
||||||
return [this.x, this.y];
|
return [this.x, this.y];
|
||||||
}
|
}
|
||||||
|
@ -93,320 +60,15 @@ class Vec3 {
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
copy() {
|
|
||||||
return new Vec3(this.x, this.y, this.z);
|
|
||||||
}
|
|
||||||
add(other) {
|
add(other) {
|
||||||
this.x += other.x;
|
this.x += other.x;
|
||||||
this.y += other.y;
|
this.y += other.y;
|
||||||
this.z += other.z;
|
this.z += other.z;
|
||||||
}
|
}
|
||||||
addNew(other) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x += other.x;
|
|
||||||
vec.y += other.y;
|
|
||||||
vec.z += other.z;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
sub(other) {
|
sub(other) {
|
||||||
this.x -= other.x;
|
this.x -= other.x;
|
||||||
this.y -= other.y;
|
this.y -= other.y;
|
||||||
this.z -= other.z;
|
this.z -= other.z;
|
||||||
}
|
}
|
||||||
subNew(other) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
vec.z -= other.z;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
multScalar(scalar) {
|
|
||||||
this.x *= scalar;
|
|
||||||
this.y *= scalar;
|
|
||||||
this.z *= scalar;
|
|
||||||
}
|
|
||||||
multScalarNew(scalar) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x *= scalar;
|
|
||||||
vec.y *= scalar;
|
|
||||||
vec.z *= scalar;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
div(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
this.z /= other.z;
|
|
||||||
}
|
|
||||||
divNew(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
vec.z /= other.z;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
reduce() {
|
|
||||||
return new Vec2(this.x, this.y);
|
|
||||||
}
|
|
||||||
extend(value) {
|
|
||||||
return new Vec4(this.x, this.y, this.z, value);
|
|
||||||
}
|
|
||||||
splatToArray() {
|
|
||||||
return [this.x, this.y, this.z];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
class Vec4 {
|
export { initializeContext, Vec2, Vec3 };
|
||||||
x;
|
|
||||||
y;
|
|
||||||
z;
|
|
||||||
w;
|
|
||||||
constructor(x, y, z, w) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.w = w;
|
|
||||||
}
|
|
||||||
copy() {
|
|
||||||
return new Vec4(this.x, this.y, this.z, this.w);
|
|
||||||
}
|
|
||||||
add(other) {
|
|
||||||
this.x += other.x;
|
|
||||||
this.y += other.y;
|
|
||||||
this.z += other.z;
|
|
||||||
this.w += other.w;
|
|
||||||
}
|
|
||||||
addNew(other) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x += other.x;
|
|
||||||
vec.y += other.y;
|
|
||||||
vec.z += other.z;
|
|
||||||
vec.w += other.w;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
sub(other) {
|
|
||||||
this.x -= other.x;
|
|
||||||
this.y -= other.y;
|
|
||||||
this.z -= other.z;
|
|
||||||
this.w -= other.w;
|
|
||||||
}
|
|
||||||
subNew(other) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
vec.z -= other.z;
|
|
||||||
vec.w -= other.w;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
multScalar(scalar) {
|
|
||||||
this.x *= scalar;
|
|
||||||
this.y *= scalar;
|
|
||||||
this.z *= scalar;
|
|
||||||
this.w *= scalar;
|
|
||||||
}
|
|
||||||
multScalarNew(scalar) {
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x *= scalar;
|
|
||||||
vec.y *= scalar;
|
|
||||||
vec.z *= scalar;
|
|
||||||
vec.w *= scalar;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
div(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0 ||
|
|
||||||
other.w == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
this.z /= other.z;
|
|
||||||
this.w /= other.w;
|
|
||||||
}
|
|
||||||
divNew(other) {
|
|
||||||
if (other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0 ||
|
|
||||||
other.w == 0) {
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
let vec = this.copy();
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
vec.z /= other.z;
|
|
||||||
vec.w /= other.w;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
reduce() {
|
|
||||||
return new Vec3(this.x, this.y, this.z);
|
|
||||||
}
|
|
||||||
extend(_value) {
|
|
||||||
throw new Error("Can't extend Vec4");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class Mat4 {
|
|
||||||
data;
|
|
||||||
constructor(i) {
|
|
||||||
if (i instanceof Float32Array) {
|
|
||||||
console.assert(i.length == 16, "Mat4 has to have 16 elements");
|
|
||||||
this.data = i;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (typeof (i) === 'number') {
|
|
||||||
this.data = new Float32Array(16).fill(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.data = new Float32Array(16);
|
|
||||||
}
|
|
||||||
static IDENTITY() {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
static orthographic(left, right, bottom, top, near, far) {
|
|
||||||
let data = new Float32Array([
|
|
||||||
2 / (right - left), 0, 0, 0,
|
|
||||||
0, 2 / (top - bottom), 0, 0,
|
|
||||||
0, 0, -2 / (far - near), 0,
|
|
||||||
-(right + left) / (right - left),
|
|
||||||
-(top + bottom) / (top - bottom),
|
|
||||||
-(far + near) / (far - near),
|
|
||||||
1,
|
|
||||||
]);
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
static isometric() {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, -1, 0, 0,
|
|
||||||
1, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
static isometric_inverse() {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
0.5, 0.5, 0, 0,
|
|
||||||
-0.5, 0.5, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
static rotation_x(angle) {
|
|
||||||
let data = new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, Math.cos(angle), -Math.sin(angle), 0,
|
|
||||||
0, Math.sin(angle), Math.cos(angle), 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
static rotation_y(angle) {
|
|
||||||
let data = new Float32Array([
|
|
||||||
Math.cos(angle), 0, Math.sin(angle), 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
-Math.sin(angle), 0, Math.cos(angle), 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
static rotation_z(angle) {
|
|
||||||
let data = new Float32Array([
|
|
||||||
Math.cos(angle), -Math.sin(angle), 0, 0,
|
|
||||||
Math.sin(angle), Math.cos(angle), 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
static translate(t) {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
t.x, t.y, t.z, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
static scale(scales) {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
scales.x, 0, 0, 0,
|
|
||||||
0, scales.y, 0, 0,
|
|
||||||
0, 0, scales.z, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
x(n) {
|
|
||||||
return this.data[n];
|
|
||||||
}
|
|
||||||
y(n) {
|
|
||||||
return this.data[n + 4];
|
|
||||||
}
|
|
||||||
z(n) {
|
|
||||||
return this.data[n + 8];
|
|
||||||
}
|
|
||||||
w(n) {
|
|
||||||
return this.data[n + 12];
|
|
||||||
}
|
|
||||||
splat() {
|
|
||||||
return Array.from(this.data);
|
|
||||||
}
|
|
||||||
row(row, data) {
|
|
||||||
for (let i = 0; i < data.length; ++i)
|
|
||||||
this.data[i + 4 * row] = data[i];
|
|
||||||
}
|
|
||||||
col(col, data) {
|
|
||||||
for (let i = 0; i < data.length; ++i)
|
|
||||||
this.data[i * 4 + col] = data[i];
|
|
||||||
}
|
|
||||||
transform(v) {
|
|
||||||
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
|
|
||||||
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
|
|
||||||
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
|
|
||||||
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
|
|
||||||
v.x = x;
|
|
||||||
v.y = y;
|
|
||||||
v.z = z;
|
|
||||||
v.w = w;
|
|
||||||
}
|
|
||||||
transformNew(v) {
|
|
||||||
let vec = v.copy();
|
|
||||||
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
|
|
||||||
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
|
|
||||||
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
|
|
||||||
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
|
|
||||||
vec.x = x;
|
|
||||||
vec.y = y;
|
|
||||||
vec.z = z;
|
|
||||||
vec.w = w;
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
multNew(other) {
|
|
||||||
let m = new Mat4(0);
|
|
||||||
for (let i = 0; i < 4; ++i) {
|
|
||||||
for (let j = 0; j < 4; ++j) {
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 0] * other.data[j + 0];
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 1] * other.data[j + 4];
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 2] * other.data[j + 8];
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 3] * other.data[j + 12];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
multScalar(scalar) {
|
|
||||||
for (let i = 0; i < this.data.length; ++i) {
|
|
||||||
this.data[i] *= scalar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export { initializeContext, Mat4, Vec2, Vec3, Vec4 };
|
|
||||||
|
|
471
src/js/common.ts
|
@ -5,27 +5,9 @@ function initializeContext(canvasId: string): WebGL2RenderingContext | null {
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make all vectors follow one interface
|
type Color = [number, number, number, number]
|
||||||
interface Vector<P, T, N> {
|
|
||||||
copy(): T;
|
|
||||||
|
|
||||||
add(other: T): void;
|
class Vec2 {
|
||||||
addNew(other: T): T;
|
|
||||||
|
|
||||||
sub(other: T): void;
|
|
||||||
subNew(other: T): T;
|
|
||||||
|
|
||||||
multScalar(scalar: number): void;
|
|
||||||
multScalarNew(scalar: number): T;
|
|
||||||
|
|
||||||
div(other: T): void;
|
|
||||||
divNew(other: T): T;
|
|
||||||
|
|
||||||
reduce(): P;
|
|
||||||
extend(value: number): N;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Vec2 implements Vector<void, Vec2, Vec3> {
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
|
||||||
|
@ -34,10 +16,6 @@ class Vec2 implements Vector<void, Vec2, Vec3> {
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(): Vec2 {
|
|
||||||
return new Vec2(this.x, this.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(other: Vec2) {
|
add(other: Vec2) {
|
||||||
this.x += other.x;
|
this.x += other.x;
|
||||||
this.y += other.y;
|
this.y += other.y;
|
||||||
|
@ -61,58 +39,15 @@ class Vec2 implements Vector<void, Vec2, Vec3> {
|
||||||
this.y -= other.y;
|
this.y -= other.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
subNew(other: Vec2): Vec2 {
|
mult(scalar: number) {
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalar(scalar: number) {
|
|
||||||
this.x *= scalar;
|
this.x *= scalar;
|
||||||
this.y *= scalar;
|
this.y *= scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
multScalarNew(scalar: number): Vec2 {
|
multNew(scalar: number): Vec2 {
|
||||||
return new Vec2(this.x * scalar, this.y * scalar);
|
return new Vec2(this.x * scalar, this.y * scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
div(other: Vec2) {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
divNew(other: Vec2): Vec2 {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
reduce(): null {
|
|
||||||
throw new Error("Can't reduce Vec2!");
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(value: number): Vec3 {
|
|
||||||
return new Vec3(this.x, this.y, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
splatToArray(): Array<number> {
|
splatToArray(): Array<number> {
|
||||||
return [this.x, this.y];
|
return [this.x, this.y];
|
||||||
}
|
}
|
||||||
|
@ -134,7 +69,7 @@ class Vec2 implements Vector<void, Vec2, Vec3> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Vec3 implements Vector<Vec2, Vec3, Vec4> {
|
class Vec3 {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
z: number;
|
z: number;
|
||||||
|
@ -145,411 +80,17 @@ class Vec3 implements Vector<Vec2, Vec3, Vec4> {
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(): Vec3 {
|
|
||||||
return new Vec3(this.x, this.y, this.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(other: Vec3) {
|
add(other: Vec3) {
|
||||||
this.x += other.x;
|
this.x += other.x;
|
||||||
this.y += other.y;
|
this.y += other.y;
|
||||||
this.z += other.z;
|
this.z += other.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
addNew(other: Vec3): Vec3 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x += other.x;
|
|
||||||
vec.y += other.y;
|
|
||||||
vec.z += other.z;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub(other: Vec3) {
|
sub(other: Vec3) {
|
||||||
this.x -= other.x;
|
this.x -= other.x;
|
||||||
this.y -= other.y;
|
this.y -= other.y;
|
||||||
this.z -= other.z;
|
this.z -= other.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
subNew(other: Vec3): Vec3 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
vec.z -= other.z;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalar(scalar: number) {
|
|
||||||
this.x *= scalar;
|
|
||||||
this.y *= scalar;
|
|
||||||
this.z *= scalar;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalarNew(scalar: number): Vec3 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x *= scalar;
|
|
||||||
vec.y *= scalar;
|
|
||||||
vec.z *= scalar;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
div(other: Vec3) {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
this.z /= other.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
divNew(other: Vec3): Vec3 {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
vec.z /= other.z;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
reduce(): Vec2 {
|
|
||||||
return new Vec2(this.x, this.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(value: number): Vec4 {
|
|
||||||
return new Vec4(this.x, this.y, this.z, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
splatToArray(): Array<number> {
|
|
||||||
return [this.x, this.y, this.z];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Vec4 implements Vector<Vec3, Vec4, void> {
|
export { initializeContext, Vec2, Vec3, Color };
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
z: number;
|
|
||||||
w: number;
|
|
||||||
|
|
||||||
constructor(x: number, y: number, z: number, w: number) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.w = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(): Vec4 {
|
|
||||||
return new Vec4(this.x, this.y, this.z, this.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(other: Vec4) {
|
|
||||||
this.x += other.x;
|
|
||||||
this.y += other.y;
|
|
||||||
this.z += other.z;
|
|
||||||
this.w += other.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
addNew(other: Vec4): Vec4 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x += other.x;
|
|
||||||
vec.y += other.y;
|
|
||||||
vec.z += other.z;
|
|
||||||
vec.w += other.w;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub(other: Vec4) {
|
|
||||||
this.x -= other.x;
|
|
||||||
this.y -= other.y;
|
|
||||||
this.z -= other.z;
|
|
||||||
this.w -= other.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
subNew(other: Vec4): Vec4 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x -= other.x;
|
|
||||||
vec.y -= other.y;
|
|
||||||
vec.z -= other.z;
|
|
||||||
vec.w -= other.w;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalar(scalar: number) {
|
|
||||||
this.x *= scalar;
|
|
||||||
this.y *= scalar;
|
|
||||||
this.z *= scalar;
|
|
||||||
this.w *= scalar;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalarNew(scalar: number): Vec4 {
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x *= scalar;
|
|
||||||
vec.y *= scalar;
|
|
||||||
vec.z *= scalar;
|
|
||||||
vec.w *= scalar;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
div(other: Vec4) {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0 ||
|
|
||||||
other.w == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.x /= other.x;
|
|
||||||
this.y /= other.y;
|
|
||||||
this.z /= other.z;
|
|
||||||
this.w /= other.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
divNew(other: Vec4): Vec4 {
|
|
||||||
if ( other.x == 0 ||
|
|
||||||
other.y == 0 ||
|
|
||||||
other.z == 0 ||
|
|
||||||
other.w == 0)
|
|
||||||
{
|
|
||||||
throw new Error("Division by zero in Vec4");
|
|
||||||
}
|
|
||||||
|
|
||||||
let vec = this.copy();
|
|
||||||
|
|
||||||
vec.x /= other.x;
|
|
||||||
vec.y /= other.y;
|
|
||||||
vec.z /= other.z;
|
|
||||||
vec.w /= other.w;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
reduce(): Vec3 {
|
|
||||||
return new Vec3(this.x, this.y, this.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(_value: number): void {
|
|
||||||
throw new Error("Can't extend Vec4");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mat4Init = number | Float32Array;
|
|
||||||
|
|
||||||
type Mat4Row = 0 | 1 | 2 | 3
|
|
||||||
type Mat4Col = Mat4Row
|
|
||||||
type Mat4X = Mat4Row
|
|
||||||
type Mat4Y = Mat4Row
|
|
||||||
type Mat4Z = Mat4Row
|
|
||||||
type Mat4W = Mat4Row
|
|
||||||
|
|
||||||
class Mat4 {
|
|
||||||
data: Float32Array;
|
|
||||||
|
|
||||||
constructor(i: Mat4Init) {
|
|
||||||
if (i instanceof Float32Array) {
|
|
||||||
console.assert(i.length == 16, "Mat4 has to have 16 elements");
|
|
||||||
this.data = i;
|
|
||||||
return;
|
|
||||||
} else if (typeof(i) === 'number') {
|
|
||||||
this.data = new Float32Array(16).fill(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.data = new Float32Array(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static IDENTITY(): Mat4 {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static orthographic(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4 {
|
|
||||||
let data = new Float32Array([
|
|
||||||
2 / (right - left), 0, 0, 0,
|
|
||||||
0, 2 / (top - bottom), 0, 0,
|
|
||||||
0, 0, -2 / (far - near), 0,
|
|
||||||
|
|
||||||
-(right + left)/(right - left),
|
|
||||||
-(top + bottom)/(top - bottom),
|
|
||||||
-(far + near)/(far - near),
|
|
||||||
1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isometric(): Mat4 {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, -1, 0, 0,
|
|
||||||
1, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static isometric_inverse(): Mat4 {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
0.5, 0.5, 0, 0,
|
|
||||||
-0.5, 0.5, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static rotation_x(angle: number): Mat4 {
|
|
||||||
let data = new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, Math.cos(angle), -Math.sin(angle), 0,
|
|
||||||
0, Math.sin(angle), Math.cos(angle), 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static rotation_y(angle: number): Mat4 {
|
|
||||||
let data = new Float32Array([
|
|
||||||
Math.cos(angle), 0, Math.sin(angle), 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
-Math.sin(angle), 0, Math.cos(angle), 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static rotation_z(angle: number): Mat4 {
|
|
||||||
let data = new Float32Array([
|
|
||||||
Math.cos(angle), -Math.sin(angle), 0, 0,
|
|
||||||
Math.sin(angle), Math.cos(angle), 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return new Mat4(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static translate(t: Vec3): Mat4 {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
t.x, t.y, t.z, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static scale(scales: Vec3) {
|
|
||||||
return new Mat4(new Float32Array([
|
|
||||||
scales.x, 0, 0, 0,
|
|
||||||
0, scales.y, 0, 0,
|
|
||||||
0, 0, scales.z, 0,
|
|
||||||
0, 0, 0, 1,
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
x(n: Mat4X) {
|
|
||||||
return this.data[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
y(n: Mat4Y) {
|
|
||||||
return this.data[n + 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
z(n: Mat4Z) {
|
|
||||||
return this.data[n + 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
w(n: Mat4W) {
|
|
||||||
return this.data[n + 12];
|
|
||||||
}
|
|
||||||
|
|
||||||
splat() {
|
|
||||||
return Array.from(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
row(row: Mat4Row, data: [number, number, number, number]) {
|
|
||||||
for (let i = 0; i < data.length; ++i)
|
|
||||||
this.data[i + 4 * row] = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
col(col: Mat4Col, data: [number, number, number, number]) {
|
|
||||||
for (let i = 0; i < data.length; ++i)
|
|
||||||
this.data[i*4 + col] = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(v: Vec4) {
|
|
||||||
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
|
|
||||||
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
|
|
||||||
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
|
|
||||||
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
|
|
||||||
|
|
||||||
v.x = x;
|
|
||||||
v.y = y;
|
|
||||||
v.z = z;
|
|
||||||
v.w = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformNew(v: Vec4): Vec4 {
|
|
||||||
let vec = v.copy();
|
|
||||||
|
|
||||||
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
|
|
||||||
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
|
|
||||||
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
|
|
||||||
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
|
|
||||||
|
|
||||||
vec.x = x;
|
|
||||||
vec.y = y;
|
|
||||||
vec.z = z;
|
|
||||||
vec.w = w;
|
|
||||||
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
multNew(other: Mat4): Mat4 {
|
|
||||||
let m = new Mat4(0);
|
|
||||||
|
|
||||||
for (let i = 0; i < 4; ++i) {
|
|
||||||
for (let j = 0; j < 4; ++j) {
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 0] * other.data[j + 0]
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 1] * other.data[j + 4]
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 2] * other.data[j + 8]
|
|
||||||
m.data[(i * 4) + j] += this.data[(i * 4) + 3] * other.data[j + 12]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
multScalar(scalar: number) {
|
|
||||||
for (let i = 0; i < this.data.length; ++i) {
|
|
||||||
this.data[i] *= scalar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { initializeContext, Mat4, Vec2, Vec3, Vec4 };
|
|
||||||
|
|
229
src/js/draw.js
|
@ -1,159 +1,92 @@
|
||||||
import { Vec3 } from "./common.js";
|
import { Vec2 } from "./common.js";
|
||||||
import { Texture, DrawTag } from "./graphics.js";
|
function drawTriangle(gfx, positions, color) {
|
||||||
import { TileEdge } from "./world.js";
|
const a_position = gfx.getAttribute("a_position");
|
||||||
// TODO: Don't assume tile size is same in all directions
|
const a_color = gfx.getAttribute("a_color");
|
||||||
function cull(point, screen, tileSize) {
|
const points = [
|
||||||
if (point.x + tileSize < screen.x)
|
positions[0].x, positions[0].y,
|
||||||
return true;
|
positions[1].x, positions[1].y,
|
||||||
if (point.x + tileSize > screen.x + screen.z)
|
positions[2].x, positions[2].y,
|
||||||
return true;
|
];
|
||||||
if (point.y - tileSize < screen.y)
|
const colors = [
|
||||||
return true;
|
color,
|
||||||
if (point.y + tileSize > screen.y + screen.w)
|
color,
|
||||||
return true;
|
color,
|
||||||
return false;
|
];
|
||||||
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
|
||||||
}
|
}
|
||||||
// Attrib format
|
function drawTriangleExts(gfx, position, exts, color) {
|
||||||
// position color uv
|
const a_position = gfx.getAttribute("a_position");
|
||||||
// (3) (4) (2) => 3 + 4 + 2 = 9 <=> data.len % 9 == 0
|
const a_color = gfx.getAttribute("a_color");
|
||||||
export class Rectangle {
|
const points = [
|
||||||
fill;
|
position.x, position.y,
|
||||||
attribs = ["a_position", "a_color", "a_tex_position"];
|
position.x + exts.x, position.y,
|
||||||
tags = [];
|
position.x, position.y + exts.y,
|
||||||
data = [];
|
|
||||||
stride = 0;
|
|
||||||
vertexStride = 0;
|
|
||||||
constructor(fill, tags, attribs) {
|
|
||||||
this.fill = fill;
|
|
||||||
if (attribs !== undefined) {
|
|
||||||
this.attribs = attribs;
|
|
||||||
}
|
|
||||||
if (tags !== undefined) {
|
|
||||||
this.tags = tags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overrideDraw(draw) {
|
|
||||||
this.draw = draw;
|
|
||||||
}
|
|
||||||
draw(gfx, corners) {
|
|
||||||
if (this.fill instanceof Texture) {
|
|
||||||
this.data = [
|
|
||||||
corners[0].x, corners[0].y, corners[0].z, 0, 0, 0, 0, 0, 0,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, -1, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, 0, -1,
|
|
||||||
corners[2].x, corners[2].y, corners[2].z, 0, 0, 0, 0, -1, -1,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, -1, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, 0, -1,
|
|
||||||
];
|
];
|
||||||
}
|
const colors = [
|
||||||
else {
|
color,
|
||||||
this.data = [
|
color,
|
||||||
corners[0].x, corners[0].y, corners[0].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
corners[1].x, corners[1].y, corners[1].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[2].x, corners[2].y, corners[2].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
];
|
];
|
||||||
}
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
this.vertexStride = 9;
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
this.stride = this.vertexStride * 4;
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
|
||||||
gfx.toRender.push({ ...this });
|
}
|
||||||
}
|
function drawRectangle(gfx, position, exts, color) {
|
||||||
drawExts(gfx, position, exts) {
|
const a_position = gfx.getAttribute("a_position");
|
||||||
if (this.fill instanceof Texture) {
|
const a_color = gfx.getAttribute("a_color");
|
||||||
this.data = [
|
const points = [
|
||||||
position.x, position.y, position.z, 0, 0, 0, 0, 0, 0,
|
position.x, position.y,
|
||||||
position.x + exts.x, position.y, position.z, 0, 0, 0, 0, -1, 0,
|
position.x + exts.x, position.y,
|
||||||
position.x, position.y + exts.y, position.z, 0, 0, 0, 0, 0, -1,
|
position.x, position.y + exts.y,
|
||||||
position.x + exts.x, position.y + exts.y, position.z, 0, 0, 0, 0, -1, -1,
|
position.x + exts.x, position.y + exts.y,
|
||||||
position.x + exts.x, position.y, position.z, 0, 0, 0, 0, -1, 0,
|
position.x + exts.x, position.y,
|
||||||
position.x, position.y + exts.y, position.z, 0, 0, 0, 0, 0, -1,
|
position.x, position.y + exts.y,
|
||||||
];
|
];
|
||||||
}
|
const colors = [
|
||||||
else {
|
color,
|
||||||
this.data = [
|
color,
|
||||||
position.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
position.x + exts.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
position.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
position.x + exts.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
position.x + exts.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
position.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
];
|
];
|
||||||
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
|
||||||
|
}
|
||||||
|
function drawCircle(gfx, position, radius, color) {
|
||||||
|
const points = new Array();
|
||||||
|
const precision = 40;
|
||||||
|
const angle = 2.0 * Math.PI / precision;
|
||||||
|
let a = 0;
|
||||||
|
for (let i = 0; i < precision; ++i) {
|
||||||
|
var vec = Vec2.angle(a);
|
||||||
|
vec.mult(radius);
|
||||||
|
a += angle;
|
||||||
|
points.push(vec);
|
||||||
}
|
}
|
||||||
this.vertexStride = 9;
|
for (let i = 0; i < points.length; i++) {
|
||||||
this.stride = this.vertexStride * 4;
|
const current = points[i];
|
||||||
gfx.toRender.push(this);
|
const next = points[(i + 1) % points.length];
|
||||||
|
let center = position;
|
||||||
|
drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)], color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function drawIsometricCube(gfx, position, exts, color, edge) {
|
function drawLine(gfx, A, B, color) {
|
||||||
|
const a_position = gfx.getAttribute("a_position");
|
||||||
|
const a_color = gfx.getAttribute("a_color");
|
||||||
let points = [
|
let points = [
|
||||||
// Left Top
|
A.x, A.y,
|
||||||
position,
|
B.x, B.y,
|
||||||
//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),
|
|
||||||
];
|
];
|
||||||
let r = new Rectangle(color.top, [
|
const colors = [
|
||||||
DrawTag.ISO,
|
color,
|
||||||
]);
|
color,
|
||||||
// Top
|
];
|
||||||
r.draw(gfx, [
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
points[0],
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
points[1],
|
gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2);
|
||||||
points[3],
|
|
||||||
points[2],
|
|
||||||
]);
|
|
||||||
// Right Edge
|
|
||||||
if (edge == TileEdge.Right || edge == TileEdge.Both) {
|
|
||||||
r.fill = color.right;
|
|
||||||
r.draw(gfx, [
|
|
||||||
points[3],
|
|
||||||
points[2],
|
|
||||||
points[4],
|
|
||||||
points[5],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
// Left Edge
|
|
||||||
if (edge == TileEdge.Left || edge == TileEdge.Both) {
|
|
||||||
r.fill = color.left;
|
|
||||||
r.draw(gfx, [
|
|
||||||
points[0],
|
|
||||||
points[2],
|
|
||||||
points[4],
|
|
||||||
points[6],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function drawIsometricGrid(gfx, grid) {
|
|
||||||
let position = { ...grid.position };
|
|
||||||
let exts = new Vec3(grid.tileSize, grid.tileSize, 0);
|
|
||||||
let tileCoord = new Vec3(0, 0, 0);
|
|
||||||
// TODO: Optimize this
|
|
||||||
for (let k = 0; k < grid.height; ++k) {
|
|
||||||
for (let j = 0; j < grid.length; ++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;
|
|
||||||
}
|
|
||||||
drawIsometricCube(gfx, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
|
|
||||||
position.x += grid.tileSize;
|
|
||||||
}
|
|
||||||
position.y -= grid.tileSize;
|
|
||||||
position.x = grid.position.x;
|
|
||||||
}
|
|
||||||
position.y = grid.position.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
export { drawTriangle, drawTriangleExts, drawRectangle, drawCircle, drawLine };
|
||||||
|
|
281
src/js/draw.ts
|
@ -1,201 +1,116 @@
|
||||||
import { Vec3, Vec2, Vec4 } from "./common.js"
|
import { Vec2 } from "./common.js"
|
||||||
import { Graphics, Texture, Drawable, DrawTag } from "./graphics.js";
|
import { Graphics } from "./graphics.js";
|
||||||
import { TileEdge, TileFill, Grid } from "./world.js";
|
import { Color } from "./common.js";
|
||||||
import * as Assets from "./assets.js";
|
|
||||||
|
|
||||||
// TODO: Don't assume tile size is same in all directions
|
function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) {
|
||||||
function cull(point: Vec3, screen: Vec4, tileSize: number): boolean {
|
const a_position = gfx.getAttribute("a_position");
|
||||||
if (point.x + tileSize < screen.x)
|
const a_color = gfx.getAttribute("a_color");
|
||||||
return true;
|
|
||||||
|
|
||||||
if (point.x + tileSize > screen.x + screen.z)
|
const points: Array<number> = [
|
||||||
return true;
|
positions[0].x, positions[0].y,
|
||||||
|
positions[1].x, positions[1].y,
|
||||||
if (point.y - tileSize < screen.y)
|
positions[2].x, positions[2].y,
|
||||||
return true;
|
|
||||||
|
|
||||||
if (point.y + tileSize > screen.y + screen.w)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attrib format
|
|
||||||
// position color uv
|
|
||||||
// (3) (4) (2) => 3 + 4 + 2 = 9 <=> data.len % 9 == 0
|
|
||||||
|
|
||||||
export class Rectangle implements Drawable {
|
|
||||||
fill: Texture | Assets.Color;
|
|
||||||
attribs: string[] = ["a_position", "a_color", "a_tex_position"];
|
|
||||||
tags: Array<DrawTag> = [];
|
|
||||||
|
|
||||||
data: number[] = [];
|
|
||||||
stride: number = 0;
|
|
||||||
vertexStride: number = 0;
|
|
||||||
|
|
||||||
constructor(fill: Texture | Assets.Color, tags?: Array<DrawTag>, attribs?: string[]) {
|
|
||||||
this.fill = fill;
|
|
||||||
|
|
||||||
if (attribs !== undefined) {
|
|
||||||
this.attribs = attribs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tags !== undefined) {
|
|
||||||
this.tags = tags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overrideDraw(draw: (...args: any[]) => void) {
|
|
||||||
this.draw = draw;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3]) {
|
|
||||||
if (this.fill instanceof Texture) {
|
|
||||||
this.data = [
|
|
||||||
corners[0].x, corners[0].y, corners[0].z, 0, 0, 0, 0, 0, 0,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, -1, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, 0, -1,
|
|
||||||
|
|
||||||
corners[2].x, corners[2].y, corners[2].z, 0, 0, 0, 0, -1, -1,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, 0, 0, 0, 0, -1, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, 0, 0, 0, 0, 0, -1,
|
|
||||||
]
|
]
|
||||||
} else {
|
|
||||||
this.data = [
|
|
||||||
corners[0].x, corners[0].y, corners[0].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[1].x, corners[1].y, corners[1].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
corners[3].x, corners[3].y, corners[3].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
|
|
||||||
corners[2].x, corners[2].y, corners[2].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
const colors: Array<number[]> = [
|
||||||
corners[1].x, corners[1].y, corners[1].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
corners[3].x, corners[3].y, corners[3].z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
color,
|
||||||
]
|
color,
|
||||||
}
|
|
||||||
|
|
||||||
this.vertexStride = 9;
|
|
||||||
this.stride = this.vertexStride * 4
|
|
||||||
gfx.toRender.push({...this});
|
|
||||||
}
|
|
||||||
|
|
||||||
drawExts(gfx: Graphics, position: Vec3, exts: Vec2) {
|
|
||||||
if (this.fill instanceof Texture) {
|
|
||||||
this.data = [
|
|
||||||
position.x, position.y, position.z, 0, 0, 0, 0, 0, 0,
|
|
||||||
position.x + exts.x, position.y, position.z, 0, 0, 0, 0, -1, 0,
|
|
||||||
position.x, position.y + exts.y, position.z, 0, 0, 0, 0, 0, -1,
|
|
||||||
|
|
||||||
position.x + exts.x, position.y + exts.y, position.z, 0, 0, 0, 0, -1, -1,
|
|
||||||
position.x + exts.x, position.y, position.z, 0, 0, 0, 0, -1, 0,
|
|
||||||
position.x, position.y + exts.y, position.z, 0, 0, 0, 0, 0, -1,
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
this.data = [
|
|
||||||
position.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
position.x + exts.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
position.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
|
|
||||||
position.x + exts.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
position.x + exts.x, position.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
position.x, position.y + exts.y, position.z, this.fill[0], this.fill[1], this.fill[2], this.fill[3], 0, 0,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.vertexStride = 9;
|
|
||||||
this.stride = this.vertexStride * 4
|
|
||||||
gfx.toRender.push(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: TileFill, edge: TileEdge) {
|
|
||||||
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),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let r = new Rectangle(color.top, [
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
DrawTag.ISO,
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
]);
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
// Top
|
function drawTriangleExts(gfx: Graphics, position: Vec2, exts: Vec2, color: Color) {
|
||||||
r.draw(
|
const a_position = gfx.getAttribute("a_position");
|
||||||
gfx,
|
const a_color = gfx.getAttribute("a_color");
|
||||||
[
|
|
||||||
points[0],
|
|
||||||
points[1],
|
|
||||||
points[3],
|
|
||||||
points[2],
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Right Edge
|
const points: Array<number> = [
|
||||||
|
position.x, position.y,
|
||||||
if (edge == TileEdge.Right || edge == TileEdge.Both) {
|
position.x + exts.x, position.y,
|
||||||
r.fill = color.right;
|
position.x, position.y + exts.y,
|
||||||
|
|
||||||
r.draw(
|
|
||||||
gfx,
|
|
||||||
[
|
|
||||||
points[3],
|
|
||||||
points[2],
|
|
||||||
points[4],
|
|
||||||
points[5],
|
|
||||||
]
|
]
|
||||||
);
|
|
||||||
|
const colors: Array<number[]> = [
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
];
|
||||||
|
|
||||||
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color) {
|
||||||
|
const a_position = gfx.getAttribute("a_position");
|
||||||
|
const a_color = gfx.getAttribute("a_color");
|
||||||
|
|
||||||
|
const points: Array<number> = [
|
||||||
|
position.x, position.y,
|
||||||
|
position.x + exts.x, position.y,
|
||||||
|
position.x, position.y + exts.y,
|
||||||
|
|
||||||
|
position.x + exts.x, position.y + exts.y,
|
||||||
|
position.x + exts.x, position.y,
|
||||||
|
position.x, position.y + exts.y,
|
||||||
|
]
|
||||||
|
|
||||||
|
const colors: Array<number[]> = [
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
];
|
||||||
|
|
||||||
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
|
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Color) {
|
||||||
|
const points: Array<Vec2> = new Array<Vec2>();
|
||||||
|
|
||||||
|
const precision = 40;
|
||||||
|
const angle = 2.0*Math.PI/precision;
|
||||||
|
let a = 0;
|
||||||
|
for (let i = 0; i < precision; ++i) {
|
||||||
|
var vec = Vec2.angle(a);
|
||||||
|
vec.mult(radius);
|
||||||
|
a += angle;
|
||||||
|
points.push(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left Edge
|
for (let i = 0; i < points.length; i++) {
|
||||||
if (edge == TileEdge.Left || edge == TileEdge.Both) {
|
const current = points[i];
|
||||||
r.fill = color.left;
|
const next = points[(i + 1) % points.length];
|
||||||
|
let center = position;
|
||||||
r.draw(
|
drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)], color);
|
||||||
gfx,
|
|
||||||
[
|
|
||||||
points[0],
|
|
||||||
points[2],
|
|
||||||
points[4],
|
|
||||||
points[6],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function drawIsometricGrid(gfx: Graphics, grid: Grid) {
|
function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Color) {
|
||||||
let position = {...grid.position} as Vec3;
|
const a_position = gfx.getAttribute("a_position");
|
||||||
let exts = new Vec3(grid.tileSize, grid.tileSize, 0);
|
const a_color = gfx.getAttribute("a_color");
|
||||||
let tileCoord = new Vec3(0, 0, 0);
|
|
||||||
|
|
||||||
// TODO: Optimize this
|
let points: Array<number> = [
|
||||||
for (let k = 0; k < grid.height; ++k) {
|
A.x, A.y,
|
||||||
for (let j = 0; j < grid.length; ++j) {
|
B.x, B.y,
|
||||||
for (let i = 0; i < grid.width; ++i) {
|
];
|
||||||
tileCoord.x = i;
|
|
||||||
tileCoord.y = j;
|
|
||||||
tileCoord.z = k;
|
|
||||||
|
|
||||||
let tile = grid.getTile(tileCoord);
|
const colors: Array<number[]> = [
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
];
|
||||||
|
|
||||||
if (tile === null) {
|
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
||||||
position.x += grid.tileSize;
|
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
||||||
continue;
|
gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2);
|
||||||
}
|
|
||||||
|
|
||||||
drawIsometricCube(gfx, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
|
|
||||||
|
|
||||||
position.x += grid.tileSize;
|
|
||||||
}
|
|
||||||
position.y -= grid.tileSize;
|
|
||||||
position.x = grid.position.x;
|
|
||||||
}
|
|
||||||
position.y = grid.position.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { drawTriangle, drawTriangleExts, drawRectangle, drawCircle, drawLine }
|
|
@ -1,5 +1,4 @@
|
||||||
import { Vec4 } from "./common.js";
|
function fullscreenCanvas(gfx, id) {
|
||||||
export function fullscreenCanvas(gfx, id) {
|
|
||||||
const canvas = document.getElementById(id);
|
const canvas = document.getElementById(id);
|
||||||
canvas.width = window.innerWidth;
|
canvas.width = window.innerWidth;
|
||||||
canvas.height = window.innerHeight;
|
canvas.height = window.innerHeight;
|
||||||
|
@ -39,29 +38,19 @@ function createProgram(ctx, vertexShaderSource, fragmentShaderSource) {
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
export var DrawTag;
|
class Graphics {
|
||||||
(function (DrawTag) {
|
|
||||||
DrawTag[DrawTag["ISO"] = 0] = "ISO";
|
|
||||||
})(DrawTag || (DrawTag = {}));
|
|
||||||
export class Graphics {
|
|
||||||
ctx;
|
ctx;
|
||||||
program;
|
program;
|
||||||
attribs = new Map();
|
attribs = new Map();
|
||||||
uniforms = new Map();
|
uniforms = new Map();
|
||||||
vao;
|
vao;
|
||||||
vbo;
|
|
||||||
toRender = [];
|
|
||||||
texCount = 0;
|
|
||||||
constructor(ctx, vs, fs) {
|
constructor(ctx, vs, fs) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.program = createProgram(ctx, vs, fs);
|
this.program = createProgram(ctx, vs, fs);
|
||||||
this.vao = ctx.createVertexArray();
|
this.vao = ctx.createVertexArray();
|
||||||
this.vbo = ctx.createBuffer();
|
|
||||||
ctx.bindVertexArray(this.vao);
|
ctx.bindVertexArray(this.vao);
|
||||||
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
|
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
ctx.useProgram(this.program);
|
ctx.useProgram(this.program);
|
||||||
ctx.blendFunc(ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA);
|
|
||||||
ctx.enable(ctx.BLEND);
|
|
||||||
}
|
}
|
||||||
clear(r, g, b, a) {
|
clear(r, g, b, a) {
|
||||||
this.ctx.clearColor(r, g, b, a);
|
this.ctx.clearColor(r, g, b, a);
|
||||||
|
@ -90,131 +79,32 @@ export class Graphics {
|
||||||
throw new Error("Tried to get uninitialized uniform: " + name);
|
throw new Error("Tried to get uninitialized uniform: " + name);
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
draw() {
|
|
||||||
for (let o of this.toRender) {
|
|
||||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vbo);
|
|
||||||
this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array(o.data), this.ctx.STATIC_DRAW);
|
|
||||||
let aid = 0;
|
|
||||||
for (let a of o.attribs) {
|
|
||||||
let attr = this.getAttribute(a);
|
|
||||||
if (!attr.formatted)
|
|
||||||
throw new Error("Tried to use unformatted attribute!");
|
|
||||||
this.ctx.enableVertexAttribArray(attr.loc);
|
|
||||||
this.ctx.vertexAttribPointer(attr.loc, attr.size, attr.type, attr.normalized, o.stride, aid * 4);
|
|
||||||
aid += attr.size;
|
|
||||||
}
|
|
||||||
// Generalize the tag uniforms aka. don't hard code them
|
|
||||||
for (let t of o.tags) {
|
|
||||||
switch (t) {
|
|
||||||
case DrawTag.ISO: {
|
|
||||||
this.ctx.uniform1ui(this.getUniform("u_isIso"), 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (o.fill instanceof Texture) {
|
|
||||||
this.ctx.uniform1i(this.getUniform("u_isTex"), 1);
|
|
||||||
o.fill.bind(this);
|
|
||||||
}
|
|
||||||
this.ctx.drawArrays(this.ctx.TRIANGLES, 0, o.data.length / o.vertexStride);
|
|
||||||
if (o.fill instanceof Texture) {
|
|
||||||
this.ctx.uniform1i(this.getUniform("u_isTex"), 0);
|
|
||||||
o.fill.unbind(this);
|
|
||||||
}
|
|
||||||
for (let t of o.tags) {
|
|
||||||
switch (t) {
|
|
||||||
case DrawTag.ISO: {
|
|
||||||
this.ctx.uniform1ui(this.getUniform("u_isIso"), 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: Maybe add persistent rendering?
|
|
||||||
this.toRender = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export class Attribute {
|
class Attribute {
|
||||||
loc;
|
loc;
|
||||||
formatted = false;
|
buffer;
|
||||||
|
// TODO: maybe use undefined as default value?
|
||||||
size = 0;
|
size = 0;
|
||||||
type = 0;
|
type = 0;
|
||||||
offset = 0;
|
|
||||||
normalized = false;
|
normalized = false;
|
||||||
|
stride = 0;
|
||||||
|
offset = 0;
|
||||||
constructor(ctx, program, name) {
|
constructor(ctx, program, name) {
|
||||||
this.loc = ctx.getAttribLocation(program, name);
|
this.loc = ctx.getAttribLocation(program, name);
|
||||||
|
this.buffer = ctx.createBuffer();
|
||||||
|
ctx.enableVertexAttribArray(this.loc);
|
||||||
}
|
}
|
||||||
format(size, type, normalized, offset) {
|
format(size, type, normalized, stride, offset) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.normalized = normalized;
|
this.normalized = normalized;
|
||||||
|
this.stride = stride;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.formatted = true;
|
}
|
||||||
}
|
data(ctx, data, usage) {
|
||||||
}
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, this.buffer);
|
||||||
export class Texture {
|
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(data), usage);
|
||||||
tex;
|
ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset);
|
||||||
texId;
|
|
||||||
width = 0;
|
|
||||||
height = 0;
|
|
||||||
constructor(texId, tex, width, height) {
|
|
||||||
this.height = height;
|
|
||||||
this.width = width;
|
|
||||||
this.tex = tex;
|
|
||||||
this.texId = texId;
|
|
||||||
}
|
|
||||||
// TODO: Load sprite sheet only once
|
|
||||||
// TODO: Allow changing sprite size
|
|
||||||
static async load(gfx, path) {
|
|
||||||
let image = await loadTexture(path);
|
|
||||||
let tex = gfx.ctx.createTexture();
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, tex);
|
|
||||||
gfx.ctx.texImage2D(gfx.ctx.TEXTURE_2D, 0, gfx.ctx.RGBA, gfx.ctx.RGBA, gfx.ctx.UNSIGNED_BYTE, image);
|
|
||||||
gfx.ctx.texParameteri(gfx.ctx.TEXTURE_2D, gfx.ctx.TEXTURE_MAG_FILTER, gfx.ctx.NEAREST);
|
|
||||||
gfx.ctx.texParameteri(gfx.ctx.TEXTURE_2D, gfx.ctx.TEXTURE_MIN_FILTER, gfx.ctx.NEAREST);
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, null);
|
|
||||||
gfx.texCount += 1;
|
|
||||||
return new Texture(gfx.texCount, tex, image.width, image.height);
|
|
||||||
}
|
|
||||||
bind(gfx) {
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, this.tex);
|
|
||||||
}
|
|
||||||
unbind(gfx) {
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function loadTexture(path) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const img = new Image();
|
|
||||||
img.addEventListener("load", () => {
|
|
||||||
resolve(img);
|
|
||||||
});
|
|
||||||
img.src = path;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
export class Camera {
|
|
||||||
dt = 0;
|
|
||||||
position;
|
|
||||||
movement;
|
|
||||||
speed = 600;
|
|
||||||
scale = 1.0;
|
|
||||||
scaling = 0.0;
|
|
||||||
scaleSpeed = 1.5;
|
|
||||||
constructor(position) {
|
|
||||||
this.position = position;
|
|
||||||
this.movement = new Vec4(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
update(dt) {
|
|
||||||
this.dt = dt;
|
|
||||||
let newPosition = this.movement.multScalarNew(this.dt);
|
|
||||||
this.position.x += (newPosition.x + newPosition.y) * this.speed;
|
|
||||||
this.position.y += (newPosition.z + newPosition.w) * this.speed;
|
|
||||||
this.scale += this.scaling * this.dt * this.scaleSpeed;
|
|
||||||
if (this.scale < 0.5) {
|
|
||||||
this.scale = 0.5;
|
|
||||||
}
|
|
||||||
if (this.scale > 1.5) {
|
|
||||||
this.scale = 1.5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export { fullscreenCanvas, Graphics, Attribute };
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as Assets from "./assets.js";
|
import { Vec2 } from "./common.js"
|
||||||
import {Vec2, Vec3, Vec4} from "./common.js";
|
|
||||||
|
|
||||||
export function fullscreenCanvas(gfx: Graphics, id: string) {
|
function fullscreenCanvas(gfx: Graphics, id: string) {
|
||||||
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
||||||
canvas.width = window.innerWidth;
|
canvas.width = window.innerWidth;
|
||||||
canvas.height = window.innerHeight;
|
canvas.height = window.innerHeight;
|
||||||
|
@ -52,43 +51,20 @@ function createProgram(ctx: WebGL2RenderingContext, vertexShaderSource: string |
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DrawTag {
|
class Graphics {
|
||||||
ISO,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Drawable {
|
|
||||||
fill: Texture | Assets.Color;
|
|
||||||
attribs: string[];
|
|
||||||
tags: Array<DrawTag>;
|
|
||||||
|
|
||||||
data: Array<number>;
|
|
||||||
vertexStride: number;
|
|
||||||
stride: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Graphics {
|
|
||||||
ctx: WebGL2RenderingContext;
|
ctx: WebGL2RenderingContext;
|
||||||
program: WebGLProgram;
|
program: WebGLProgram;
|
||||||
attribs: Map<string, Attribute> = new Map();
|
attribs: Map<string, Attribute> = new Map();
|
||||||
uniforms: Map<string, WebGLUniformLocation> = new Map();
|
uniforms: Map<string, WebGLUniformLocation> = new Map();
|
||||||
vao: WebGLVertexArrayObject;
|
vao: WebGLVertexArrayObject;
|
||||||
vbo: WebGLBuffer;
|
|
||||||
|
|
||||||
toRender: Array<Drawable> = [];
|
|
||||||
texCount: number = 0;
|
|
||||||
|
|
||||||
constructor(ctx: WebGL2RenderingContext, vs: string, fs: string) {
|
constructor(ctx: WebGL2RenderingContext, vs: string, fs: string) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.program = createProgram(ctx, vs, fs);
|
this.program = createProgram(ctx, vs, fs);
|
||||||
this.vao = ctx.createVertexArray();
|
this.vao = ctx.createVertexArray();
|
||||||
this.vbo = ctx.createBuffer();
|
|
||||||
|
|
||||||
ctx.bindVertexArray(this.vao);
|
ctx.bindVertexArray(this.vao);
|
||||||
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
|
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
ctx.useProgram(this.program);
|
ctx.useProgram(this.program);
|
||||||
|
|
||||||
ctx.blendFunc(ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA);
|
|
||||||
ctx.enable(ctx.BLEND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(r: number, g: number, b: number, a: number) {
|
clear(r: number, g: number, b: number, a: number) {
|
||||||
|
@ -128,171 +104,45 @@ export class Graphics {
|
||||||
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
|
||||||
for (let o of this.toRender) {
|
|
||||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vbo);
|
|
||||||
this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array(o.data), this.ctx.STATIC_DRAW);
|
|
||||||
|
|
||||||
let aid = 0;
|
|
||||||
for (let a of o.attribs) {
|
|
||||||
let attr = this.getAttribute(a);
|
|
||||||
if (!attr.formatted)
|
|
||||||
throw new Error("Tried to use unformatted attribute!");
|
|
||||||
|
|
||||||
this.ctx.enableVertexAttribArray(attr.loc);
|
|
||||||
this.ctx.vertexAttribPointer(attr.loc, attr.size, attr.type, attr.normalized, o.stride, aid * 4);
|
|
||||||
aid += attr.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generalize the tag uniforms aka. don't hard code them
|
|
||||||
for (let t of o.tags) {
|
|
||||||
switch (t) {
|
|
||||||
case DrawTag.ISO: {
|
|
||||||
this.ctx.uniform1ui(this.getUniform("u_isIso"), 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.fill instanceof Texture)
|
|
||||||
{
|
|
||||||
this.ctx.uniform1i(this.getUniform("u_isTex"), 1);
|
|
||||||
o.fill.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ctx.drawArrays(this.ctx.TRIANGLES, 0, o.data.length / o.vertexStride);
|
|
||||||
|
|
||||||
if (o.fill instanceof Texture)
|
|
||||||
{
|
|
||||||
this.ctx.uniform1i(this.getUniform("u_isTex"), 0);
|
|
||||||
o.fill.unbind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let t of o.tags) {
|
|
||||||
switch (t) {
|
|
||||||
case DrawTag.ISO: {
|
|
||||||
this.ctx.uniform1ui(this.getUniform("u_isIso"), 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Maybe add persistent rendering?
|
|
||||||
this.toRender = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Attribute {
|
class Attribute {
|
||||||
loc: GLint;
|
loc: GLint;
|
||||||
formatted: boolean = false;
|
buffer: WebGLBuffer;
|
||||||
|
|
||||||
|
// TODO: maybe use undefined as default value?
|
||||||
size: GLint = 0;
|
size: GLint = 0;
|
||||||
type: GLenum = 0;
|
type: GLenum = 0;
|
||||||
offset: GLintptr = 0;
|
|
||||||
normalized: GLboolean = false;
|
normalized: GLboolean = false;
|
||||||
|
stride: GLsizei = 0;
|
||||||
|
offset: GLintptr = 0;
|
||||||
|
|
||||||
constructor(ctx: WebGL2RenderingContext, program: WebGLProgram, name: string) {
|
constructor(ctx: WebGL2RenderingContext, program: WebGLProgram, name: string) {
|
||||||
this.loc = ctx.getAttribLocation(program, name);
|
this.loc = ctx.getAttribLocation(program, name);
|
||||||
|
this.buffer = ctx.createBuffer();
|
||||||
|
|
||||||
|
ctx.enableVertexAttribArray(this.loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
format(
|
format(
|
||||||
size: GLint,
|
size: GLint,
|
||||||
type: GLenum,
|
type: GLenum,
|
||||||
normalized: GLboolean,
|
normalized: GLboolean,
|
||||||
|
stride: GLsizei,
|
||||||
offset: GLintptr)
|
offset: GLintptr)
|
||||||
{
|
{
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.normalized = normalized;
|
this.normalized = normalized;
|
||||||
|
this.stride = stride;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
this.formatted = true;
|
data(ctx: WebGL2RenderingContext, data: Array<number>, usage: GLenum) {
|
||||||
}
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, this.buffer);
|
||||||
}
|
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(data), usage);
|
||||||
|
ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset);
|
||||||
export class Texture {
|
|
||||||
tex: WebGLTexture | null;
|
|
||||||
texId: number;
|
|
||||||
width: number = 0;
|
|
||||||
height: number = 0;
|
|
||||||
|
|
||||||
constructor(texId: number, tex: WebGLTexture, width: number, height: number) {
|
|
||||||
this.height = height;
|
|
||||||
this.width = width;
|
|
||||||
this.tex = tex;
|
|
||||||
this.texId = texId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Load sprite sheet only once
|
|
||||||
// TODO: Allow changing sprite size
|
|
||||||
static async load(gfx: Graphics, path: string): Promise<Texture> {
|
|
||||||
let image = await loadTexture(path);
|
|
||||||
|
|
||||||
let tex = gfx.ctx.createTexture();
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, tex);
|
|
||||||
gfx.ctx.texImage2D(gfx.ctx.TEXTURE_2D, 0, gfx.ctx.RGBA, gfx.ctx.RGBA, gfx.ctx.UNSIGNED_BYTE, image);
|
|
||||||
gfx.ctx.texParameteri(gfx.ctx.TEXTURE_2D, gfx.ctx.TEXTURE_MAG_FILTER, gfx.ctx.NEAREST);
|
|
||||||
gfx.ctx.texParameteri(gfx.ctx.TEXTURE_2D, gfx.ctx.TEXTURE_MIN_FILTER, gfx.ctx.NEAREST);
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, null);
|
|
||||||
|
|
||||||
gfx.texCount += 1;
|
|
||||||
return new Texture(gfx.texCount, tex, image.width, image.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(gfx: Graphics) {
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, this.tex);
|
|
||||||
}
|
|
||||||
|
|
||||||
unbind(gfx: Graphics) {
|
|
||||||
gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadTexture(path: string): Promise<HTMLImageElement> {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const img = new Image();
|
|
||||||
img.addEventListener("load", () => {
|
|
||||||
resolve(img);
|
|
||||||
})
|
|
||||||
img.src = path;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Camera {
|
|
||||||
dt: number = 0;
|
|
||||||
|
|
||||||
position: Vec3;
|
|
||||||
movement: Vec4;
|
|
||||||
speed: number = 600;
|
|
||||||
|
|
||||||
scale: number = 1.0;
|
|
||||||
scaling: number = 0.0;
|
|
||||||
scaleSpeed: number = 1.5;
|
|
||||||
|
|
||||||
constructor(position: Vec3) {
|
|
||||||
this.position = position;
|
|
||||||
this.movement = new Vec4(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number) {
|
|
||||||
this.dt = dt;
|
|
||||||
|
|
||||||
let newPosition = this.movement.multScalarNew(this.dt);
|
|
||||||
this.position.x += (newPosition.x + newPosition.y) * this.speed;
|
|
||||||
this.position.y += (newPosition.z + newPosition.w) * this.speed;
|
|
||||||
|
|
||||||
this.scale += this.scaling * this.dt * this.scaleSpeed;
|
|
||||||
|
|
||||||
if (this.scale < 0.5) {
|
|
||||||
this.scale = 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.scale > 1.5) {
|
|
||||||
this.scale = 1.5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { fullscreenCanvas, Graphics, Attribute }
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
class KeyAction {
|
|
||||||
key;
|
|
||||||
keyup;
|
|
||||||
keydown;
|
|
||||||
data;
|
|
||||||
constructor(key, ku, kd, data) {
|
|
||||||
this.key = key;
|
|
||||||
this.keyup = ku;
|
|
||||||
this.keydown = kd;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class Input {
|
|
||||||
handlers = new Map();
|
|
||||||
constructor() {
|
|
||||||
window.addEventListener("keyup", e => {
|
|
||||||
this.handlers.forEach(ka => {
|
|
||||||
if (ka.keyup !== null && ka.key == e.code) {
|
|
||||||
ka.keyup(ka.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
window.addEventListener("keydown", e => {
|
|
||||||
this.handlers.forEach(ka => {
|
|
||||||
if (ka.keydown !== null && ka.key == e.code) {
|
|
||||||
ka.keydown(ka.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//TODO: add modifier key support
|
|
||||||
addKeyAction(key, modifiers, data, keydown, keyup) {
|
|
||||||
this.handlers.set(key, new KeyAction(key, keydown, keyup, data));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
type Action = ((data: any) => void);
|
|
||||||
|
|
||||||
class KeyAction {
|
|
||||||
key: string;
|
|
||||||
keyup: Action | null;
|
|
||||||
keydown: Action | null;
|
|
||||||
data: any;
|
|
||||||
constructor(key: string, ku: Action | null, kd: Action | null, data: any) {
|
|
||||||
this.key = key;
|
|
||||||
this.keyup = ku;
|
|
||||||
this.keydown = kd;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Input {
|
|
||||||
handlers: Map<string, KeyAction> = new Map();
|
|
||||||
constructor() {
|
|
||||||
window.addEventListener("keyup", e => {
|
|
||||||
this.handlers.forEach(ka => {
|
|
||||||
if (ka.keyup !== null && ka.key == e.code) {
|
|
||||||
ka.keyup(ka.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
window.addEventListener("keydown", e => {
|
|
||||||
this.handlers.forEach(ka => {
|
|
||||||
if (ka.keydown !== null && ka.key == e.code) {
|
|
||||||
ka.keydown(ka.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: add modifier key support
|
|
||||||
addKeyAction(key: string, modifiers: [string] | [], data: any, keydown: Action | null, keyup: Action | null) {
|
|
||||||
this.handlers.set(key, new KeyAction(key, keydown, keyup, data));
|
|
||||||
}
|
|
||||||
}
|
|
171
src/js/script.js
|
@ -1,124 +1,53 @@
|
||||||
import { initializeContext, Vec3, Mat4, Vec4, Vec2 } from "./common.js";
|
import { initializeContext, Vec2 } from "./common.js";
|
||||||
import { Graphics, fullscreenCanvas, Camera } from "./graphics.js";
|
import { Graphics, fullscreenCanvas } from "./graphics.js";
|
||||||
import * as drawing from "./draw.js";
|
import * as drawing from "./draw.js";
|
||||||
import * as wasm from "./wasm.js";
|
import * as wasm from "./wasm.js";
|
||||||
import { Input } from "./input.js";
|
|
||||||
import { bush, Grid, Tile, tree } from "./world.js";
|
|
||||||
import * as Assets from "./assets.js";
|
|
||||||
const vertexShader = `#version 300 es
|
const vertexShader = `#version 300 es
|
||||||
|
|
||||||
layout(location = 0) in vec3 a_position;
|
in vec2 a_position;
|
||||||
layout(location = 1) in vec2 a_tex_position;
|
in vec4 a_color;
|
||||||
layout(location = 2) in vec4 a_color;
|
out vec4 color;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
out vec4 v_color;
|
|
||||||
out vec2 v_tex_position;
|
|
||||||
|
|
||||||
uniform mat4 u_matrix;
|
|
||||||
uniform bool u_isIso;
|
|
||||||
uniform bool u_isTex;
|
|
||||||
|
|
||||||
mat4 Iso = mat4(
|
|
||||||
1, -1, 0, 0,
|
|
||||||
1, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 orthographic;
|
vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0;
|
||||||
|
|
||||||
if (u_isIso) {
|
color = a_color;
|
||||||
vec4 isometric = Iso * vec4(a_position.xyz, 1.0);
|
|
||||||
orthographic = u_matrix * isometric;
|
|
||||||
//orthographic = u_matrix * vec4(a_position.xyz, 1.0);
|
|
||||||
} else {
|
|
||||||
orthographic = u_matrix * vec4(a_position.xyz, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_Position = orthographic;
|
gl_Position = vec4(clipSpace.xy, 0.0, 1.0);
|
||||||
|
|
||||||
if (u_isTex) {
|
|
||||||
v_tex_position = a_tex_position;
|
|
||||||
} else {
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const fragmentShader = `#version 300 es
|
const fragmentShader = `#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
in vec4 color;
|
||||||
in vec4 v_color;
|
|
||||||
in vec2 v_tex_position;
|
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform bool u_isTex;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (u_isTex) {
|
outColor = color;
|
||||||
outColor = texture(u_texture, v_tex_position);
|
|
||||||
} else {
|
|
||||||
outColor = v_color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
function draw(gfx, camera, dt, grid) {
|
function draw(gfx, dt, pos, velocity) {
|
||||||
gfx.clear(0, 0, 0, 0);
|
gfx.clear(0, 0, 0, 0);
|
||||||
camera.update(dt);
|
gfx.ctx.uniform2f(gfx.getUniform("u_resolution"), gfx.ctx.canvas.width, gfx.ctx.canvas.height);
|
||||||
let right = gfx.ctx.canvas.width;
|
drawing.drawCircle(gfx, pos, 200, [1, 0, 0, 1]);
|
||||||
let left = 0;
|
if (pos.x + 200 >= gfx.ctx.canvas.width) {
|
||||||
let top = gfx.ctx.canvas.height;
|
pos.x = gfx.ctx.canvas.width - 200;
|
||||||
let bottom = 0;
|
velocity.x *= -1;
|
||||||
let near = -100;
|
}
|
||||||
let far = 100;
|
else if (pos.x - 200 <= 0) {
|
||||||
let m = Mat4.IDENTITY();
|
pos.x = 200;
|
||||||
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
|
velocity.x *= -1;
|
||||||
let mc = Mat4.translate(new Vec3((gfx.ctx.canvas.width / 2 - camera.position.x), (gfx.ctx.canvas.height / 2 - camera.position.y), 1.0));
|
}
|
||||||
let mr = Mat4.translate(new Vec3(-(gfx.ctx.canvas.width / 2 - camera.position.x), -(gfx.ctx.canvas.height / 2 - camera.position.y), 1.0));
|
if (pos.y + 200 >= gfx.ctx.canvas.height) {
|
||||||
let mt = Mat4.translate(camera.position);
|
pos.y = gfx.ctx.canvas.height - 200;
|
||||||
let ms = Mat4.scale(new Vec3(camera.scale, camera.scale, 1));
|
velocity.y *= -1;
|
||||||
m = m.multNew(mr);
|
}
|
||||||
m = m.multNew(ms);
|
else if (pos.y - 200 <= 0) {
|
||||||
m = m.multNew(mc);
|
pos.y = 200;
|
||||||
m = m.multNew(mt);
|
velocity.y *= -1;
|
||||||
m = m.multNew(mo);
|
}
|
||||||
gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat());
|
pos.add(velocity.multNew(dt));
|
||||||
drawing.drawIsometricGrid(gfx, grid);
|
|
||||||
gfx.draw();
|
|
||||||
}
|
|
||||||
function addDefaultKeybinds(input, camera) {
|
|
||||||
input.addKeyAction("KeyA", [], camera, (c) => {
|
|
||||||
c.movement.x = 0;
|
|
||||||
}, (c) => {
|
|
||||||
c.movement.x = 1;
|
|
||||||
});
|
|
||||||
input.addKeyAction("KeyD", [], camera, (c) => {
|
|
||||||
c.movement.y = 0;
|
|
||||||
}, (c) => {
|
|
||||||
c.movement.y = -1;
|
|
||||||
});
|
|
||||||
input.addKeyAction("KeyW", [], camera, (c) => {
|
|
||||||
c.movement.z = 0;
|
|
||||||
}, (c) => {
|
|
||||||
c.movement.z = -1;
|
|
||||||
});
|
|
||||||
input.addKeyAction("KeyS", [], camera, (c) => {
|
|
||||||
c.movement.w = 0;
|
|
||||||
}, (c) => {
|
|
||||||
c.movement.w = 1;
|
|
||||||
});
|
|
||||||
input.addKeyAction("KeyQ", [], camera, (c) => {
|
|
||||||
c.scaling = 0.0;
|
|
||||||
}, (c) => {
|
|
||||||
c.scaling = 1.0;
|
|
||||||
});
|
|
||||||
input.addKeyAction("KeyE", [], camera, (c) => {
|
|
||||||
c.scaling = 0.0;
|
|
||||||
}, (c) => {
|
|
||||||
c.scaling = -1.0;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
(async () => {
|
(async () => {
|
||||||
const canvasId = "game";
|
const canvasId = "game";
|
||||||
|
@ -127,44 +56,24 @@ function addDefaultKeybinds(input, camera) {
|
||||||
return;
|
return;
|
||||||
const gfx = new Graphics(ctx, vertexShader, fragmentShader);
|
const gfx = new Graphics(ctx, vertexShader, fragmentShader);
|
||||||
fullscreenCanvas(gfx, canvasId);
|
fullscreenCanvas(gfx, canvasId);
|
||||||
let a = gfx.createAttribute("a_position");
|
const a_position = gfx.createAttribute("a_position");
|
||||||
a.format(3, ctx.FLOAT, false, 0);
|
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
a = gfx.createAttribute("a_color");
|
const a_color = gfx.createAttribute("a_color");
|
||||||
a.format(4, ctx.FLOAT, false, 0);
|
a_color.format(4, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
a = gfx.createAttribute("a_tex_position");
|
gfx.createUniform("u_resolution");
|
||||||
a.format(2, ctx.FLOAT, false, 0);
|
let pos = new Vec2(300, 300);
|
||||||
gfx.createUniform("u_matrix");
|
let velocity = new Vec2(200, 200);
|
||||||
gfx.createUniform("u_isIso");
|
|
||||||
gfx.createUniform("u_isTex");
|
|
||||||
let camera = new Camera(new Vec3(0, 0, -1));
|
|
||||||
await Assets.assets.load(gfx);
|
|
||||||
let m = Mat4.isometric();
|
|
||||||
let size = 100;
|
|
||||||
let grid = new Grid(m.transformNew(new Vec4(ctx.canvas.width / 4, ctx.canvas.height / 2, 0, 1)).reduce(), 24, size, size, 10);
|
|
||||||
grid.fillLayer(new Tile({
|
|
||||||
top: Assets.assets.get("grass"),
|
|
||||||
right: Assets.Colors.Brown,
|
|
||||||
left: Assets.Colors.Brown,
|
|
||||||
}), 0);
|
|
||||||
tree(grid, new Vec2(size / 2, size / 2));
|
|
||||||
bush(grid, new Vec2(size / 2 + 4, size / 2 + 4));
|
|
||||||
//for (let i = 0; i < 10; i++) {
|
|
||||||
// tree(grid, new Vec2(Math.floor(Math.random() * size - 1), Math.floor(Math.random() * size - 1)));
|
|
||||||
//}
|
|
||||||
//grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(0, 29, 1));
|
|
||||||
let prevTimestamp = 0;
|
let prevTimestamp = 0;
|
||||||
const frame = (timestamp) => {
|
const frame = (timestamp) => {
|
||||||
const deltaTime = (timestamp - prevTimestamp) / 1000;
|
const deltaTime = (timestamp - prevTimestamp) / 1000;
|
||||||
prevTimestamp = timestamp;
|
prevTimestamp = timestamp;
|
||||||
fullscreenCanvas(gfx, "game");
|
fullscreenCanvas(gfx, "game");
|
||||||
draw(gfx, camera, deltaTime, grid);
|
draw(gfx, deltaTime, pos, velocity);
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
};
|
};
|
||||||
window.requestAnimationFrame((timestamp) => {
|
window.requestAnimationFrame((timestamp) => {
|
||||||
prevTimestamp = timestamp;
|
prevTimestamp = timestamp;
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
});
|
});
|
||||||
const input = new Input();
|
let env = await wasm.loadWasmModule("./src/wasm/module.wasm");
|
||||||
addDefaultKeybinds(input, camera);
|
|
||||||
const wasmgl = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
|
|
||||||
})();
|
})();
|
||||||
|
|
217
src/js/script.ts
|
@ -1,50 +1,22 @@
|
||||||
import { initializeContext, Vec3, Mat4, Vec4, Vec2 } from "./common.js";
|
import { initializeContext, Vec2 } from "./common.js";
|
||||||
import { Graphics, fullscreenCanvas, Camera, DrawTag } from "./graphics.js";
|
import { Graphics, fullscreenCanvas } from "./graphics.js";
|
||||||
import * as drawing from "./draw.js";
|
import * as drawing from "./draw.js";
|
||||||
import * as wasm from "./wasm.js";
|
import * as wasm from "./wasm.js";
|
||||||
import { Input } from "./input.js";
|
|
||||||
import {bush, Grid, Tile, TileEdge, tree} from "./world.js";
|
|
||||||
import * as Assets from "./assets.js";
|
|
||||||
|
|
||||||
const vertexShader =
|
const vertexShader =
|
||||||
`#version 300 es
|
`#version 300 es
|
||||||
|
|
||||||
layout(location = 0) in vec3 a_position;
|
in vec2 a_position;
|
||||||
layout(location = 1) in vec2 a_tex_position;
|
in vec4 a_color;
|
||||||
layout(location = 2) in vec4 a_color;
|
out vec4 color;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
out vec4 v_color;
|
|
||||||
out vec2 v_tex_position;
|
|
||||||
|
|
||||||
uniform mat4 u_matrix;
|
|
||||||
uniform bool u_isIso;
|
|
||||||
uniform bool u_isTex;
|
|
||||||
|
|
||||||
mat4 Iso = mat4(
|
|
||||||
1, -1, 0, 0,
|
|
||||||
1, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
);
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 orthographic;
|
vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0;
|
||||||
|
|
||||||
if (u_isIso) {
|
color = a_color;
|
||||||
vec4 isometric = Iso * vec4(a_position.xyz, 1.0);
|
|
||||||
orthographic = u_matrix * isometric;
|
|
||||||
//orthographic = u_matrix * vec4(a_position.xyz, 1.0);
|
|
||||||
} else {
|
|
||||||
orthographic = u_matrix * vec4(a_position.xyz, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_Position = orthographic;
|
gl_Position = vec4(clipSpace.xy, 0.0, 1.0);
|
||||||
|
|
||||||
if (u_isTex) {
|
|
||||||
v_tex_position = a_tex_position;
|
|
||||||
} else {
|
|
||||||
v_color = a_color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -52,118 +24,42 @@ const fragmentShader =
|
||||||
`#version 300 es
|
`#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
in vec4 color;
|
||||||
in vec4 v_color;
|
|
||||||
in vec2 v_tex_position;
|
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform bool u_isTex;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (u_isTex) {
|
outColor = color;
|
||||||
outColor = texture(u_texture, v_tex_position);
|
|
||||||
} else {
|
|
||||||
outColor = v_color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function draw(gfx: Graphics, camera: Camera, dt: number, grid: Grid) {
|
|
||||||
|
|
||||||
|
function draw(gfx: Graphics, dt: number, pos: Vec2, velocity: Vec2) {
|
||||||
gfx.clear(0, 0, 0, 0);
|
gfx.clear(0, 0, 0, 0);
|
||||||
camera.update(dt);
|
gfx.ctx.uniform2f(gfx.getUniform("u_resolution"), gfx.ctx.canvas.width, gfx.ctx.canvas.height);
|
||||||
|
drawing.drawCircle(gfx, pos, 200, [1, 0, 0, 1]);
|
||||||
|
|
||||||
let right = gfx.ctx.canvas.width;
|
if (pos.x + 200 >= gfx.ctx.canvas.width)
|
||||||
let left = 0;
|
{
|
||||||
let top = gfx.ctx.canvas.height;
|
pos.x = gfx.ctx.canvas.width - 200;
|
||||||
let bottom = 0;
|
velocity.x *= -1;
|
||||||
let near = -100;
|
} else if (pos.x - 200 <= 0)
|
||||||
let far = 100;
|
{
|
||||||
|
pos.x = 200;
|
||||||
|
velocity.x *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
let m = Mat4.IDENTITY();
|
if (pos.y + 200 >= gfx.ctx.canvas.height)
|
||||||
|
{
|
||||||
|
pos.y = gfx.ctx.canvas.height - 200;
|
||||||
|
velocity.y *= -1;
|
||||||
|
} else if (pos.y - 200 <= 0)
|
||||||
|
{
|
||||||
|
pos.y = 200;
|
||||||
|
velocity.y *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
|
pos.add(velocity.multNew(dt));
|
||||||
|
|
||||||
let mc = Mat4.translate(
|
|
||||||
new Vec3(
|
|
||||||
(gfx.ctx.canvas.width / 2 - camera.position.x),
|
|
||||||
(gfx.ctx.canvas.height / 2 - camera.position.y),
|
|
||||||
1.0));
|
|
||||||
|
|
||||||
let mr = Mat4.translate(
|
|
||||||
new Vec3(
|
|
||||||
-(gfx.ctx.canvas.width / 2 - camera.position.x),
|
|
||||||
-(gfx.ctx.canvas.height / 2 - camera.position.y),
|
|
||||||
1.0));
|
|
||||||
|
|
||||||
let mt = Mat4.translate(camera.position);
|
|
||||||
|
|
||||||
let ms = Mat4.scale(new Vec3(camera.scale, camera.scale, 1));
|
|
||||||
|
|
||||||
m = m.multNew(mr);
|
|
||||||
m = m.multNew(ms);
|
|
||||||
m = m.multNew(mc);
|
|
||||||
m = m.multNew(mt);
|
|
||||||
m = m.multNew(mo);
|
|
||||||
|
|
||||||
gfx.ctx.uniformMatrix4fv(
|
|
||||||
gfx.getUniform("u_matrix"),
|
|
||||||
false,
|
|
||||||
m.splat()
|
|
||||||
);
|
|
||||||
|
|
||||||
drawing.drawIsometricGrid(gfx, grid);
|
|
||||||
gfx.draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDefaultKeybinds(input: Input, camera: Camera) {
|
|
||||||
input.addKeyAction("KeyA", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.movement.x = 0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.movement.x = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addKeyAction("KeyD", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.movement.y = 0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.movement.y = -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addKeyAction("KeyW", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.movement.z = 0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.movement.z = -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addKeyAction("KeyS", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.movement.w = 0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.movement.w = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addKeyAction("KeyQ", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.scaling = 0.0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.scaling = 1.0;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.addKeyAction("KeyE", [], camera,
|
|
||||||
(c) => {
|
|
||||||
c.scaling = 0.0;
|
|
||||||
},
|
|
||||||
(c) => {
|
|
||||||
c.scaling = -1.0;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -174,38 +70,16 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
|
||||||
const gfx = new Graphics(ctx, vertexShader, fragmentShader);
|
const gfx = new Graphics(ctx, vertexShader, fragmentShader);
|
||||||
fullscreenCanvas(gfx, canvasId);
|
fullscreenCanvas(gfx, canvasId);
|
||||||
|
|
||||||
let a = gfx.createAttribute("a_position");
|
const a_position = gfx.createAttribute("a_position");
|
||||||
a.format(3, ctx.FLOAT, false, 0)
|
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
a = gfx.createAttribute("a_color");
|
|
||||||
a.format(4, ctx.FLOAT, false, 0)
|
|
||||||
a = gfx.createAttribute("a_tex_position");
|
|
||||||
a.format(2, ctx.FLOAT, false, 0)
|
|
||||||
|
|
||||||
gfx.createUniform("u_matrix");
|
const a_color = gfx.createAttribute("a_color");
|
||||||
gfx.createUniform("u_isIso");
|
a_color.format(4, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
gfx.createUniform("u_isTex");
|
|
||||||
|
|
||||||
let camera = new Camera(new Vec3(0, 0, -1));
|
gfx.createUniform("u_resolution");
|
||||||
|
|
||||||
await Assets.assets.load(gfx);
|
let pos = new Vec2(300, 300);
|
||||||
|
let velocity = new Vec2(200, 200);
|
||||||
let m = Mat4.isometric();
|
|
||||||
|
|
||||||
let size = 100;
|
|
||||||
let grid = new Grid(m.transformNew(new Vec4(ctx.canvas.width / 4, ctx.canvas.height / 2, 0, 1)).reduce(), 24, size, size, 10);
|
|
||||||
grid.fillLayer(new Tile({
|
|
||||||
top: Assets.assets.get("grass"),
|
|
||||||
right: Assets.Colors.Brown,
|
|
||||||
left: Assets.Colors.Brown,
|
|
||||||
}), 0);
|
|
||||||
|
|
||||||
tree(grid, new Vec2(size / 2, size / 2));
|
|
||||||
bush(grid, new Vec2(size / 2 + 4, size / 2 + 4));
|
|
||||||
//for (let i = 0; i < 10; i++) {
|
|
||||||
// tree(grid, new Vec2(Math.floor(Math.random() * size - 1), Math.floor(Math.random() * size - 1)));
|
|
||||||
//}
|
|
||||||
|
|
||||||
//grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(0, 29, 1));
|
|
||||||
|
|
||||||
let prevTimestamp = 0;
|
let prevTimestamp = 0;
|
||||||
const frame = (timestamp: number) => {
|
const frame = (timestamp: number) => {
|
||||||
|
@ -213,7 +87,7 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
|
||||||
prevTimestamp = timestamp;
|
prevTimestamp = timestamp;
|
||||||
|
|
||||||
fullscreenCanvas(gfx, "game");
|
fullscreenCanvas(gfx, "game");
|
||||||
draw(gfx, camera, deltaTime, grid);
|
draw(gfx, deltaTime, pos, velocity);
|
||||||
|
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
}
|
}
|
||||||
|
@ -223,8 +97,5 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
});
|
});
|
||||||
|
|
||||||
const input = new Input();
|
let env: any = await wasm.loadWasmModule("./src/wasm/module.wasm");
|
||||||
addDefaultKeybinds(input, camera);
|
|
||||||
|
|
||||||
const wasmgl: wasm.WASMGL = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class WASMGLvalue {
|
class WASMGLvalue {
|
||||||
ptr;
|
ptr;
|
||||||
size;
|
size;
|
||||||
constructor(ptr, size) {
|
constructor(ptr, size) {
|
||||||
|
@ -6,32 +6,58 @@ export class WASMGLvalue {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function loadWasmModule(path) {
|
async function loadWasmModule(path) {
|
||||||
return WebAssembly.instantiateStreaming(fetch(path));
|
let wasm = await WebAssembly.instantiateStreaming(fetch(path));
|
||||||
|
const memSize = new Int32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value + 4, 1)[0];
|
||||||
|
let memInt = new Int32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value, memSize);
|
||||||
|
let memFloat = new Float32Array(wasm.instance.exports.memory.buffer, wasm.instance.exports.WASMGLmemory.value, memSize);
|
||||||
|
wasm.instance.exports.WASMGLmain();
|
||||||
|
const data = [
|
||||||
|
1.5,
|
||||||
|
2.5,
|
||||||
|
3.5,
|
||||||
|
4.5,
|
||||||
|
5.5,
|
||||||
|
6.5,
|
||||||
|
7.5,
|
||||||
|
8.5,
|
||||||
|
];
|
||||||
|
let ptr = sendDataFloat(memFloat, data);
|
||||||
|
wasm.instance.exports.calc(ptr, data.length);
|
||||||
|
for (let i = 0; i < data.length; ++i) {
|
||||||
|
console.log(memFloat[ptr + i]);
|
||||||
|
}
|
||||||
|
return wasm.instance.exports;
|
||||||
}
|
}
|
||||||
export class WASMGL {
|
function alloc(mem, size) {
|
||||||
exports;
|
const head = mem[2];
|
||||||
mem;
|
mem[2] += size;
|
||||||
constructor(wasm) {
|
|
||||||
this.exports = wasm.instance.exports;
|
|
||||||
const memSize = new Float32Array(this.exports.memory.buffer, this.exports.WASMGLmemory.value + 4, 1).at(0);
|
|
||||||
this.mem = new Float32Array(this.exports.memory.buffer, this.exports.WASMGLmemory.value, memSize);
|
|
||||||
}
|
|
||||||
alloc(size) {
|
|
||||||
const head = this.mem[2];
|
|
||||||
this.mem[2] += size;
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
setstr(ptr, str) {
|
function allocFloat(mem, size) {
|
||||||
for (let i = 0; i < str.length; i++) {
|
const head = mem[2];
|
||||||
this.mem[ptr] = str.charCodeAt(i);
|
mem[2] += size;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
function setstr(mem, ptr, size, str) {
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
mem[ptr] = str.charCodeAt(i);
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set(ptr, data) {
|
function sendData(mem, data) {
|
||||||
|
let ptr = alloc(mem, data.length);
|
||||||
data.forEach((v, i) => {
|
data.forEach((v, i) => {
|
||||||
this.mem[ptr + i] = v;
|
mem[ptr + i] = v;
|
||||||
});
|
});
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
function sendDataFloat(mem, data) {
|
||||||
|
let ptr = allocFloat(mem, data.length);
|
||||||
|
data.forEach((v, i) => {
|
||||||
|
mem[ptr + i] = v;
|
||||||
|
console.log(mem[ptr + i]);
|
||||||
|
});
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
export { loadWasmModule, alloc, setstr };
|
||||||
|
|
104
src/js/wasm.ts
|
@ -1,4 +1,4 @@
|
||||||
export class WASMGLvalue {
|
class WASMGLvalue {
|
||||||
ptr: number;
|
ptr: number;
|
||||||
size: number;
|
size: number;
|
||||||
|
|
||||||
|
@ -8,54 +8,90 @@ export class WASMGLvalue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WASMGLEnvironment {
|
async function loadWasmModule(path: string): Promise<WebAssembly.Exports> {
|
||||||
exports: any,
|
let wasm: any = await WebAssembly.instantiateStreaming(fetch(path));
|
||||||
mem: Float32Array,
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadWasmModule(path: string): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
|
const memSize = new Int32Array(
|
||||||
return WebAssembly.instantiateStreaming(fetch(path));
|
wasm.instance.exports.memory.buffer,
|
||||||
}
|
wasm.instance.exports.WASMGLmemory.value + 4,
|
||||||
|
|
||||||
export class WASMGL {
|
|
||||||
exports: any;
|
|
||||||
mem: Float32Array;
|
|
||||||
|
|
||||||
constructor(wasm: WebAssembly.WebAssemblyInstantiatedSource) {
|
|
||||||
this.exports = wasm.instance.exports;
|
|
||||||
|
|
||||||
const memSize = new Float32Array(
|
|
||||||
this.exports.memory.buffer,
|
|
||||||
this.exports.WASMGLmemory.value + 4,
|
|
||||||
1
|
1
|
||||||
).at(0);
|
)[0];
|
||||||
|
|
||||||
this.mem = new Float32Array(
|
let memInt = new Int32Array(
|
||||||
this.exports.memory.buffer,
|
wasm.instance.exports.memory.buffer,
|
||||||
this.exports.WASMGLmemory.value,
|
wasm.instance.exports.WASMGLmemory.value,
|
||||||
memSize
|
memSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let memFloat = new Float32Array(
|
||||||
|
wasm.instance.exports.memory.buffer,
|
||||||
|
wasm.instance.exports.WASMGLmemory.value,
|
||||||
|
memSize
|
||||||
|
);
|
||||||
|
|
||||||
|
wasm.instance.exports.WASMGLmain();
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
1.5,
|
||||||
|
2.5,
|
||||||
|
3.5,
|
||||||
|
4.5,
|
||||||
|
5.5,
|
||||||
|
6.5,
|
||||||
|
7.5,
|
||||||
|
8.5,
|
||||||
|
];
|
||||||
|
|
||||||
|
let ptr = sendDataFloat(memFloat, data);
|
||||||
|
wasm.instance.exports.calc(ptr, data.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; ++i) {
|
||||||
|
console.log(memFloat[ptr + i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc(size: number): number {
|
return wasm.instance.exports;
|
||||||
const head = this.mem[2];
|
}
|
||||||
this.mem[2] += size;
|
|
||||||
|
function alloc(mem: Int32Array, size: number): number {
|
||||||
|
const head = mem[2];
|
||||||
|
mem[2] += size;
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
setstr(ptr: number, str: string) {
|
function allocFloat(mem: Float32Array, size: number): number {
|
||||||
for (let i = 0; i < str.length; i++) {
|
const head = mem[2];
|
||||||
this.mem[ptr] = str.charCodeAt(i);
|
mem[2] += size;
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setstr(mem: Int32Array, ptr: number, size: number, str: string) {
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
mem[ptr] = str.charCodeAt(i);
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendData(mem: Int32Array, data: number[]): number {
|
||||||
|
let ptr = alloc(mem, data.length);
|
||||||
|
|
||||||
set(ptr: number, data: number[]): number {
|
|
||||||
data.forEach((v, i) => {
|
data.forEach((v, i) => {
|
||||||
this.mem[ptr + i] = v;
|
mem[ptr + i] = v;
|
||||||
});
|
});
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendDataFloat(mem: Float32Array, data: number[]): number {
|
||||||
|
let ptr = allocFloat(mem, data.length);
|
||||||
|
|
||||||
|
data.forEach((v, i) => {
|
||||||
|
mem[ptr + i] = v;
|
||||||
|
console.log(mem[ptr + i]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { loadWasmModule, alloc, setstr }
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
import * as Assets from "./assets.js";
|
|
||||||
import { Vec3 } from "./common.js";
|
|
||||||
export var TileEdge;
|
|
||||||
(function (TileEdge) {
|
|
||||||
TileEdge[TileEdge["None"] = 0] = "None";
|
|
||||||
TileEdge[TileEdge["Left"] = 1] = "Left";
|
|
||||||
TileEdge[TileEdge["Right"] = 2] = "Right";
|
|
||||||
TileEdge[TileEdge["Both"] = 3] = "Both";
|
|
||||||
})(TileEdge || (TileEdge = {}));
|
|
||||||
export class Tile {
|
|
||||||
fill = {
|
|
||||||
top: [1, 0, 1, 1],
|
|
||||||
left: [0, 0, 0, 1],
|
|
||||||
right: [0, 0, 0, 1],
|
|
||||||
};
|
|
||||||
edge = TileEdge.None;
|
|
||||||
constructor(fill, edge) {
|
|
||||||
if (fill !== undefined)
|
|
||||||
this.fill = fill;
|
|
||||||
if (edge !== undefined)
|
|
||||||
this.edge = edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function ColorToTile(c) {
|
|
||||||
return {
|
|
||||||
left: c,
|
|
||||||
top: c,
|
|
||||||
right: c,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export class Grid {
|
|
||||||
position;
|
|
||||||
tiles3d;
|
|
||||||
tileSize;
|
|
||||||
width;
|
|
||||||
length;
|
|
||||||
height;
|
|
||||||
constructor(position, tileSize, width, length, height) {
|
|
||||||
this.tiles3d = new Array(height);
|
|
||||||
this.position = position;
|
|
||||||
this.tileSize = tileSize;
|
|
||||||
this.width = width;
|
|
||||||
this.length = length;
|
|
||||||
this.height = height;
|
|
||||||
let layer = new Array(width * length);
|
|
||||||
for (let i = 0; i < this.height; ++i)
|
|
||||||
this.tiles3d[i] = { ...layer };
|
|
||||||
}
|
|
||||||
fillLayer(tile, z) {
|
|
||||||
for (let i = 0; i < this.width; ++i) {
|
|
||||||
for (let j = 0; j < this.length; ++j) {
|
|
||||||
this.tiles3d[z][i + j * this.width] = { ...tile };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = 0; i < this.width; ++i) {
|
|
||||||
this.tiles3d[z][this.length * i - 1] = { ...tile, edge: TileEdge.Right };
|
|
||||||
}
|
|
||||||
for (let i = 0; i < this.length - 1; ++i) {
|
|
||||||
this.tiles3d[z][this.width * (this.length - 1) + i] = { ...tile, edge: TileEdge.Left };
|
|
||||||
}
|
|
||||||
this.tiles3d[z][this.width * this.length - 1] = { ...tile, edge: TileEdge.Both };
|
|
||||||
}
|
|
||||||
setTile(tile, coord) {
|
|
||||||
let index = coord.x + coord.y * this.width;
|
|
||||||
this.tiles3d[coord.z][index] = { ...tile };
|
|
||||||
}
|
|
||||||
getTile(coord) {
|
|
||||||
let index = coord.x + coord.y * this.width;
|
|
||||||
let tile = this.tiles3d[coord.z][index];
|
|
||||||
if (tile === undefined)
|
|
||||||
return null;
|
|
||||||
return tile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function tree(grid, position) {
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 3));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.None), new Vec3(position.x, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 5));
|
|
||||||
}
|
|
||||||
export function bush(grid, position) {
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 2));
|
|
||||||
}
|
|
122
src/js/world.ts
|
@ -1,122 +0,0 @@
|
||||||
import * as Assets from "./assets.js";
|
|
||||||
import {Vec2, Vec3} from "./common.js";
|
|
||||||
import {Texture} from "./graphics.js";
|
|
||||||
|
|
||||||
export enum TileEdge {
|
|
||||||
None,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Both,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TileFillament = Texture | Assets.Color;
|
|
||||||
export type TileFill = { left: TileFillament, top: TileFillament, right: TileFillament };
|
|
||||||
|
|
||||||
export class Tile {
|
|
||||||
fill: TileFill = {
|
|
||||||
top : [1, 0, 1, 1],
|
|
||||||
left : [0, 0, 0, 1],
|
|
||||||
right : [0, 0, 0, 1],
|
|
||||||
};
|
|
||||||
edge: TileEdge = TileEdge.None;
|
|
||||||
|
|
||||||
constructor(fill?: TileFill, edge?: TileEdge) {
|
|
||||||
if (fill !== undefined)
|
|
||||||
this.fill = fill;
|
|
||||||
|
|
||||||
if (edge !== undefined)
|
|
||||||
this.edge = edge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ColorToTile(c: Assets.Color) {
|
|
||||||
return {
|
|
||||||
left: c,
|
|
||||||
top: c,
|
|
||||||
right: c,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Grid {
|
|
||||||
position: Vec3;
|
|
||||||
tiles3d: Tile[][];
|
|
||||||
tileSize: number;
|
|
||||||
|
|
||||||
width: number;
|
|
||||||
length: number;
|
|
||||||
height: number;
|
|
||||||
|
|
||||||
constructor(position: Vec3, tileSize: number, width: number, length: number, height: number) {
|
|
||||||
this.tiles3d = new Array<Tile[]>(height);
|
|
||||||
this.position = position;
|
|
||||||
|
|
||||||
this.tileSize = tileSize;
|
|
||||||
|
|
||||||
this.width = width;
|
|
||||||
this.length = length;
|
|
||||||
this.height = height;
|
|
||||||
|
|
||||||
let layer = new Array(width * length);
|
|
||||||
|
|
||||||
for (let i = 0; i < this.height; ++i)
|
|
||||||
this.tiles3d[i] = {...layer};
|
|
||||||
}
|
|
||||||
|
|
||||||
fillLayer(tile: Tile, z: number) {
|
|
||||||
for (let i = 0; i < this.width; ++i) {
|
|
||||||
for (let j = 0; j < this.length; ++j) {
|
|
||||||
this.tiles3d[z][i + j * this.width] = {...tile};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.width; ++i) {
|
|
||||||
this.tiles3d[z][this.length * i - 1] = {...tile, edge: TileEdge.Right};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.length - 1; ++i) {
|
|
||||||
this.tiles3d[z][this.width * (this.length - 1) + i] = {...tile, edge: TileEdge.Left};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tiles3d[z][this.width * this.length - 1] = {...tile, edge: TileEdge.Both};
|
|
||||||
}
|
|
||||||
|
|
||||||
setTile(tile: Tile, coord: Vec3) {
|
|
||||||
let index = coord.x + coord.y * this.width;
|
|
||||||
this.tiles3d[coord.z][index] = {...tile};
|
|
||||||
}
|
|
||||||
|
|
||||||
getTile(coord: Vec3): Tile | null {
|
|
||||||
let index = coord.x + coord.y * this.width;
|
|
||||||
let tile = this.tiles3d[coord.z][index];
|
|
||||||
|
|
||||||
if (tile === undefined) return null;
|
|
||||||
|
|
||||||
return tile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function tree(grid: Grid, position: Vec2) {
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 3));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.None), new Vec3(position.x, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 5));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 4));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 5));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bush(grid: Grid, position: Vec2) {
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 1));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 1));
|
|
||||||
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 2));
|
|
||||||
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 2));
|
|
||||||
}
|
|
|
@ -1,20 +1,19 @@
|
||||||
#include "wasmgl.h"
|
#include "wasmgl.h"
|
||||||
|
|
||||||
void doubel(WASMGLvalue(0))
|
int WASMGLmemory[WASMGLmemory_size] = {
|
||||||
|
[MEM_SIZE] = WASMGLmemory_size,
|
||||||
|
[MEM_HEAD] = MEM_ELEM_COUNT,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void calc(WASMGLvalue(0))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < size_0; ++i)
|
for (int i = 0; i < size_0; ++i)
|
||||||
WASMGLset(ptr_0 + i, WASMGLmemory[ptr_0 + i] * 2.0);
|
WASMGLmemory[ptr_0 + i] = ((float) WASMGLmemory[ptr_0 + i]) * 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uppercase(WASMGLvalue(0)) {
|
int main(void)
|
||||||
int val = 0;
|
{
|
||||||
|
|
||||||
for (int i = 0; i < size_0; ++i)
|
return 0;
|
||||||
{
|
|
||||||
val = WASMGLmemory[ptr_0 + i] - 32;
|
|
||||||
|
|
||||||
if (val < 65 || val > 122) val = WASMGLmemory[ptr_0 + i];
|
|
||||||
|
|
||||||
WASMGLset(ptr_0 + i, val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
#include "wasmgl.h"
|
#include "wasmgl.h"
|
||||||
|
|
||||||
float WASMGLmemory[WASMGLmemory_size] = {
|
WASMGLptr WASMGLmalloc(int * mem, WASMGLsize size)
|
||||||
[MEM_SIZE] = WASMGLmemory_size,
|
|
||||||
[MEM_HEAD] = MEM_ELEM_COUNT,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
WASMGLptr WASMGLmalloc(WASMGLsize size)
|
|
||||||
{
|
{
|
||||||
WASMGLptr ptr = WASMGLmemory[MEM_HEAD];
|
WASMGLptr ptr = mem[MEM_HEAD];
|
||||||
WASMGLmemory[MEM_HEAD] += size;
|
mem[MEM_HEAD] += size;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WASMGLset(WASMGLptr ptr, int value)
|
void WASMGLset(int * mem, WASMGLptr ptr, int value)
|
||||||
{
|
{
|
||||||
WASMGLmemory[ptr] = value;
|
mem[ptr] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WASMGLsetstr(WASMGLptr ptr, const char * cstr, WASMGLsize size)
|
void WASMGLsetstr(int * mem, WASMGLptr ptr, const char * cstr, WASMGLsize size)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
WASMGLset(ptr + i, cstr[i]);
|
{
|
||||||
|
WASMGLset(mem, ptr + i, cstr[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,12 @@ typedef enum {
|
||||||
MEM_ELEM_COUNT,
|
MEM_ELEM_COUNT,
|
||||||
} WASMGLmemory_layout;
|
} WASMGLmemory_layout;
|
||||||
|
|
||||||
extern float WASMGLmemory[WASMGLmemory_size];
|
|
||||||
|
|
||||||
typedef unsigned int WASMGLptr;
|
typedef unsigned int WASMGLptr;
|
||||||
typedef unsigned int WASMGLsize;
|
typedef unsigned int WASMGLsize;
|
||||||
|
|
||||||
#define WASMGLvalue(n) WASMGLptr ptr_##n, WASMGLsize size_##n
|
#define WASMGLvalue(n) WASMGLptr ptr_##n, WASMGLsize size_##n
|
||||||
|
|
||||||
WASMGLptr WASMGLmalloc(WASMGLsize size);
|
WASMGLptr WASMGLmalloc(int * mem, WASMGLsize size);
|
||||||
void WASMGLset(WASMGLptr ptr, int value);
|
void WASMGLset(int * mem, WASMGLptr ptr, int value);
|
||||||
void WASMGLsetstr(WASMGLptr ptr, const char * cstr, WASMGLsize size);
|
void WASMGLsetstr(int * mem, WASMGLptr ptr, const char * cstr, WASMGLsize size);
|
||||||
#endif // WASMGL_H_
|
#endif // WASMGL_H_
|
||||||
|
|