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
99
|
import { Game } from ".";
import { Miscellaneous, loadAssets } from "./config";
import { LevelNames } from "./levels";
import {
Grid,
FacingDirection,
Input,
Render,
Collision,
GridSpawner,
Life,
Music,
Level,
Modal,
} from "./systems";
export class TheAbstractionEngine {
private game: Game;
private ctx: CanvasRenderingContext2D;
private animationFrameId: number | null;
constructor(game: Game, ctx: CanvasRenderingContext2D) {
this.game = game;
this.ctx = ctx;
this.animationFrameId = null;
}
public async init() {
await loadAssets();
const inputSystem = new Input();
this.addWindowEventListenersToInputSystem(inputSystem);
const facingDirectionSystem = new FacingDirection(inputSystem);
[
new Modal(),
new Level(LevelNames.CarCadr),
inputSystem,
facingDirectionSystem,
new Grid(
{ width: Miscellaneous.GRID_COLUMNS, height: Miscellaneous.GRID_ROWS },
{
width: Miscellaneous.GRID_CELL_WIDTH,
height: Miscellaneous.GRID_CELL_HEIGHT,
},
),
new GridSpawner(),
new Collision(),
new Life(),
new Music(),
new Render(this.ctx),
].forEach((system) => this.game.addSystem(system));
}
public play() {
this.game.start();
const loop = (timestamp: number) => {
this.game.doGameLoop(timestamp);
this.animationFrameId = requestAnimationFrame(loop); // tail call recursion! /s
};
this.animationFrameId = requestAnimationFrame(loop);
}
public stop() {
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
}
private addWindowEventListenersToInputSystem(input: Input) {
this.ctx.canvas.addEventListener("keydown", (e) => {
if (!e.repeat) {
input.keyPressed(e.key.toLowerCase());
}
});
this.ctx.canvas.addEventListener("keyup", (e) =>
input.keyReleased(e.key.toLowerCase()),
);
this.ctx.canvas.addEventListener("blur", () => input.clearKeys());
this.ctx.canvas.addEventListener("mousemove", (e) => {
const canvas = this.ctx.canvas;
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;
const x = (e.clientX - rect.left) * scaleX;
const y = (e.clientY - rect.top) * scaleY;
input.setMousePosition({ x, y });
});
}
}
|