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();
}
}
|