UNPKG

playable.js

Version:

A lightweight HTML5 game engine.

156 lines (138 loc) 3.71 kB
import {Vector} from './Vector'; /** * ``` * {a b 0} * (x, y, 1) * {c d 0} = (ax + cy + tx, bx + dy + ty, 1) * {tx ty 1} * ``` */ export class Matrix { public a: number; public b: number; public c: number; public d: number; public tx: number; public ty: number; protected constructor(a?: number, b?: number, c?: number, d?: number, tx?: number, ty?: number) { if (arguments.length > 0) { this.set(a, b, c, d, tx, ty); } else { this.identity(); } } public set(a: number, b: number, c: number, d: number, tx: number, ty: number): this { this.a = a; this.b = b; this.c = c; this.d = d; this.tx = tx; this.ty = ty; return this; } public identity(): this { return this.set(1, 0, 0, 1, 0, 0); } public invert(): this { let a = this.a; let b = this.b; let c = this.c; let d = this.d; let tx = this.tx; let ty = this.ty; let n = a * d - c * b; this.a = d / n; this.b = -b / n; this.c = -c / n; this.d = a / n; this.tx = (c * ty - d * tx) / n; this.ty = (b * tx - a * ty) / n; return this; } public prepend(m: Matrix): this; public prepend(a: number, b: number, c: number, d: number, tx: number, ty: number): this; public prepend(a: number | Matrix, b?: number, c?: number, d?: number, tx?: number, ty?: number): this { if (a instanceof Matrix) { return this.prepend(a.a, a.b, a.c, a.d, a.tx, a.ty); } let a1 = this.a; let b1 = this.b; let c1 = this.c; let d1 = this.d; let tx1 = this.tx; let ty1 = this.ty; this.a = a * a1 + b * c1; this.b = a * b1 + b * d1; this.c = c * a1 + d * c1; this.d = c * b1 + d * d1; this.tx = tx * a1 + ty * c1 + tx1; this.ty = tx * b1 + ty * d1 + ty1; return this; } public append(m: Matrix): this; public append(a: number, b: number, c: number, d: number, tx: number, ty: number): this; public append(a: number | Matrix, b?: number, c?: number, d?: number, tx?: number, ty?: number): this { if (a instanceof Matrix) { return this.append(a.a, a.b, a.c, a.d, a.tx, a.ty); } let a1 = this.a; let b1 = this.b; let c1 = this.c; let d1 = this.d; let tx1 = this.tx; let ty1 = this.ty; this.a = a * a1 + c * b1; this.b = b * a1 + d * b1; this.c = a * c1 + c * d1; this.d = b * c1 + d * d1; this.tx = a * tx1 + c * ty1 + tx; this.ty = b * tx1 + d * ty1 + ty; return this; } public scale(x: number, y?: number): this { return this.append(x, 0, 0, y === undefined ? x : y, 0, 0); } public rotate(angle: number): this { let sin = Math.sin(angle); let cos = Math.cos(angle); return this.append(cos, sin, -sin, cos, 0, 0); } public skew(skewX: number, skewY: number): this { return this.append(1, Math.tan(skewY), Math.tan(skewX), 1, 0, 0); } public translate(v: Vector): this; public translate(x: number, y: number): this; public translate(x: number | Vector, y?: number): this { if (x instanceof Vector) { return this.append(1, 0, 0, 1, x.x, x.y); } return this.append(1, 0, 0, 1, x, y); } public equal(m: Matrix): boolean { return m instanceof Matrix && this.a === m.a && this.b === m.b && this.c === m.c && this.d === m.d && this.tx === m.tx && this.ty === m.ty; } public release(): void { Matrix.recycle(this); } protected static readonly $pool: Array<Matrix> = []; public static create(a?: number, b?: number, c?: number, d?: number, tx?: number, ty?: number): Matrix { let m; let pool = this.$pool; if (pool.length > 0) { m = pool.pop(); } else { m = new Matrix(); } if (arguments.length) { m.set(a, b, c, d, tx, ty); } else { m.identity(); } return m; } public static recycle(m: Matrix) { this.$pool.push(m); } }