import { EntityAnimation, EntityData } from '../model/data/entity'; import { loadEntity } from '../view/entity'; import { Renderer } from '../view/renderer/renderer'; import { SpriteView } from '../view/sprite'; import { Collidable } from '../math/collision'; import { getJSON } from '../util'; import { CollidableGroup, mkCollision } from './collision'; import { vec2 } from 'gl-matrix'; export class EntityContext implements CollidableGroup { public static async load(renderer: Renderer, name: string): Promise { const entity = new EntityData(await getJSON(`resources/entity/${name}.json`)); return new EntityContext( renderer, name, await loadEntity(renderer, entity), mkCollision(entity.collision), entity.animation, ); } public readonly pos: vec2 = vec2.create(); private readonly totalTime: number; private constructor( private readonly renderer: Renderer, private readonly name: string, private readonly sprites: SpriteView[], private readonly collision: Collidable[], private readonly animation?: EntityAnimation, ) { if (animation) this.totalTime = animation.sequence.reduce((a, s) => a + s[0], 0); else this.totalTime = 0; } public render(time: number) { this.renderer.setTranslation(this.pos); this.getSprite(time).render(); } public getTranslation(): vec2 { return this.pos; } public getCollidables(): Collidable[] { return this.collision; } public interact() { alert(`You've interacted with ${this.name}!`); } private getSprite(time: number): SpriteView { time %= this.totalTime; if (this.animation) { for (const [len, sprite] of this.animation.sequence) { time -= len; if (time < 0) return this.sprites[sprite]; } } return this.sprites[0]; } }