Add glMatrix
This commit is contained in:
parent
582979d3ed
commit
e88b4589d2
26 changed files with 212 additions and 359 deletions
|
|
@ -22,3 +22,4 @@ A good-looking 2D adventure.
|
||||||
- monitoring
|
- monitoring
|
||||||
- traefik
|
- traefik
|
||||||
- digital ocean docker contianer registry
|
- digital ocean docker contianer registry
|
||||||
|
- dynamic shader generation
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,13 @@
|
||||||
"usedExports": true
|
"usedExports": true
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/gl-matrix": "^2.4.5",
|
||||||
"@types/uuid": "^8.0.0",
|
"@types/uuid": "^8.0.0",
|
||||||
"autoprefixer": "^9.8.5",
|
"autoprefixer": "^9.8.5",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"css-loader": "^3.5.2",
|
"css-loader": "^3.5.2",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
|
"gl-matrix": "^3.3.0",
|
||||||
"html-webpack-inline-source-plugin": "0.0.10",
|
"html-webpack-inline-source-plugin": "0.0.10",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"image-webpack-loader": "^6.0.0",
|
"image-webpack-loader": "^6.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
import './styles/main.scss';
|
import './styles/main.scss';
|
||||||
import { Game } from './scripts/game';
|
import { Game } from './scripts/game';
|
||||||
|
import { applyArrayPlugins } from './scripts/helper/array';
|
||||||
|
import { glMatrix } from 'gl-matrix';
|
||||||
|
|
||||||
|
glMatrix.setMatrixArrayType(Array);
|
||||||
|
applyArrayPlugins();
|
||||||
|
|
||||||
new Game();
|
new Game();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
import { Vec2 } from '../../math/vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class MoveToCommand extends Command {
|
export class MoveToCommand extends Command {
|
||||||
public constructor(public readonly position?: Vec2) {
|
public constructor(public readonly position?: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
import { Vec2 } from '../../math/vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class PrimaryActionCommand extends Command {
|
export class PrimaryActionCommand extends Command {
|
||||||
public constructor(public readonly position?: Vec2) {
|
public constructor(public readonly position?: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
import { Vec2 } from '../../math/vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class SecondaryActionCommand extends Command {
|
export class SecondaryActionCommand extends Command {
|
||||||
public constructor(public readonly position?: Vec2) {
|
public constructor(public readonly position?: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
import { Vec2 } from '../../math/vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class SwipeCommand extends Command {
|
export class SwipeCommand extends Command {
|
||||||
public constructor(public readonly delta?: Vec2) {
|
public constructor(public readonly delta?: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { Vec2 } from '../math/vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { Rectangle } from '../math/rectangle';
|
|
||||||
|
|
||||||
export interface Drawer {
|
export interface Drawer {
|
||||||
startFrame(): void;
|
startFrame(): void;
|
||||||
finishFrame(): void;
|
finishFrame(): void;
|
||||||
giveUniforms(uniforms: any): void;
|
giveUniforms(uniforms: any): void;
|
||||||
setCameraPosition(position: Vec2): void;
|
setCameraPosition(position: vec2): void;
|
||||||
setInViewArea(size: number): Vec2;
|
setCursorPosition(position: vec2): void;
|
||||||
|
setInViewArea(size: number): vec2;
|
||||||
drawInfoText(text: string): void;
|
drawInfoText(text: string): void;
|
||||||
isOnScreen(position: Vec2): boolean;
|
isOnScreen(position: vec2): boolean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Vec2 } from '../../math/vec2';
|
|
||||||
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
|
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export abstract class FrameBuffer {
|
export abstract class FrameBuffer {
|
||||||
public renderScale = 1;
|
public renderScale = 1;
|
||||||
public enableHighDpiRendering = false;
|
public enableHighDpiRendering = false;
|
||||||
|
|
||||||
protected size: Vec2;
|
protected size: vec2;
|
||||||
protected frameBuffer: WebGLFramebuffer;
|
protected frameBuffer: WebGLFramebuffer;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -39,10 +39,10 @@ export abstract class FrameBuffer {
|
||||||
const displayWidth = Math.floor(canvasWidth * realToCssPixels);
|
const displayWidth = Math.floor(canvasWidth * realToCssPixels);
|
||||||
const displayHeight = Math.floor(canvasHeight * realToCssPixels);
|
const displayHeight = Math.floor(canvasHeight * realToCssPixels);
|
||||||
|
|
||||||
this.size = new Vec2(displayWidth, displayHeight);
|
this.size = vec2.fromValues(displayWidth, displayHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSize(): Vec2 {
|
public getSize(): vec2 {
|
||||||
return this.size;
|
return this.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Vec2 } from '../../math/vec2';
|
import { mat3, vec2 } from 'gl-matrix';
|
||||||
import { Mat3 } from '../../math/mat3';
|
|
||||||
|
const loaderMat3 = mat3.create();
|
||||||
|
|
||||||
export const loadUniform = (
|
export const loadUniform = (
|
||||||
gl: WebGL2RenderingContext,
|
gl: WebGL2RenderingContext,
|
||||||
|
|
@ -22,23 +23,23 @@ export const loadUniform = (
|
||||||
|
|
||||||
converters.set(
|
converters.set(
|
||||||
WebGL2RenderingContext.FLOAT_VEC2,
|
WebGL2RenderingContext.FLOAT_VEC2,
|
||||||
(gl, v: Vec2 | Array<Vec2>, l) => {
|
(gl, v: vec2 | Array<vec2>, l) => {
|
||||||
if (v instanceof Array) {
|
if (v[0] instanceof Array) {
|
||||||
const result = new Float32Array(v.length * 2);
|
const result = new Float32Array(v.length * 2);
|
||||||
for (let i = 0; i < v.length; i++) {
|
for (let i = 0; i < v.length; i++) {
|
||||||
result[2 * i] = v[i].x;
|
result[2 * i] = (v[i] as Array<number>).x;
|
||||||
result[2 * i + 1] = v[i].y;
|
result[2 * i + 1] = (v[i] as Array<number>).y;
|
||||||
}
|
}
|
||||||
gl.uniform2fv(l, new Float32Array(result));
|
gl.uniform2fv(l, new Float32Array(result));
|
||||||
} else {
|
} else {
|
||||||
gl.uniform2fv(l, new Float32Array(v.list));
|
gl.uniform2fv(l, v as vec2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
converters.set(WebGL2RenderingContext.FLOAT_MAT3, (gl, v: Mat3, l) =>
|
converters.set(WebGL2RenderingContext.FLOAT_MAT3, (gl, v, l) => {
|
||||||
gl.uniformMatrix3fv(l, false, new Float32Array(v.transposedFlat))
|
gl.uniformMatrix3fv(l, true, mat3.fromMat2d(loaderMat3, v));
|
||||||
);
|
});
|
||||||
|
|
||||||
converters.set(WebGL2RenderingContext.BOOL, (gl, v, l) =>
|
converters.set(WebGL2RenderingContext.BOOL, (gl, v, l) =>
|
||||||
gl.uniform1i(l, v)
|
gl.uniform1i(l, v)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { Drawer } from './drawer';
|
import { Drawer } from './drawer';
|
||||||
import { Vec2 } from '../math/vec2';
|
import { mat2d, vec2, mat2, mat3 } from 'gl-matrix';
|
||||||
import { Mat3 } from '../math/mat3';
|
|
||||||
import { FragmentShaderOnlyProgram } from './graphics-library/fragment-shader-only-program';
|
import { FragmentShaderOnlyProgram } from './graphics-library/fragment-shader-only-program';
|
||||||
import { WebGlStopwatch } from './graphics-library/stopwatch';
|
import { WebGlStopwatch } from './graphics-library/stopwatch';
|
||||||
import { Rectangle } from '../math/rectangle';
|
import { Rectangle } from '../math/rectangle';
|
||||||
|
|
@ -14,6 +13,7 @@ export class WebGl2Renderer implements Drawer {
|
||||||
|
|
||||||
private viewBox: Rectangle = new Rectangle();
|
private viewBox: Rectangle = new Rectangle();
|
||||||
private nextFrameUniforms: any;
|
private nextFrameUniforms: any;
|
||||||
|
private cursorPosition = vec2.create();
|
||||||
private frameBuffers: Array<FrameBuffer> = [];
|
private frameBuffers: Array<FrameBuffer> = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -38,7 +38,7 @@ export class WebGl2Renderer implements Drawer {
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
this.frameBuffers[0].renderScale = 0.2;
|
this.frameBuffers[0].renderScale = 1;
|
||||||
this.frameBuffers[1].renderScale = 1;
|
this.frameBuffers[1].renderScale = 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -53,19 +53,30 @@ export class WebGl2Renderer implements Drawer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public finishFrame() {
|
public finishFrame() {
|
||||||
const resolution = new Vec2(this.canvas.width, this.canvas.height);
|
const resolution = vec2.fromValues(this.canvas.width, this.canvas.height);
|
||||||
|
|
||||||
this.nextFrameUniforms.transform = Mat3.translateMatrix(new Vec2(0.5, 0.5))
|
const transform = mat2d.fromTranslation(
|
||||||
.times(
|
mat2d.create(),
|
||||||
Mat3.scaleMatrix(
|
this.viewBox.topLeft
|
||||||
this.viewBox.size.divide(this.frameBuffers[0].getSize())
|
);
|
||||||
)
|
mat2d.scale(
|
||||||
|
transform,
|
||||||
|
transform,
|
||||||
|
vec2.divide(
|
||||||
|
vec2.create(),
|
||||||
|
this.viewBox.size,
|
||||||
|
this.frameBuffers[0].getSize()
|
||||||
)
|
)
|
||||||
.times(Mat3.translateMatrix(this.viewBox.topLeft));
|
);
|
||||||
|
mat2d.translate(transform, transform, vec2.fromValues(0.5, 0.5));
|
||||||
|
this.nextFrameUniforms.transform = transform;
|
||||||
|
|
||||||
this.nextFrameUniforms.transformUV = Mat3.translateMatrix(
|
const transformUV = mat2d.fromScaling(
|
||||||
new Vec2(0.5, 0.5)
|
mat2d.create(),
|
||||||
).times(Mat3.scaleMatrix(new Vec2(1).divide(resolution)));
|
vec2.divide(vec2.create(), vec2.fromValues(1, 1), resolution)
|
||||||
|
);
|
||||||
|
mat2d.translate(transformUV, transformUV, vec2.fromValues(0.5, 0.5));
|
||||||
|
this.nextFrameUniforms.transformUV = transformUV;
|
||||||
|
|
||||||
this.frameBuffers[0].render(this.nextFrameUniforms);
|
this.frameBuffers[0].render(this.nextFrameUniforms);
|
||||||
this.frameBuffers[1].render(
|
this.frameBuffers[1].render(
|
||||||
|
|
@ -76,19 +87,23 @@ export class WebGl2Renderer implements Drawer {
|
||||||
this.stopwatch?.stop();
|
this.stopwatch?.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCameraPosition(position: Vec2) {
|
public setCameraPosition(position: vec2) {
|
||||||
this.viewBox.topLeft = position;
|
this.viewBox.topLeft = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setCursorPosition(position: vec2): void {
|
||||||
|
this.cursorPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
public giveUniforms(uniforms: any): void {
|
public giveUniforms(uniforms: any): void {
|
||||||
this.nextFrameUniforms = { ...this.nextFrameUniforms, ...uniforms };
|
this.nextFrameUniforms = { ...this.nextFrameUniforms, ...uniforms };
|
||||||
}
|
}
|
||||||
|
|
||||||
public setInViewArea(size: number): Vec2 {
|
public setInViewArea(size: number): vec2 {
|
||||||
const canvasAspectRatio =
|
const canvasAspectRatio =
|
||||||
this.canvas.clientWidth / this.canvas.clientHeight;
|
this.canvas.clientWidth / this.canvas.clientHeight;
|
||||||
|
|
||||||
this.viewBox.size = new Vec2(
|
this.viewBox.size = vec2.fromValues(
|
||||||
Math.sqrt(size * canvasAspectRatio),
|
Math.sqrt(size * canvasAspectRatio),
|
||||||
Math.sqrt(size / canvasAspectRatio)
|
Math.sqrt(size / canvasAspectRatio)
|
||||||
);
|
);
|
||||||
|
|
@ -101,7 +116,7 @@ export class WebGl2Renderer implements Drawer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isOnScreen(position: Vec2): boolean {
|
isOnScreen(position: vec2): boolean {
|
||||||
return this.viewBox.isInside(position);
|
return this.viewBox.isInside(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
frontend/src/scripts/helper/array.ts
Normal file
49
frontend/src/scripts/helper/array.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
declare global {
|
||||||
|
interface Array<T> {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Float32Array {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const applyArrayPlugins = () => {
|
||||||
|
Object.defineProperty(Array.prototype, 'x', {
|
||||||
|
get: function () {
|
||||||
|
return this[0];
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this[0] = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Array.prototype, 'y', {
|
||||||
|
get: function () {
|
||||||
|
return this[1];
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this[1] = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Float32Array.prototype, 'x', {
|
||||||
|
get: function () {
|
||||||
|
return this[0];
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this[0] = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(Float32Array.prototype, 'y', {
|
||||||
|
get: function () {
|
||||||
|
return this[1];
|
||||||
|
},
|
||||||
|
set: function (value) {
|
||||||
|
this[1] = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
4
frontend/src/scripts/helper/clamp.ts
Normal file
4
frontend/src/scripts/helper/clamp.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const clamp = (value: number, min: number, max: number): number =>
|
||||||
|
Math.min(max, Math.max(min, value));
|
||||||
|
|
||||||
|
export const clamp01 = (value: number): number => clamp(value, 0, 1);
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import { CommandGenerator } from '../commands/command-generator';
|
import { CommandGenerator } from '../commands/command-generator';
|
||||||
import { PrimaryActionCommand } from '../commands/types/primary-action';
|
import { PrimaryActionCommand } from '../commands/types/primary-action';
|
||||||
import { SecondaryActionCommand } from '../commands/types/secondary-action';
|
import { SecondaryActionCommand } from '../commands/types/secondary-action';
|
||||||
import { Vec2 } from '../math/vec2';
|
|
||||||
import { SwipeCommand } from '../commands/types/swipe';
|
import { SwipeCommand } from '../commands/types/swipe';
|
||||||
import { ZoomCommand } from '../commands/types/zoom';
|
import { ZoomCommand } from '../commands/types/zoom';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { clamp01 } from '../helper/clamp';
|
||||||
|
|
||||||
export class MouseListener extends CommandGenerator {
|
export class MouseListener extends CommandGenerator {
|
||||||
private previousPosition: Vec2 = null;
|
private previousPosition = vec2.create();
|
||||||
private isMouseDown = false;
|
private isMouseDown = false;
|
||||||
|
|
||||||
constructor(private target: Element) {
|
constructor(private target: Element) {
|
||||||
|
|
@ -27,7 +28,9 @@ export class MouseListener extends CommandGenerator {
|
||||||
if (this.isMouseDown) {
|
if (this.isMouseDown) {
|
||||||
const position = this.positionFromEvent(event);
|
const position = this.positionFromEvent(event);
|
||||||
this.sendCommand(
|
this.sendCommand(
|
||||||
new SwipeCommand(this.previousPosition.subtract(position))
|
new SwipeCommand(
|
||||||
|
vec2.subtract(vec2.create(), this.previousPosition, position)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
this.previousPosition = position;
|
this.previousPosition = position;
|
||||||
}
|
}
|
||||||
|
|
@ -52,12 +55,12 @@ export class MouseListener extends CommandGenerator {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private positionFromEvent(event: MouseEvent): Vec2 {
|
private positionFromEvent(event: MouseEvent): vec2 {
|
||||||
const bb = this.target.getBoundingClientRect();
|
const bb = this.target.getBoundingClientRect();
|
||||||
|
|
||||||
return new Vec2(
|
return vec2.fromValues(
|
||||||
(event.clientX - bb.x) / bb.width,
|
clamp01((event.clientX - bb.x) / bb.width),
|
||||||
1 - (event.clientY - bb.y) / bb.height
|
clamp01(1 - (event.clientY - bb.y) / bb.height)
|
||||||
).clamped_0_1;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import { CommandGenerator } from '../commands/command-generator';
|
import { CommandGenerator } from '../commands/command-generator';
|
||||||
import { PrimaryActionCommand } from '../commands/types/primary-action';
|
import { PrimaryActionCommand } from '../commands/types/primary-action';
|
||||||
import { SecondaryActionCommand } from '../commands/types/secondary-action';
|
import { SecondaryActionCommand } from '../commands/types/secondary-action';
|
||||||
import { Vec2 } from '../math/vec2';
|
|
||||||
import { SwipeCommand } from '../commands/types/swipe';
|
import { SwipeCommand } from '../commands/types/swipe';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { clamp01 } from '../helper/clamp';
|
||||||
|
|
||||||
export class TouchListener extends CommandGenerator {
|
export class TouchListener extends CommandGenerator {
|
||||||
private previousPosition: Vec2 = null;
|
private previousPosition = vec2.create();
|
||||||
|
|
||||||
constructor(private target: HTMLElement) {
|
constructor(private target: HTMLElement) {
|
||||||
super();
|
super();
|
||||||
|
|
@ -30,19 +31,21 @@ export class TouchListener extends CommandGenerator {
|
||||||
const position = this.positionFromEvent(event);
|
const position = this.positionFromEvent(event);
|
||||||
|
|
||||||
this.sendCommand(
|
this.sendCommand(
|
||||||
new SwipeCommand(position.subtract(this.previousPosition))
|
new SwipeCommand(
|
||||||
|
vec2.subtract(vec2.create(), position, this.previousPosition)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.previousPosition = position;
|
this.previousPosition = position;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private positionFromEvent(event: TouchEvent): Vec2 {
|
private positionFromEvent(event: TouchEvent): vec2 {
|
||||||
const bb = this.target.getBoundingClientRect();
|
const bb = this.target.getBoundingClientRect();
|
||||||
|
|
||||||
return new Vec2(
|
return vec2.fromValues(
|
||||||
1 - (event.touches[0].clientX - bb.x) / bb.width,
|
clamp01(1 - (event.touches[0].clientX - bb.x) / bb.width),
|
||||||
(event.touches[0].clientY - bb.y) / bb.height
|
clamp01((event.touches[0].clientY - bb.y) / bb.height)
|
||||||
).clamped_0_1;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
// https://github.com/Azleur/mat3/blob/master/src/index.ts
|
|
||||||
|
|
||||||
import { Vec2 } from './vec2';
|
|
||||||
|
|
||||||
export class Mat3 {
|
|
||||||
constructor(private readonly values: Array<Array<number>>) {}
|
|
||||||
|
|
||||||
public static get Zero() {
|
|
||||||
return new Mat3([
|
|
||||||
[0, 0, 0],
|
|
||||||
[0, 0, 0],
|
|
||||||
[0, 0, 0],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static get Id() {
|
|
||||||
return new Mat3([
|
|
||||||
[1, 0, 0],
|
|
||||||
[0, 1, 0],
|
|
||||||
[0, 0, 1],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static get Ones() {
|
|
||||||
return new Mat3([
|
|
||||||
[1, 1, 1],
|
|
||||||
[1, 1, 1],
|
|
||||||
[1, 1, 1],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static translateMatrix(by: Vec2): Mat3 {
|
|
||||||
return new Mat3([
|
|
||||||
[1, 0, 0],
|
|
||||||
[0, 1, 0],
|
|
||||||
[by.x, by.y, 1],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static scaleMatrix(by: Vec2): Mat3 {
|
|
||||||
return new Mat3([
|
|
||||||
[by.x, 0, 0],
|
|
||||||
[0, by.y, 0],
|
|
||||||
[0, 0, 1],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get transposed(): Mat3 {
|
|
||||||
const values: number[][] = [[], [], []];
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
for (let j = 0; j < 3; j++) {
|
|
||||||
values[i][j] = this.values[j][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Mat3(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public times(other: Mat3): Mat3 {
|
|
||||||
const values: number[][] = Mat3.Zero.values;
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
for (let j = 0; j < 3; j++) {
|
|
||||||
for (let k = 0; k < 3; k++) {
|
|
||||||
values[i][j] += this.values[i][k] * other.values[k][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Mat3(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get transposedFlat(): Array<number> {
|
|
||||||
const transposed = this.transposed;
|
|
||||||
return [
|
|
||||||
...transposed.values[0],
|
|
||||||
...transposed.values[1],
|
|
||||||
...transposed.values[2],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import { Typed } from '../transport/serializable';
|
import { Typed } from '../transport/serializable';
|
||||||
import { Vec2 } from './vec2';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class Rectangle extends Typed {
|
export class Rectangle extends Typed {
|
||||||
public constructor(
|
public constructor(
|
||||||
public topLeft: Vec2 = new Vec2(),
|
public topLeft: vec2 = vec2.create(),
|
||||||
public size: Vec2 = new Vec2()
|
public size: vec2 = vec2.create()
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public isInside(position: Vec2): boolean {
|
public isInside(position: vec2): boolean {
|
||||||
const translated = position.subtract(this.topLeft);
|
const translated = vec2.subtract(vec2.create(), position, this.topLeft);
|
||||||
return (
|
return (
|
||||||
0 <= translated.x &&
|
0 <= translated.x &&
|
||||||
translated.x < this.size.x &&
|
translated.x < this.size.x &&
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { Typed } from '../transport/serializable';
|
|
||||||
|
|
||||||
export class Vec2 extends Typed {
|
|
||||||
public constructor(public x: number = 0.0, public y: number = null) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
if (this.y === null) {
|
|
||||||
this.y = this.x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public scale(scalar: number): Vec2 {
|
|
||||||
return new Vec2(this.x * scalar, this.y * scalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
public add(other: Vec2): Vec2 {
|
|
||||||
return new Vec2(this.x + other.x, this.y + other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public subtract(other: Vec2): Vec2 {
|
|
||||||
return new Vec2(this.x - other.x, this.y - other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public times(other: Vec2): Vec2 {
|
|
||||||
return new Vec2(this.x * other.x, this.y * other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public divide(other: Vec2): Vec2 {
|
|
||||||
return new Vec2(this.x / other.x, this.y / other.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get length(): number {
|
|
||||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get normalized(): Vec2 {
|
|
||||||
return this.scale(1 / this.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get clamped_0_1(): Vec2 {
|
|
||||||
return new Vec2(
|
|
||||||
Math.min(1, Math.max(0, this.x)),
|
|
||||||
Math.min(1, Math.max(0, this.y))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get list(): [number, number] {
|
|
||||||
return [this.x, this.y];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
import { Typed } from '../transport/serializable';
|
import { Typed } from '../transport/serializable';
|
||||||
import { Vec2 } from '../math/vec2';
|
|
||||||
import { IdentityManager } from '../identity/identity-manager';
|
import { IdentityManager } from '../identity/identity-manager';
|
||||||
import { Command } from '../commands/command';
|
import { Command } from '../commands/command';
|
||||||
import { CommandReceiver } from '../commands/command-receiver';
|
import { CommandReceiver } from '../commands/command-receiver';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export abstract class GameObject extends Typed implements CommandReceiver {
|
export abstract class GameObject extends Typed implements CommandReceiver {
|
||||||
public readonly id = IdentityManager.generateId();
|
public readonly id = IdentityManager.generateId();
|
||||||
|
|
||||||
protected _position = new Vec2();
|
protected _position = vec2.create();
|
||||||
public get position(): Vec2 {
|
public get position(): vec2 {
|
||||||
return this._position;
|
return this._position;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _boundingBoxSize = new Vec2();
|
protected _boundingBoxSize = vec2.create();
|
||||||
public get boundingBoxSize(): Vec2 {
|
public get boundingBoxSize(): vec2 {
|
||||||
return this._boundingBoxSize;
|
return this._boundingBoxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ import { GameObject } from '../game-object';
|
||||||
import { MoveToCommand } from '../../commands/types/move-to';
|
import { MoveToCommand } from '../../commands/types/move-to';
|
||||||
import { ZoomCommand } from '../../commands/types/zoom';
|
import { ZoomCommand } from '../../commands/types/zoom';
|
||||||
import { BeforeDrawCommand } from '../../commands/types/before-draw';
|
import { BeforeDrawCommand } from '../../commands/types/before-draw';
|
||||||
|
import { PrimaryActionCommand } from '../../commands/types/primary-action';
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
|
||||||
export class Camera extends GameObject {
|
export class Camera extends GameObject {
|
||||||
private inViewArea = 1920 * 1080;
|
private inViewArea = 1920 * 1080;
|
||||||
|
private cursorPosition = vec2.create();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
@ -12,10 +15,15 @@ export class Camera extends GameObject {
|
||||||
this.addCommandExecutor(BeforeDrawCommand, this.draw.bind(this));
|
this.addCommandExecutor(BeforeDrawCommand, this.draw.bind(this));
|
||||||
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
|
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
|
||||||
this.addCommandExecutor(ZoomCommand, this.zoom.bind(this));
|
this.addCommandExecutor(ZoomCommand, this.zoom.bind(this));
|
||||||
|
this.addCommandExecutor(
|
||||||
|
PrimaryActionCommand,
|
||||||
|
this.setCursorPosition.bind(this)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private draw(c: BeforeDrawCommand) {
|
private draw(c: BeforeDrawCommand) {
|
||||||
c.drawer.setCameraPosition(this.position);
|
c.drawer.setCameraPosition(this.position);
|
||||||
|
c.drawer.setCursorPosition(this.cursorPosition);
|
||||||
this._boundingBoxSize = c.drawer.setInViewArea(this.inViewArea);
|
this._boundingBoxSize = c.drawer.setInViewArea(this.inViewArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,4 +34,8 @@ export class Camera extends GameObject {
|
||||||
private zoom(c: ZoomCommand) {
|
private zoom(c: ZoomCommand) {
|
||||||
this.inViewArea *= c.factor;
|
this.inViewArea *= c.factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setCursorPosition(c: PrimaryActionCommand) {
|
||||||
|
this.cursorPosition = c.position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue