Add server screen

This commit is contained in:
schmelczerandras 2020-10-16 23:26:03 +02:00
parent 89fafeafd3
commit e2129bbb26
20 changed files with 672 additions and 174 deletions

View file

@ -23,8 +23,8 @@ import { MouseListener } from './commands/generators/mouse-listener';
import { TouchListener } from './commands/generators/touch-listener';
import { CommandReceiverSocket } from './commands/receivers/command-receiver-socket';
import { Configuration } from './config/configuration';
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
import { PlayerDecision } from './join-form-handler';
import { GameObjectContainer } from './objects/game-object-container';
import { BlobShape } from './shapes/blob-shape';
import { Circle } from './shapes/circle';
@ -32,18 +32,23 @@ import { Polygon } from './shapes/polygon';
export class Game {
public readonly gameObjects = new GameObjectContainer(this);
private readonly canvas: HTMLCanvasElement = document.querySelector(
'canvas#main',
) as HTMLCanvasElement;
private readonly canvas = document.querySelector('canvas') as HTMLCanvasElement;
private renderer!: Renderer;
private socket!: SocketIOClient.Socket;
private promises: Promise<[void, void]>;
private deltaTimeCalculator = new DeltaTimeCalculator();
private overlay: HTMLElement = document.querySelector('#overlay') as HTMLDivElement;
private async setupCommunication(): Promise<void> {
await Configuration.initialize();
constructor(playerDecision: PlayerDecision) {
console.log(playerDecision.server);
this.promises = Promise.all([
this.setupCommunication(playerDecision.server),
this.setupRenderer(),
]);
}
this.socket = io(Configuration.servers[1], {
private async setupCommunication(serverUrl: string): Promise<void> {
this.socket = io(serverUrl, {
reconnectionDelayMax: 10000,
transports: ['websocket'],
});
@ -81,7 +86,7 @@ export class Game {
[
{
...Polygon.descriptor,
shaderCombinationSteps: [0, 2, 6, 16],
shaderCombinationSteps: [0, 1, 2, 3],
},
{
...BlobShape.descriptor,
@ -93,11 +98,11 @@ export class Game {
},
{
...CircleLight.descriptor,
shaderCombinationSteps: [0, 1, 2, 4, 8],
shaderCombinationSteps: [0, 1, 2, 4, 8, 16],
},
{
...Flashlight.descriptor,
shaderCombinationSteps: [0, 1],
shaderCombinationSteps: [0],
},
],
{
@ -131,7 +136,7 @@ export class Game {
}
public async start(): Promise<void> {
await Promise.all([this.setupCommunication(), this.setupRenderer()]);
await this.promises;
requestAnimationFrame(this.gameLoop.bind(this));
}

View file

@ -0,0 +1,72 @@
import { ServerInformation, serverInformationEndpoint } from 'shared';
import { Configuration } from './config/configuration';
export type PlayerDecision = {
playerName: string;
server: string;
};
export class JoinFormHandler {
private waitingForDecision: Promise<PlayerDecision>;
private resolvePlayerDecision!: (d: PlayerDecision) => void;
constructor(form: HTMLFormElement, private readonly container: HTMLElement) {
this.waitingForDecision = new Promise((r) => (this.resolvePlayerDecision = r));
new FormData(form);
document.addEventListener('keyup', (e) => {
if (e.key === 'enter') {
form.submit();
}
});
form.onsubmit = (e) => {
const result: PlayerDecision = (Array.from(
(new FormData(form) as any).entries(),
) as Array<[string, any]>).reduce((result, [name, value]) => {
(result as any)[name] = value;
return result;
}, {}) as any;
this.resolvePlayerDecision(result);
e.preventDefault();
};
this.loadServers();
}
private async loadServers() {
await Configuration.initialize();
const serverList = Configuration.servers;
serverList.map(async (url) => {
const response = await fetch(url + serverInformationEndpoint);
if (response.ok) {
const content: ServerInformation = await response.json();
this.displayNewServerInfo(content, url);
}
});
}
public async getPlayerDecision(): Promise<PlayerDecision> {
return this.waitingForDecision;
}
private isFirstServer = true;
private displayNewServerInfo(content: ServerInformation, url: string) {
this.container.innerHTML += `
<div>
<input required ${
this.isFirstServer ? 'checked' : ''
} type="radio" id="${url}" name="server" value="${url}" />
<label for="${url}">${content.serverName} - ${content.playerCount}/${
content.playerLimit
} players</label>
</div>
`;
this.isFirstServer = false;
}
}

View file

@ -0,0 +1,165 @@
import { vec2 } from 'gl-matrix';
import {
CircleLight,
compile,
FilteringOptions,
hsl,
NoisyPolygonFactory,
Renderer,
renderNoise,
WrapOptions,
} from 'sdf-2d';
import { settings, rgb, PlanetBase, Random } from 'shared';
const landingPageVertexCount = 9;
const LangindPagePolygon = NoisyPolygonFactory(
landingPageVertexCount,
rgb(0.5, 0.4, 0.7),
);
export class LandingPageBackground {
private readonly canvas = document.querySelector('canvas') as HTMLCanvasElement;
private renderer!: Renderer;
constructor() {
this.start();
}
private async start(): Promise<void> {
const noiseTexture = await renderNoise([256, 256], 1.2, 2);
this.renderer = await compile(
this.canvas,
[
{
...LangindPagePolygon.descriptor,
shaderCombinationSteps: [0, 1, 2],
},
{
...CircleLight.descriptor,
shaderCombinationSteps: [0, 2],
},
],
{
shadowTraceCount: 16,
paletteSize: 1,
},
);
this.renderer.setRuntimeSettings({
ambientLight: rgb(0, 0, 0),
lightCutoffDistance: settings.lightCutoffDistance,
textures: {
noiseTexture: {
source: noiseTexture,
overrides: {
maxFilter: FilteringOptions.LINEAR,
wrapS: WrapOptions.MIRRORED_REPEAT,
wrapT: WrapOptions.MIRRORED_REPEAT,
},
},
},
});
requestAnimationFrame(this.gameLoop.bind(this));
}
public destroy() {
this.renderer.destroy();
}
private gameLoop(time: DOMHighResTimeStamp) {
Random.seed = 42;
this.renderer.setViewArea(
vec2.fromValues(0, this.renderer.canvasSize.y),
this.renderer.canvasSize,
);
const topPlanetPosition = vec2.fromValues(
0.7 * this.renderer.canvasSize.x,
0.7 * this.renderer.canvasSize.y,
);
const topPlanet = new LangindPagePolygon(
PlanetBase.createPlanetVertices(
topPlanetPosition,
Random.getRandomInRange(150, 400),
Random.getRandomInRange(150, 400),
Random.getRandomInRange(10, 20),
landingPageVertexCount,
),
);
(topPlanet as any).randomOffset = 0.5 + time / 3500;
const bottomPlanetPosition = vec2.fromValues(
0.3 * this.renderer.canvasSize.x,
0.3 * this.renderer.canvasSize.y,
);
const bottomPlanet = new LangindPagePolygon(
PlanetBase.createPlanetVertices(
bottomPlanetPosition,
Random.getRandomInRange(150, 800),
Random.getRandomInRange(150, 400),
Random.getRandomInRange(10, 40),
landingPageVertexCount,
),
);
(bottomPlanet as any).randomOffset = time / 2500;
const planetDistance = vec2.subtract(
vec2.create(),
topPlanetPosition,
bottomPlanetPosition,
);
const planetDistanceLength = vec2.length(planetDistance);
const planetDirection = vec2.normalize(planetDistance, planetDistance);
const planetAngle = Math.atan2(planetDirection.y, planetDirection.x);
this.renderer.addDrawable(topPlanet);
this.renderer.addDrawable(bottomPlanet);
this.renderer.addDrawable(
new CircleLight(
this.calculateLightPosition(
planetAngle,
planetDistanceLength * 1.2,
-time / 3000,
),
hsl(25, 75, 60),
0.75,
),
);
this.renderer.addDrawable(
new CircleLight(
this.calculateLightPosition(
planetAngle,
planetDistanceLength * 1.2,
time / 2000 + Math.PI,
),
hsl(249, 79, 70),
0.25,
),
);
this.renderer.renderDrawables();
requestAnimationFrame(this.gameLoop.bind(this));
}
private calculateLightPosition(angle: number, length: number, t: number): vec2 {
const lightPosition = vec2.fromValues(
length * Math.sin(t),
length * Math.sin(t) * Math.cos(t),
);
const canvasCenter = vec2.scale(vec2.create(), this.renderer.canvasSize, 0.5);
vec2.add(lightPosition, lightPosition, canvasCenter);
vec2.rotate(lightPosition, lightPosition, canvasCenter, angle);
return lightPosition;
}
}