summaryrefslogtreecommitdiffstats
path: root/src/controller/gamecontext.ts
blob: 76ca7ccd0248c51f2e83b8eb40d41f1cc419925b (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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import MapData from '../model/data/MapData';

import { loadSimpleEntity } from '../view/entity';
import DirectionHandler from '../view/input/DirectionHandler';
import { loadMap } from '../view/map';
import Renderer from '../view/renderer/Renderer';
import { SpriteView } from '../view/sprite';

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

import { vec2 } from 'gl-matrix';

function snapToGrid(out: vec2, a: vec2): void {
	const res = 64;

	vec2.scale(out, a, res);
	vec2.round(out, out);
	vec2.scale(out, out, 1 / res);
}

export class GameContext {
	public static async load(renderer: Renderer): Promise<GameContext> {
		const [
			mapView,
			entity,
		] = await Promise.all([
			GameContext.loadMap(renderer),
			loadSimpleEntity(renderer, 'simple_square'),
		]);

		return new GameContext(
			renderer,
			mapView,
			entity,
		);
	}

	private static async loadMap(renderer: Renderer): Promise<SpriteView> {
		const map = new MapData(await getJSON('resources/map/test.json'));
		return loadMap(renderer, map);
	}

	private time: number|null = null;

	private readonly speed = 1 / 100;

	private readonly input: DirectionHandler;

	private readonly entityPos: vec2 = vec2.create();
	private readonly entityMovement: vec2 = vec2.create();

	private constructor(
		private readonly renderer: Renderer,
		private readonly mapView: SpriteView,
		private readonly entity: SpriteView,
	) {
		this.input = new DirectionHandler();
		this.input.addListener((v) => {
			if (vec2.sqrLen(v) > 0)
				vec2.normalize(this.entityMovement, v);
			else
				vec2.copy(this.entityMovement, [0, 0]);
		});

		window.requestAnimationFrame(this.render);
	}

	private updateTime(time: number): number {
		let diff = 0;
		if (this.time !== null)
			diff = time - this.time;

		this.time = time;

		return diff;
	}

	private update(time: number): void {
		const diff = this.updateTime(time);

		vec2.scaleAndAdd(this.entityPos, this.entityPos, this.entityMovement, diff * this.speed);
		snapToGrid(this.entityPos, this.entityPos);
	}

	private render = (time: number) => {
		this.update(time);

		this.renderer.setCenter(this.entityPos);
		this.renderer.clear();

		this.mapView.render();

		this.renderer.setTranslation(this.entityPos);
		this.entity.render();

		window.requestAnimationFrame(this.render);
	}
}