decla-red/frontend/src/scripts/game.ts
2020-07-26 19:11:03 +02:00

101 lines
3.3 KiB
TypeScript

import caveFragmentShader from '../shaders/cave-distance-fs.glsl';
import lightsShader from '../shaders/lights-shading-fs.glsl';
import caveVertexShader from '../shaders/passthrough-distance-vs.glsl';
import lightsVertexShader from '../shaders/passthrough-shading-vs.glsl';
// import lightsShader from '../shaders/rainbow-shading-fs.glsl';
import { CommandBroadcaster } from './commands/command-broadcaster';
import { BeforeDrawCommand } from './commands/types/before-draw';
import { DrawCommand } from './commands/types/draw';
import { StepCommand } from './commands/types/step';
import { WebGl2Renderer } from './drawing/webgl2-renderer';
import { timeIt } from './helper/timing';
import { KeyboardListener } from './input/keyboard-listener';
import { MouseListener } from './input/mouse-listener';
import { TouchListener } from './input/touch-listener';
import { ObjectContainer } from './objects/object-container';
import { InfoText } from './objects/types/info-text';
import { createCharacter } from './objects/world/create-character';
import { createDungeon } from './objects/world/create-dungeon';
export class Game {
private previousTime?: DOMHighResTimeStamp = null;
private objects: ObjectContainer = new ObjectContainer();
private renderer: WebGl2Renderer;
private previousFpsValues: Array<number> = [];
constructor() {
const canvas: HTMLCanvasElement = document.querySelector('canvas#main');
const overlay: HTMLElement = document.querySelector('#overlay');
document.addEventListener(
'visibilitychange',
this.handleVisibilityChange.bind(this)
);
new CommandBroadcaster(
[
new KeyboardListener(document.body),
new MouseListener(canvas),
new TouchListener(canvas),
],
[this.objects]
);
this.renderer = new WebGl2Renderer(canvas, overlay, [
[caveVertexShader, caveFragmentShader],
[lightsVertexShader, lightsShader],
]);
this.initializeScene();
requestAnimationFrame(this.gameLoop.bind(this));
}
private initializeScene() {
this.objects.addObject(new InfoText());
createCharacter(this.objects);
createDungeon(this.objects);
createDungeon(this.objects);
}
private handleVisibilityChange() {
if (!document.hidden) {
this.previousTime = null;
}
}
@timeIt()
private gameLoop(time: DOMHighResTimeStamp) {
if (this.previousTime === null) {
this.previousTime = time;
}
const deltaTime = time - this.previousTime;
this.previousTime = time;
this.calculateFps(deltaTime);
this.objects.sendCommand(new StepCommand(deltaTime));
this.renderer.startFrame(deltaTime);
this.objects.sendCommand(new BeforeDrawCommand(this.renderer));
this.objects.sendCommand(new DrawCommand(this.renderer));
this.renderer.finishFrame();
window.requestAnimationFrame(this.gameLoop.bind(this));
}
private calculateFps(deltaTime: number) {
this.previousFpsValues.push(1000 / deltaTime);
if (this.previousFpsValues.length > 30) {
this.previousFpsValues.sort();
const text = `Min: ${this.previousFpsValues[0].toFixed(
2
)}\n\tMedian: ${this.previousFpsValues[
Math.floor(this.previousFpsValues.length / 2)
].toFixed(2)}`;
InfoText.modifyRecord('FPS', text);
this.previousFpsValues = [];
}
}
}