diff --git a/src/js/colors.js b/src/js/colors.js
new file mode 100644
index 0000000..3f184ca
--- /dev/null
+++ b/src/js/colors.js
@@ -0,0 +1,4 @@
+export let Red = [1, 0, 0, 1];
+export let Green = [0, 1, 0, 1];
+export let Blue = [0, 0, 1, 1];
+export let Brown = [0.341, 0.337, 0.204, 1];
diff --git a/src/js/colors.ts b/src/js/colors.ts
new file mode 100644
index 0000000..6fe4f78
--- /dev/null
+++ b/src/js/colors.ts
@@ -0,0 +1,6 @@
+export type Color = [number, number, number, number]
+
+export let Red : Color = [1, 0, 0, 1];
+export let Green : Color = [0, 1, 0, 1];
+export let Blue : Color = [0, 0, 1, 1];
+export let Brown : Color = [0.341, 0.337, 0.204, 1];
diff --git a/src/js/common.js b/src/js/common.js
index f0c813a..6b48587 100644
--- a/src/js/common.js
+++ b/src/js/common.js
@@ -10,6 +10,9 @@ class Vec2 {
this.x = x;
this.y = y;
}
+ copy() {
+ return new Vec2(this.x, this.y);
+ }
add(other) {
this.x += other.x;
this.y += other.y;
@@ -28,13 +31,43 @@ class Vec2 {
this.x -= other.x;
this.y -= other.y;
}
- mult(scalar) {
+ subNew(other) {
+ let vec = this.copy();
+ vec.x -= other.x;
+ vec.y -= other.y;
+ return vec;
+ }
+ multScalar(scalar) {
this.x *= scalar;
this.y *= scalar;
}
- multNew(scalar) {
+ multScalarNew(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() {
return [this.x, this.y];
}
@@ -60,28 +93,73 @@ class Vec3 {
this.y = y;
this.z = z;
}
+ copy() {
+ return new Vec3(this.x, this.y, this.z);
+ }
add(other) {
this.x += other.x;
this.y += other.y;
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) {
this.x -= other.x;
this.y -= other.y;
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 = new Vec3(this.x, this.y, this.z);
+ 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];
}
@@ -97,18 +175,37 @@ class Vec4 {
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;
@@ -116,7 +213,7 @@ class Vec4 {
this.w *= scalar;
}
multScalarNew(scalar) {
- let vec = new Vec4(this.x, this.y, this.z, this.w);
+ let vec = this.copy();
vec.x *= scalar;
vec.y *= scalar;
vec.z *= scalar;
@@ -142,7 +239,7 @@ class Vec4 {
other.w == 0) {
throw new Error("Division by zero in Vec4");
}
- let vec = new Vec4(this.x, this.y, this.z, this.w);
+ let vec = this.copy();
vec.x /= other.x;
vec.y /= other.y;
vec.z /= other.z;
@@ -152,11 +249,15 @@ class Vec4 {
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;
}
diff --git a/src/js/common.ts b/src/js/common.ts
index aad594f..9b15e57 100644
--- a/src/js/common.ts
+++ b/src/js/common.ts
@@ -5,14 +5,27 @@ function initializeContext(canvasId: string): WebGL2RenderingContext | null {
return ctx;
}
-type Color = [number, number, number, number]
-
// TODO: Make all vectors follow one interface
-interface Vector {
+interface Vector
{
+ copy(): T;
+ add(other: T): void;
+ 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 {
+class Vec2 implements Vector {
x: number;
y: number;
@@ -21,6 +34,10 @@ class Vec2 {
this.y = y;
}
+ copy(): Vec2 {
+ return new Vec2(this.x, this.y);
+ }
+
add(other: Vec2) {
this.x += other.x;
this.y += other.y;
@@ -44,15 +61,58 @@ class Vec2 {
this.y -= other.y;
}
- mult(scalar: number) {
+ subNew(other: Vec2): Vec2 {
+ let vec = this.copy();
+
+ vec.x -= other.x;
+ vec.y -= other.y;
+
+ return vec;
+ }
+
+ multScalar(scalar: number) {
this.x *= scalar;
this.y *= scalar;
}
- multNew(scalar: number): Vec2 {
+ multScalarNew(scalar: number): Vec2 {
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 {
return [this.x, this.y];
}
@@ -74,7 +134,7 @@ class Vec2 {
}
}
-class Vec3 {
+class Vec3 implements Vector {
x: number;
y: number;
z: number;
@@ -85,18 +145,42 @@ class Vec3 {
this.z = z;
}
+ copy(): Vec3 {
+ return new Vec3(this.x, this.y, this.z);
+ }
+
add(other: Vec3) {
this.x += other.x;
this.y += other.y;
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) {
this.x -= other.x;
this.y -= other.y;
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;
@@ -104,7 +188,7 @@ class Vec3 {
}
multScalarNew(scalar: number): Vec3 {
- let vec = new Vec3(this.x, this.y, this.z);
+ let vec = this.copy();
vec.x *= scalar;
vec.y *= scalar;
@@ -113,12 +197,50 @@ class Vec3 {
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 {
return [this.x, this.y, this.z];
}
}
-class Vec4 {
+class Vec4 implements Vector {
x: number;
y: number;
z: number;
@@ -131,6 +253,10 @@ class Vec4 {
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;
@@ -138,6 +264,17 @@ class Vec4 {
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;
@@ -145,6 +282,17 @@ class Vec4 {
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;
@@ -153,7 +301,7 @@ class Vec4 {
}
multScalarNew(scalar: number): Vec4 {
- let vec = new Vec4(this.x, this.y, this.z, this.w);
+ let vec = this.copy();
vec.x *= scalar;
vec.y *= scalar;
@@ -187,7 +335,7 @@ class Vec4 {
throw new Error("Division by zero in Vec4");
}
- let vec = new Vec4(this.x, this.y, this.z, this.w);
+ let vec = this.copy();
vec.x /= other.x;
vec.y /= other.y;
@@ -200,6 +348,10 @@ class Vec4 {
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;
@@ -216,6 +368,7 @@ class Mat4 {
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') {
@@ -374,4 +527,4 @@ class Mat4 {
}
}
-export { initializeContext, Mat4, Vec2, Vec3, Vec4, Color };
+export { initializeContext, Mat4, Vec2, Vec3, Vec4 };
diff --git a/src/js/draw.js b/src/js/draw.js
index a351379..8cdc8b4 100644
--- a/src/js/draw.js
+++ b/src/js/draw.js
@@ -1,5 +1,17 @@
import { Vec3, Vec2 } from "./common.js";
import { Texture } from "./graphics.js";
+import { TileEdge } from "./world.js";
+function cull(bb, screen) {
+ if (bb.x > screen.x)
+ return false;
+ if (bb.x + bb.z < screen.x + screen.z)
+ return false;
+ if (bb.y > screen.y)
+ return false;
+ if (bb.y + bb.w < screen.y + screen.w)
+ return false;
+ return true;
+}
export function drawTriangle(gfx, positions, color) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
@@ -69,7 +81,7 @@ export function drawRectangle(gfx, corners, color) {
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
}
}
-export function drawIsometricCube(gfx, position, exts, color) {
+export function drawIsometricCube(gfx, position, exts, color, edge) {
let points = [
position,
new Vec3(position.x, position.y + exts.y, position.z),
@@ -80,26 +92,60 @@ export function drawIsometricCube(gfx, position, exts, color) {
new Vec3(position.x + 0.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z),
];
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 1);
+ // Top
drawRectangle(gfx, [
points[0],
points[1],
points[3],
points[2],
], color);
- drawRectangle(gfx, [
- points[3],
- points[2],
- points[4],
- points[5],
- ], color);
- drawRectangle(gfx, [
- points[0],
- points[2],
- points[4],
- points[6],
- ], color);
+ // Right Edge
+ if (edge == TileEdge.Right || edge == TileEdge.Both) {
+ drawRectangle(gfx, [
+ points[3],
+ points[2],
+ points[4],
+ points[5],
+ ], color);
+ }
+ // Left Edge
+ if (edge == TileEdge.Left || edge == TileEdge.Both) {
+ drawRectangle(gfx, [
+ points[0],
+ points[2],
+ points[4],
+ points[6],
+ ], color);
+ }
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 0);
}
+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);
+ // Optimize this by:
+ // 1. Skip all empty tiles by using lowTiles
+ // 2. tba
+ 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 function drawRectangleExts(gfx, position, exts, color) {
const a_position = gfx.getAttribute("a_position");
const points = [
@@ -142,7 +188,7 @@ export function drawCircle(gfx, position, radius, color) {
let a = 0;
for (let i = 0; i < precision; ++i) {
var vec = Vec2.angle(a);
- vec.mult(radius);
+ vec.multScalar(radius);
a += angle;
points.push(vec);
}
diff --git a/src/js/draw.ts b/src/js/draw.ts
index f7ed7b2..b3d75ce 100644
--- a/src/js/draw.ts
+++ b/src/js/draw.ts
@@ -1,5 +1,17 @@
-import { Vec3, Vec2, Color } from "./common.js"
+import {Color} from "./colors.js";
+import { Vec3, Vec2, Vec4 } from "./common.js"
import { Graphics, Texture } from "./graphics.js";
+import {Grid, TileEdge} from "./world.js";
+
+function cull(bb: Vec4, screen: Vec4): boolean {
+ if (bb.x > screen.x) return false;
+ if (bb.x + bb.z < screen.x + screen.z) return false;
+
+ if (bb.y > screen.y) return false;
+ if (bb.y + bb.w < screen.y + screen.w) return false;
+
+ return true;
+}
export function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) {
const a_position = gfx.getAttribute("a_position");
@@ -87,7 +99,7 @@ export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3],
}
-export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color | Texture) {
+export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color | Texture, edge: TileEdge) {
let points = [
position,
new Vec3(position.x, position.y + exts.y, position.z),
@@ -100,6 +112,7 @@ export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, col
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 1);
+ // Top
drawRectangle(
gfx,
[
@@ -109,30 +122,70 @@ export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, col
points[2],
],
color);
+
+ // Right Edge
- drawRectangle(
- gfx,
- [
- points[3],
- points[2],
- points[4],
- points[5],
- ],
- color);
+ if (edge == TileEdge.Right || edge == TileEdge.Both) {
+ drawRectangle(
+ gfx,
+ [
+ points[3],
+ points[2],
+ points[4],
+ points[5],
+ ],
+ color);
+ }
- drawRectangle(
- gfx,
- [
- points[0],
- points[2],
- points[4],
- points[6],
- ],
- color);
+ // Left Edge
+ if (edge == TileEdge.Left || edge == TileEdge.Both) {
+ drawRectangle(
+ gfx,
+ [
+ points[0],
+ points[2],
+ points[4],
+ points[6],
+ ],
+ color);
+ }
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 0);
}
+export function drawIsometricGrid(gfx: Graphics, grid: Grid) {
+ let position = {...grid.position} as Vec3;
+ let exts = new Vec3(grid.tileSize, grid.tileSize, 0);
+ let tileCoord = new Vec3(0, 0, 0);
+
+ // Optimize this by:
+ // 1. Skip all empty tiles by using lowTiles
+ // 2. tba
+ 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 function drawRectangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Color | Texture) {
const a_position = gfx.getAttribute("a_position");
@@ -184,7 +237,7 @@ export function drawCircle(gfx: Graphics, position: Vec2, radius: number, color:
let a = 0;
for (let i = 0; i < precision; ++i) {
var vec = Vec2.angle(a);
- vec.mult(radius);
+ vec.multScalar(radius);
a += angle;
points.push(vec);
}
diff --git a/src/js/graphics.js b/src/js/graphics.js
index c7027a2..b3defd2 100644
--- a/src/js/graphics.js
+++ b/src/js/graphics.js
@@ -110,7 +110,11 @@ export class Attribute {
}
export class Texture {
tex;
- constructor(tex) {
+ width = 0;
+ height = 0;
+ constructor(tex, width, height) {
+ this.height = height;
+ this.width = width;
this.tex = tex;
}
static async load(ctx, path) {
@@ -122,7 +126,7 @@ export class Texture {
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR_MIPMAP_NEAREST);
ctx.generateMipmap(ctx.TEXTURE_2D);
ctx.bindTexture(ctx.TEXTURE_2D, null);
- return new Texture(tex);
+ return new Texture(tex, image.width, image.height);
}
bind(gfx) {
gfx.ctx.uniform1i(gfx.getUniform("u_isTex"), 1);
diff --git a/src/js/graphics.ts b/src/js/graphics.ts
index 8b90fc9..b0e38e9 100644
--- a/src/js/graphics.ts
+++ b/src/js/graphics.ts
@@ -146,8 +146,12 @@ export class Attribute {
export class Texture {
tex: WebGLTexture | null;
+ width: number = 0;
+ height: number = 0;
- constructor(tex: WebGLTexture) {
+ constructor(tex: WebGLTexture, width: number, height: number) {
+ this.height = height;
+ this.width = width;
this.tex = tex;
}
@@ -162,7 +166,7 @@ export class Texture {
ctx.generateMipmap(ctx.TEXTURE_2D);
ctx.bindTexture(ctx.TEXTURE_2D, null);
- return new Texture(tex);
+ return new Texture(tex, image.width, image.height);
}
bind(gfx: Graphics) {
diff --git a/src/js/script.js b/src/js/script.js
index f5efe7d..269d572 100644
--- a/src/js/script.js
+++ b/src/js/script.js
@@ -1,8 +1,9 @@
-import { initializeContext, Vec3, Mat4 } from "./common.js";
-import { Graphics, fullscreenCanvas, Texture, Camera } from "./graphics.js";
+import { initializeContext, Vec3, Mat4, Vec2 } from "./common.js";
+import { Graphics, fullscreenCanvas, Camera } from "./graphics.js";
import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
import { Input } from "./input.js";
+import { Grid, Tile, tree } from "./world.js";
const vertexShader = `#version 300 es
in vec3 a_position;
@@ -59,30 +60,30 @@ const fragmentShader = `#version 300 es
}
}
`;
-function draw(gfx, camera, dt, tex) {
+function draw(gfx, camera, dt, grid) {
gfx.clear(0, 0, 0, 0);
camera.update(dt);
- let right = gfx.ctx.canvas.width;
- let left = 0;
- let top = gfx.ctx.canvas.height;
- let bottom = 0;
+ let zoom = 2;
+ let right = gfx.ctx.canvas.width * zoom;
+ let left = -right * zoom;
+ let top = gfx.ctx.canvas.height * zoom;
+ let bottom = -top * zoom;
let near = -100;
let far = 100;
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
let mt = Mat4.translate(camera.position);
- let mi = Mat4.isometric();
let m = mo.multNew(mt);
gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat());
- let exts = new Vec3(50, 50, 20);
- for (let i = 0; i < 10; ++i) {
- for (let j = 0; j < 10; ++j) {
- //drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [Math.sin(angle * i + j), Math.cos(angle * i + j), -Math.sin(angle * i + j), 1]);
- if ((i + j) % 2)
- drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]);
- else
- drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, tex);
- }
- }
+ //let exts = new Vec3(50, 50, 20);
+ //for (let i = 0; i < 10; ++i) {
+ // for (let j = 0; j < 10; ++j) {
+ // if ((i + j) % 2)
+ // drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 0, 1, 1], TileEdge.None);
+ // else
+ // drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 0, 1], TileEdge.None);
+ // }
+ //}
+ drawing.drawIsometricGrid(gfx, grid);
}
function addDefaultKeybinds(input, camera) {
input.addKeyAction("KeyA", [], camera, (c) => {
@@ -122,15 +123,20 @@ function addDefaultKeybinds(input, camera) {
gfx.createUniform("u_matrix");
gfx.createUniform("u_isTex");
gfx.createUniform("u_isIso");
- let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
- let wall = await Texture.load(ctx, "../../assets/wall.png");
+ //let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
+ //let wall = await Texture.load(ctx, "../../assets/wall.png");
let camera = new Camera(new Vec3(0, 0, 0));
+ let grid = new Grid(new Vec3(-800, 0, 0), 100, 20, 20, 10);
+ grid.fillLayer(new Tile([0, 0, 1, 1]), 0);
+ for (let i = 0; i < 5; i++) {
+ tree(grid, new Vec2(Math.floor(Math.random() * 19), Math.floor(Math.random() * 19)));
+ }
let prevTimestamp = 0;
const frame = (timestamp) => {
const deltaTime = (timestamp - prevTimestamp) / 1000;
prevTimestamp = timestamp;
fullscreenCanvas(gfx, "game");
- draw(gfx, camera, deltaTime, wall);
+ draw(gfx, camera, deltaTime, grid);
window.requestAnimationFrame(frame);
};
window.requestAnimationFrame((timestamp) => {
diff --git a/src/js/script.ts b/src/js/script.ts
index 342901e..9b80770 100644
--- a/src/js/script.ts
+++ b/src/js/script.ts
@@ -3,6 +3,7 @@ import { Graphics, fullscreenCanvas, Texture, Camera } from "./graphics.js";
import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
import { Input } from "./input.js";
+import {Grid, Tile, tree} from "./world.js";
const vertexShader =
`#version 300 es
@@ -64,24 +65,20 @@ const fragmentShader =
}
`;
-
-
-function draw(gfx: Graphics, camera: Camera, dt: number, tex: Texture) {
+function draw(gfx: Graphics, camera: Camera, dt: number, grid: Grid) {
gfx.clear(0, 0, 0, 0);
camera.update(dt);
-
- let right = gfx.ctx.canvas.width;
- let left = 0;
- let top = gfx.ctx.canvas.height;
- let bottom = 0;
+ let zoom = 2;
+ let right = gfx.ctx.canvas.width * zoom;
+ let left = -right * zoom;
+ let top = gfx.ctx.canvas.height * zoom;
+ let bottom = -top * zoom;
let near = -100;
let far = 100;
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
let mt = Mat4.translate(camera.position);
- let mi = Mat4.isometric();
-
let m = mo.multNew(mt);
gfx.ctx.uniformMatrix4fv(
@@ -90,17 +87,17 @@ function draw(gfx: Graphics, camera: Camera, dt: number, tex: Texture) {
m.splat()
);
- let exts = new Vec3(50, 50, 20);
- for (let i = 0; i < 10; ++i) {
- for (let j = 0; j < 10; ++j) {
- //drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [Math.sin(angle * i + j), Math.cos(angle * i + j), -Math.sin(angle * i + j), 1]);
-
- if ((i + j) % 2)
- drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]);
- else
- drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, tex);
- }
- }
+ //let exts = new Vec3(50, 50, 20);
+ //for (let i = 0; i < 10; ++i) {
+ // for (let j = 0; j < 10; ++j) {
+ // if ((i + j) % 2)
+ // drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 0, 1, 1], TileEdge.None);
+ // else
+ // drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 0, 1], TileEdge.None);
+ // }
+ //}
+
+ drawing.drawIsometricGrid(gfx, grid);
}
function addDefaultKeybinds(input: Input, camera: Camera) {
@@ -158,18 +155,26 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
gfx.createUniform("u_isTex");
gfx.createUniform("u_isIso");
- let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
- let wall = await Texture.load(ctx, "../../assets/wall.png");
+ //let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
+ //let wall = await Texture.load(ctx, "../../assets/wall.png");
let camera = new Camera(new Vec3(0, 0, 0));
+ let grid = new Grid(new Vec3(-800, 0, 0), 100, 20, 20, 10);
+ grid.fillLayer(new Tile([0, 0, 1, 1]), 0);
+
+
+ for (let i = 0; i < 5; i++) {
+ tree(grid, new Vec2(Math.floor(Math.random() * 19), Math.floor(Math.random() * 19)));
+ }
+
let prevTimestamp = 0;
const frame = (timestamp: number) => {
const deltaTime = (timestamp - prevTimestamp)/1000;
prevTimestamp = timestamp;
fullscreenCanvas(gfx, "game");
- draw(gfx, camera, deltaTime, wall);
+ draw(gfx, camera, deltaTime, grid);
window.requestAnimationFrame(frame);
}
diff --git a/src/js/world.js b/src/js/world.js
new file mode 100644
index 0000000..9ddffe0
--- /dev/null
+++ b/src/js/world.js
@@ -0,0 +1,73 @@
+import * as Colors from "./colors.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 = [1, 0, 1, 1];
+ edge = TileEdge.None;
+ constructor(fill, edge) {
+ if (fill !== undefined)
+ this.fill = fill;
+ if (edge !== undefined)
+ this.edge = edge;
+ }
+}
+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(Colors.Brown, TileEdge.Both), new Vec3(position.x, position.y, 1));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 3));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 5));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 3));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 6));
+}
diff --git a/src/js/world.ts b/src/js/world.ts
new file mode 100644
index 0000000..7612ffe
--- /dev/null
+++ b/src/js/world.ts
@@ -0,0 +1,92 @@
+import * as Colors from "./colors.js";
+import {Vec2, Vec3} from "./common.js";
+import {Texture} from "./graphics.js";
+
+export enum TileEdge {
+ None,
+ Left,
+ Right,
+ Both,
+}
+
+export class Tile {
+ fill: Texture | Colors.Color = [1, 0, 1, 1];
+ edge: TileEdge = TileEdge.None;
+
+ constructor(fill?: Texture | Colors.Color, edge?: TileEdge) {
+ if (fill !== undefined)
+ this.fill = fill;
+
+ if (edge !== undefined)
+ this.edge = edge;
+ }
+}
+
+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(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(Colors.Brown, TileEdge.Both), new Vec3(position.x, position.y, 1));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 3));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 5));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 3));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
+ grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 6));
+}