namespace TSE { export class Sprite { protected _buffer: GLBuffer; protected _width: number; protected _height: number; protected _name: string; protected _material: Material; protected _vertices: Vertex[] = []; public constructor(name: string, materialName: string, width: number = 100, height: number = 100) { this._name = name; this._width = width; this._height = height; this._material = MaterialManager.getMaterial(materialName); } public load(): void { this._buffer = new GLBuffer(); this._buffer.addAttributeLocation(new AttributeInfo(0, 3)); //Position this._buffer.addAttributeLocation(new AttributeInfo(1, 2)); //UVs this._vertices = [ new Vertex(0, 0, 0, 0, 0), new Vertex(0, this._height, 0, 0, 1.0), new Vertex(this._width, this._height, 0, 1.0, 1.0), new Vertex(this._width, this._height, 0, 1.0, 1.0), new Vertex(this._width, 0, 0, 1.0, 0), new Vertex(0, 0, 0, 0, 0) ]; this._buffer.pushBackData(Vertex.vertexArray(this._vertices)); this._buffer.upload(); this._buffer.unbind(); } public destroy(): void { this._buffer.destroy(); MaterialManager.releaseMaterial(this._material.name); delete this._material; } public update(time: number): void { } public draw(shader: Shader, model: Matrix4x4): void { let modelLocation = shader.getUniformLocation("u_model"); gl.uniformMatrix4fv(modelLocation, false, model.toFloat32Array()); let colorLocation = shader.getUniformLocation("u_tint"); gl.uniform4fv(colorLocation, this._material.tint.toFloat32Array()); if (this._material.diffuseTexture !== undefined) { this._material.diffuseTexture.activateAndBind(0); let diffuseLocation = shader.getUniformLocation("u_diffuse"); gl.uniform1i(diffuseLocation, 0); } this._buffer.bind(); this._buffer.draw(); } public get name(): string { return this._name; } } export class AnimatedSprite extends Sprite { private _frameHeight: number; private _frameWidth: number; private _frameCount: number; private _frameSequence: number[]; private _currentFrame: number = 0; private currentTime: number = 0; private _frameTime: number = 300; private _frameUVs: Vector2[][]; private _loaded: boolean = false; public constructor(name: string, materialName: string, frameWidth: number = 10, frameHeight: number = 10, frameCount: number = 1, frameSequence: number[] = []) { super(name, materialName, frameWidth, frameHeight); this._frameWidth = frameWidth; this._frameHeight = frameHeight; this._frameCount = frameCount; this._frameSequence = frameSequence; } public load() { super.load(); this.calculateUVs(); } private calculateUVs(): void { setTimeout(() => { this._frameUVs = []; let totalWidth: number = 0; let totalHeight: number = 0; for (let i = 0; i < this._frameCount; i++) { totalWidth += this._frameWidth; if (totalWidth > this._material.diffuseTexture.width) { totalWidth = 0; totalHeight++; } const u = (i * this._frameWidth) / this._material.diffuseTexture.width; const v = (totalHeight * this._frameHeight) / this._material.diffuseTexture.height; const um = ((i * this._frameWidth) + this._frameWidth) / this._material.diffuseTexture.width; const vm = ((totalHeight * this._frameHeight) + this._frameHeight) / this._material.diffuseTexture.height; this._frameUVs.push([new Vector2(u, v), new Vector2(um, vm)]); } this._loaded = true; }, 0); } public update(time: number) { if (!this._loaded) return; this.currentTime += time; if (this.currentTime > this._frameTime) { this._currentFrame++; this.currentTime = 0; if (this._currentFrame >= this._frameSequence.length) this._currentFrame = 0; const frameUVs = this._frameUVs[this._frameSequence[this._currentFrame]]; this._vertices[0].texCoords.copyFrom(frameUVs[0]); this._vertices[1].texCoords = new Vector2(frameUVs[0].x, frameUVs[1].y); this._vertices[2].texCoords.copyFrom(frameUVs[1]); this._vertices[3].texCoords.copyFrom(frameUVs[1]); this._vertices[4].texCoords = new Vector2(frameUVs[1].x, frameUVs[0].y); this._vertices[5].texCoords.copyFrom(frameUVs[0]); this._buffer.setData(Vertex.vertexArray(this._vertices)); this._buffer.upload(); this._buffer.unbind(); } super.update(time); } } }