summaryrefslogtreecommitdiffstats
path: root/src/renderer/runtime/view/entity.ts
blob: 12dd38fff97ed06c1f649ee571f809572feacedc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { EntityData, EntityDataInput } from '../model/data/entity';
import { Renderer } from './renderer/renderer';
import { SpriteCoords, SpriteView, SpriteViewBuilder } from './sprite';
import { loadImage, mkTexture } from './util/image';

import { getJSON } from '../util';

import { vec2 } from 'gl-matrix';

export class EntityView {
	public static async load(r: Renderer, name: string): Promise<EntityView> {
		const data = new EntityData((await getJSON(`resources/entity/${name}.json`)) as EntityDataInput);
		const tile = await loadImage(`resources/sprite/entity/${data.sprite}.png`);

		const [texture, size] = mkTexture(r, tile);
		const frameSize: [number, number] = [size[0], size[1] / data.frames];

		const offset = vec2.mul(vec2.create(), frameSize, data.anchor);
		r.snapToGrid(offset, offset);

		const coords: SpriteCoords = [
			-offset[0],
			-offset[1],
			-offset[0] + frameSize[0],
			-offset[1] + frameSize[1],
		];

		const sprites: SpriteView[] = [];

		for (let frame = 0; frame < data.frames; frame++) {
			const builder = new SpriteViewBuilder(r, texture);
			builder.addSprite(coords, [0, frame / data.frames, 1, (frame + 1) / data.frames]);
			sprites.push(builder.build());
		}

		return new EntityView(data, sprites);
	}

	private readonly totalTime: number;

	private constructor(public readonly data: EntityData, public readonly sprites: SpriteView[]) {
		if (data.animation) this.totalTime = data.animation.sequence.reduce((a, s) => a + s[0], 0);
		else this.totalTime = 0;
	}

	public getSpriteByTime(time: number): SpriteView {
		time %= this.totalTime;

		if (this.data.animation) {
			for (const [len, sprite] of this.data.animation.sequence) {
				time -= len;
				if (time < 0) return this.sprites[sprite];
			}
		}

		return this.sprites[0];
	}

	public renderByTime(time: number): void {
		this.getSpriteByTime(time).render();
	}
}