Fix issues
This commit is contained in:
parent
57d7009342
commit
42e4de28b5
15 changed files with 175 additions and 145 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -2,6 +2,7 @@
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Deserializable",
|
"Deserializable",
|
||||||
"Deserialization",
|
"Deserialization",
|
||||||
|
"Respawn",
|
||||||
"decla",
|
"decla",
|
||||||
"overridable",
|
"overridable",
|
||||||
"serializable"
|
"serializable"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "declared-server",
|
"name": "declared-server",
|
||||||
"version": "0.0.12",
|
"version": "0.0.13",
|
||||||
"description": "Game server for decla.red",
|
"description": "Game server for decla.red",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "András Schmelczer <andras@schmelczer.dev> (https://schmelczer.dev/)",
|
"author": "András Schmelczer <andras@schmelczer.dev> (https://schmelczer.dev/)",
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ export const defaultOptions: Options = {
|
||||||
port: 3000,
|
port: 3000,
|
||||||
name: 'Test server',
|
name: 'Test server',
|
||||||
playerLimit: 16,
|
playerLimit: 16,
|
||||||
npcCount: 16,
|
npcCount: 12,
|
||||||
seed: Math.random(),
|
seed: Math.random(),
|
||||||
scoreLimit: 500,
|
scoreLimit: 1000,
|
||||||
worldSize: 8000,
|
worldSize: 8000,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,12 @@ export class GameServer {
|
||||||
|
|
||||||
private endGame(winningTeam: CharacterTeam) {
|
private endGame(winningTeam: CharacterTeam) {
|
||||||
this.isInEndGame = true;
|
this.isInEndGame = true;
|
||||||
const endTitleLength = 6000;
|
const endTitleLength = 6;
|
||||||
|
this.players.endGame(winningTeam);
|
||||||
this.players.queueCommandForEachClient(
|
this.players.queueCommandForEachClient(
|
||||||
new GameEndCommand(winningTeam, endTitleLength / 1000, true),
|
new GameEndCommand(winningTeam, endTitleLength, true),
|
||||||
);
|
);
|
||||||
setTimeout(() => this.destroy(), endTitleLength * 1.1);
|
setTimeout(() => this.destroy(), endTitleLength * 1000 * 1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private destroy() {
|
private destroy() {
|
||||||
|
|
@ -147,15 +148,17 @@ export class GameServer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scaledDelta = delta;
|
||||||
if (this.isInEndGame) {
|
if (this.isInEndGame) {
|
||||||
this.timeScaling *= Math.pow(settings.endGameDeltaScaling, delta);
|
this.timeScaling *= Math.pow(settings.endGameDeltaScaling, delta);
|
||||||
delta /= this.timeScaling;
|
scaledDelta /= this.timeScaling;
|
||||||
} else {
|
} else {
|
||||||
this.updatePoints();
|
this.updatePoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.objects.stepObjects(delta);
|
this.objects.stepObjects(scaledDelta);
|
||||||
this.players.step(delta);
|
this.players.step(scaledDelta);
|
||||||
|
this.players.stepCommunication(delta);
|
||||||
this.objects.resetRemoteCalls();
|
this.objects.resetRemoteCalls();
|
||||||
|
|
||||||
this.deltaTimes.push(this.deltaTimeCalculator.getNextDeltaTimeInSeconds());
|
this.deltaTimes.push(this.deltaTimeCalculator.getNextDeltaTimeInSeconds());
|
||||||
|
|
@ -165,7 +168,7 @@ export class GameServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleStats() {
|
private handleStats() {
|
||||||
const framesBetweenDeltaTimeCalculation = 1000;
|
const framesBetweenDeltaTimeCalculation = 10000;
|
||||||
|
|
||||||
if (this.deltaTimes.length > framesBetweenDeltaTimeCalculation) {
|
if (this.deltaTimes.length > framesBetweenDeltaTimeCalculation) {
|
||||||
this.deltaTimes.sort((a, b) => a - b);
|
this.deltaTimes.sort((a, b) => a - b);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import {
|
||||||
settings,
|
settings,
|
||||||
PlanetBase,
|
PlanetBase,
|
||||||
CharacterTeam,
|
CharacterTeam,
|
||||||
|
PropertyUpdatesForObject,
|
||||||
|
UpdateProperty,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
|
|
||||||
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
||||||
|
|
@ -102,12 +104,16 @@ export class PlanetPhysical
|
||||||
|
|
||||||
public step(deltaTime: number): void {
|
public step(deltaTime: number): void {
|
||||||
this.timeSinceLastPointGeneration += deltaTime;
|
this.timeSinceLastPointGeneration += deltaTime;
|
||||||
|
|
||||||
// In reverse order, so that teams can achieve a 100% control.
|
// In reverse order, so that teams can achieve a 100% control.
|
||||||
this.remoteCall('setOwnership', this.ownership);
|
|
||||||
this.takeControl(CharacterTeam.neutral, deltaTime);
|
this.takeControl(CharacterTeam.neutral, deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPropertyUpdates(): PropertyUpdatesForObject {
|
||||||
|
return new PropertyUpdatesForObject(this.id, [
|
||||||
|
new UpdateProperty('ownership', this.ownership, 0),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public takeControl(team: CharacterTeam, deltaTime: number) {
|
public takeControl(team: CharacterTeam, deltaTime: number) {
|
||||||
if (team === CharacterTeam.decla) {
|
if (team === CharacterTeam.decla) {
|
||||||
this.ownership -= (0.5 / settings.takeControlTimeInSeconds) * deltaTime;
|
this.ownership -= (0.5 / settings.takeControlTimeInSeconds) * deltaTime;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export class PlayerContainer {
|
||||||
this.npcMaxCount - this._npcs.length,
|
this.npcMaxCount - this._npcs.length,
|
||||||
);
|
);
|
||||||
for (let i = 0; i < newNpcCount; i++) {
|
for (let i = 0; i < newNpcCount; i++) {
|
||||||
const name = `BOT ${Random.choose(settings.npcNames)}`;
|
const name = `🤖 ${Random.choose(settings.npcNames)}`;
|
||||||
this._npcs.push(
|
this._npcs.push(
|
||||||
new NPC({ name }, this, this.objects, this.getTeamOfNextPlayer(true)),
|
new NPC({ name }, this, this.objects, this.getTeamOfNextPlayer(true)),
|
||||||
);
|
);
|
||||||
|
|
@ -60,6 +60,14 @@ export class PlayerContainer {
|
||||||
this.players.forEach((p) => p.step(deltaTimeInSeconds));
|
this.players.forEach((p) => p.step(deltaTimeInSeconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public stepCommunication(deltaTimeInSeconds: number) {
|
||||||
|
this._players.forEach((p) => p.stepCommunications(deltaTimeInSeconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public endGame(winner: CharacterTeam) {
|
||||||
|
this._players.forEach((p) => p.onGameEnded(winner));
|
||||||
|
}
|
||||||
|
|
||||||
public queueCommandForEachClient(command: Command) {
|
public queueCommandForEachClient(command: Command) {
|
||||||
this._players.forEach((p) => p.queueCommandSend(command));
|
this._players.forEach((p) => p.queueCommandSend(command));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ import { PlayerBase } from './player-base';
|
||||||
export class Player extends PlayerBase {
|
export class Player extends PlayerBase {
|
||||||
// default, until the clients sends its real value
|
// default, until the clients sends its real value
|
||||||
private aspectRatio: number = 16 / 9;
|
private aspectRatio: number = 16 / 9;
|
||||||
|
private timeUntilRespawn = 0;
|
||||||
|
private timeSinceLastMessage = 0;
|
||||||
private objectsPreviouslyInViewArea: Array<GameObject> = [];
|
private objectsPreviouslyInViewArea: Array<GameObject> = [];
|
||||||
|
|
||||||
protected commandExecutors: CommandExecutors = {
|
protected commandExecutors: CommandExecutors = {
|
||||||
|
|
@ -68,12 +69,12 @@ export class Player extends PlayerBase {
|
||||||
this.queueCommandSend(new CreatePlayerCommand(this.character!));
|
this.queueCommandSend(new CreatePlayerCommand(this.character!));
|
||||||
}
|
}
|
||||||
|
|
||||||
private timeSinceLastMessage = 0;
|
private winnerTeam?: CharacterTeam;
|
||||||
private messageInterval = 1 / 30;
|
public onGameEnded(winnerTeam: CharacterTeam) {
|
||||||
private timeUntilRespawn = 0;
|
this.winnerTeam = winnerTeam;
|
||||||
public step(deltaTimeInSeconds: number) {
|
}
|
||||||
this.timeSinceLastMessage += deltaTimeInSeconds;
|
|
||||||
|
|
||||||
|
public step(deltaTimeInSeconds: number) {
|
||||||
if (this.character) {
|
if (this.character) {
|
||||||
this.center = this.character?.center;
|
this.center = this.character?.center;
|
||||||
|
|
||||||
|
|
@ -85,72 +86,60 @@ export class Player extends PlayerBase {
|
||||||
this.timeUntilRespawn = settings.playerDiedTimeout;
|
this.timeUntilRespawn = settings.playerDiedTimeout;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.timeSinceLastMessage > this.messageInterval) {
|
|
||||||
this.queueCommandSend(
|
|
||||||
new ServerAnnouncement(`Reviving in ${Math.round(this.timeUntilRespawn)}…`),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.timeUntilRespawn -= deltaTimeInSeconds) < 0) {
|
if ((this.timeUntilRespawn -= deltaTimeInSeconds) < 0) {
|
||||||
this.createCharacter();
|
this.createCharacter();
|
||||||
this.center = this.character!.center;
|
this.center = this.character!.center;
|
||||||
this.queueCommandSend(new ServerAnnouncement(''));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.timeSinceLastMessage > this.messageInterval) {
|
const remoteCalls = this.objectsPreviouslyInViewArea
|
||||||
const viewArea = calculateViewArea(this.center, this.aspectRatio, 1.2);
|
.map((g) => new RemoteCallsForObject(g.id, g.getRemoteCalls()))
|
||||||
const bb = new BoundingBox();
|
.filter((c) => c.calls.length > 0);
|
||||||
bb.topLeft = viewArea.topLeft;
|
|
||||||
bb.size = viewArea.size;
|
|
||||||
|
|
||||||
const objectsInViewArea = Array.from(
|
if (remoteCalls.length > 0) {
|
||||||
new Set(this.objectContainer.findIntersecting(bb).map((o) => o.gameObject)),
|
this.queueCommandSend(new RemoteCallsForObjects(remoteCalls));
|
||||||
);
|
|
||||||
|
|
||||||
const newlyIntersecting = objectsInViewArea.filter(
|
|
||||||
(o) => !this.objectsPreviouslyInViewArea.includes(o),
|
|
||||||
);
|
|
||||||
|
|
||||||
const noLongerIntersecting = this.objectsPreviouslyInViewArea.filter(
|
|
||||||
(o) => !objectsInViewArea.includes(o),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.objectsPreviouslyInViewArea = objectsInViewArea;
|
|
||||||
|
|
||||||
if (noLongerIntersecting.length > 0) {
|
|
||||||
this.queueCommandSend(
|
|
||||||
new DeleteObjectsCommand(noLongerIntersecting.map((g) => g.id)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newlyIntersecting.length > 0) {
|
|
||||||
this.queueCommandSend(new CreateObjectsCommand(newlyIntersecting));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.queueCommandSend(new UpdateOtherPlayerDirections(this.getOtherPlayers()));
|
|
||||||
|
|
||||||
this.queueCommandSend(
|
|
||||||
new PropertyUpdatesForObjects(
|
|
||||||
this.objectsPreviouslyInViewArea
|
|
||||||
.map((o) => o.getPropertyUpdates())
|
|
||||||
.filter((u) => u) as Array<PropertyUpdatesForObject>,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.queueCommandSend(
|
private handleViewAreaUpdate() {
|
||||||
new RemoteCallsForObjects(
|
const viewArea = calculateViewArea(this.center, this.aspectRatio, 1.2);
|
||||||
this.objectsPreviouslyInViewArea.map(
|
const bb = new BoundingBox();
|
||||||
(g) => new RemoteCallsForObject(g.id, g.getRemoteCalls()),
|
bb.topLeft = viewArea.topLeft;
|
||||||
),
|
bb.size = viewArea.size;
|
||||||
),
|
|
||||||
|
const objectsInViewArea = Array.from(
|
||||||
|
new Set(this.objectContainer.findIntersecting(bb).map((o) => o.gameObject)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.timeSinceLastMessage > this.messageInterval) {
|
const newlyIntersecting = objectsInViewArea.filter(
|
||||||
this.sendQueuedCommandsToClient();
|
(o) => !this.objectsPreviouslyInViewArea.includes(o),
|
||||||
this.timeSinceLastMessage = 0;
|
);
|
||||||
|
|
||||||
|
const noLongerIntersecting = this.objectsPreviouslyInViewArea.filter(
|
||||||
|
(o) => !objectsInViewArea.includes(o),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.objectsPreviouslyInViewArea = objectsInViewArea;
|
||||||
|
|
||||||
|
if (noLongerIntersecting.length > 0) {
|
||||||
|
this.queueCommandSend(
|
||||||
|
new DeleteObjectsCommand(noLongerIntersecting.map((g) => g.id)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newlyIntersecting.length > 0) {
|
||||||
|
this.queueCommandSend(new CreateObjectsCommand(newlyIntersecting));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.queueCommandSend(new UpdateOtherPlayerDirections(this.getOtherPlayers()));
|
||||||
|
|
||||||
|
this.queueCommandSend(
|
||||||
|
new PropertyUpdatesForObjects(
|
||||||
|
this.objectsPreviouslyInViewArea
|
||||||
|
.map((o) => o.getPropertyUpdates())
|
||||||
|
.filter((u) => u) as Array<PropertyUpdatesForObject>,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOtherPlayers(): Array<OtherPlayerDirection> {
|
private getOtherPlayers(): Array<OtherPlayerDirection> {
|
||||||
|
|
@ -190,11 +179,33 @@ export class Player extends PlayerBase {
|
||||||
this.commandsToBeSent.push(command);
|
this.commandsToBeSent.push(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public stepCommunications(deltaTime: number) {
|
||||||
|
if ((this.timeSinceLastMessage += deltaTime) > settings.updateMessageInterval) {
|
||||||
|
this.handleAnnouncements();
|
||||||
|
this.handleViewAreaUpdate();
|
||||||
|
this.sendQueuedCommandsToClient();
|
||||||
|
this.timeSinceLastMessage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sendQueuedCommandsToClient() {
|
public sendQueuedCommandsToClient() {
|
||||||
this.socket.emit(TransportEvents.ServerToPlayer, serialize(this.commandsToBeSent));
|
this.socket.emit(TransportEvents.ServerToPlayer, serialize(this.commandsToBeSent));
|
||||||
this.commandsToBeSent = [];
|
this.commandsToBeSent = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleAnnouncements() {
|
||||||
|
let announcement = '';
|
||||||
|
if (this.winnerTeam) {
|
||||||
|
announcement = `Team <span class="${this.winnerTeam}">${this.winnerTeam}</span> won 🎉`;
|
||||||
|
} else if (!this.character) {
|
||||||
|
announcement = `Reviving in ${Math.round(this.timeUntilRespawn)}…`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (announcement) {
|
||||||
|
this.queueCommandSend(new ServerAnnouncement(announcement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ export class Game extends CommandReceiver {
|
||||||
this.lastAnnouncementText = '';
|
this.lastAnnouncementText = '';
|
||||||
this.overlay.appendChild(this.progressBar);
|
this.overlay.appendChild(this.progressBar);
|
||||||
this.announcementText.innerText = '';
|
this.announcementText.innerText = '';
|
||||||
|
this.timeScaling = 1;
|
||||||
this.overlay.appendChild(this.announcementText);
|
this.overlay.appendChild(this.announcementText);
|
||||||
|
|
||||||
this.socket = io(this.playerDecision.server, {
|
this.socket = io(this.playerDecision.server, {
|
||||||
|
|
@ -128,16 +129,16 @@ export class Game extends CommandReceiver {
|
||||||
|
|
||||||
private lastGameState?: UpdateGameState;
|
private lastGameState?: UpdateGameState;
|
||||||
private isEnding = false;
|
private isEnding = false;
|
||||||
|
private timeScaling = 1;
|
||||||
|
|
||||||
private lastAnnouncementText = '';
|
private lastAnnouncementText = '';
|
||||||
protected commandExecutors: CommandExecutors = {
|
protected commandExecutors: CommandExecutors = {
|
||||||
[ServerAnnouncement.type]: (c: ServerAnnouncement) =>
|
[ServerAnnouncement.type]: (c: ServerAnnouncement) => {
|
||||||
(this.lastAnnouncementText = c.text),
|
this.lastAnnouncementText = c.text;
|
||||||
[UpdateGameState.type]: (c: UpdateGameState) => (this.lastGameState = c),
|
this.timeSinceLastAnnouncement = 0;
|
||||||
[GameEndCommand.type]: (c: GameEndCommand) => {
|
|
||||||
const team = `<span class="${c.winningTeam}">${c.winningTeam}</span>`;
|
|
||||||
this.lastAnnouncementText = `Team ${team} won 🎉`;
|
|
||||||
this.isEnding = true;
|
|
||||||
},
|
},
|
||||||
|
[UpdateGameState.type]: (c: UpdateGameState) => (this.lastGameState = c),
|
||||||
|
[GameEndCommand.type]: () => (this.isEnding = true),
|
||||||
[UpdateOtherPlayerDirections.type]: (c: UpdateOtherPlayerDirections) =>
|
[UpdateOtherPlayerDirections.type]: (c: UpdateOtherPlayerDirections) =>
|
||||||
(this.lastOtherPlayerDirections = c),
|
(this.lastOtherPlayerDirections = c),
|
||||||
[GameStartCommand.type]: this.initialize.bind(this),
|
[GameStartCommand.type]: this.initialize.bind(this),
|
||||||
|
|
@ -255,6 +256,7 @@ export class Game extends CommandReceiver {
|
||||||
this.isActive = false;
|
this.isActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private timeSinceLastAnnouncement = 0;
|
||||||
private framesSinceLastLayoutUpdate = 0;
|
private framesSinceLastLayoutUpdate = 0;
|
||||||
private gameLoop(
|
private gameLoop(
|
||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
|
|
@ -271,10 +273,19 @@ export class Game extends CommandReceiver {
|
||||||
this.draw();
|
this.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((this.timeSinceLastAnnouncement += deltaTime) > 0.5) {
|
||||||
|
this.lastAnnouncementText = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isEnding) {
|
||||||
|
this.timeScaling *= Math.pow(settings.endGameDeltaScaling, deltaTime);
|
||||||
|
deltaTime /= this.timeScaling;
|
||||||
|
}
|
||||||
|
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
|
||||||
this.socketReceiver.sendQueuedCommands();
|
this.socketReceiver.sendQueuedCommands();
|
||||||
this.gameObjects.stepObjects(this.isEnding ? 0 : deltaTime);
|
this.gameObjects.stepObjects(deltaTime);
|
||||||
this.gameObjects.drawObjects(this.renderer, this.overlay, shouldChangeLayout);
|
this.gameObjects.drawObjects(this.renderer, this.overlay, shouldChangeLayout);
|
||||||
|
|
||||||
return this.isActive;
|
return this.isActive;
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,20 @@ export class JoinFormHandler {
|
||||||
private waitingForDecision: Promise<PlayerDecision>;
|
private waitingForDecision: Promise<PlayerDecision>;
|
||||||
private resolvePlayerDecision!: (d: PlayerDecision) => void;
|
private resolvePlayerDecision!: (d: PlayerDecision) => void;
|
||||||
private pollServersTimer: any;
|
private pollServersTimer: any;
|
||||||
|
private keyUpListener = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'enter') {
|
||||||
|
this.form.submit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
constructor(form: HTMLFormElement, private readonly container: HTMLElement) {
|
constructor(private form: HTMLFormElement, private readonly container: HTMLElement) {
|
||||||
this.joinButton = form.querySelector('button[type="submit"]') as HTMLButtonElement;
|
this.joinButton = form.querySelector('button[type="submit"]') as HTMLButtonElement;
|
||||||
this.joinButton.disabled = true;
|
this.joinButton.disabled = true;
|
||||||
this.waitingForDecision = new Promise((r) => (this.resolvePlayerDecision = r));
|
this.waitingForDecision = new Promise((r) => (this.resolvePlayerDecision = r));
|
||||||
|
|
||||||
new FormData(form);
|
new FormData(form);
|
||||||
|
|
||||||
document.addEventListener('keyup', (e) => {
|
addEventListener('keyup', this.keyUpListener);
|
||||||
if (e.key === 'enter') {
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
form.onsubmit = (e) => {
|
form.onsubmit = (e) => {
|
||||||
SoundHandler.play(Sounds.click);
|
SoundHandler.play(Sounds.click);
|
||||||
|
|
@ -54,6 +55,7 @@ export class JoinFormHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private destroy() {
|
private destroy() {
|
||||||
|
removeEventListener('keyup', this.keyUpListener);
|
||||||
clearInterval(this.pollServersTimer);
|
clearInterval(this.pollServersTimer);
|
||||||
this.servers.forEach((s) => s.destroy());
|
this.servers.forEach((s) => s.destroy());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import { ViewObject } from './view-object';
|
||||||
|
|
||||||
export class Camera extends GameObject implements ViewObject {
|
export class Camera extends GameObject implements ViewObject {
|
||||||
public center: vec2 = vec2.create();
|
public center: vec2 = vec2.create();
|
||||||
|
|
||||||
private aspectRatio?: number;
|
private aspectRatio?: number;
|
||||||
|
|
||||||
constructor(private game: Game) {
|
constructor(private game: Game) {
|
||||||
|
|
@ -15,12 +14,10 @@ export class Camera extends GameObject implements ViewObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateProperties(update: UpdateProperty[]): void {}
|
public updateProperties(update: UpdateProperty[]): void {}
|
||||||
|
public step(deltaTimeInSeconds: number): void {}
|
||||||
public beforeDestroy(): void {}
|
public beforeDestroy(): void {}
|
||||||
|
|
||||||
public step(deltaTimeInSeconds: number): void {}
|
public draw(renderer: Renderer) {
|
||||||
|
|
||||||
public draw(renderer: Renderer, overlay: HTMLElement, shouldChangeLayout: boolean) {
|
|
||||||
const canvasAspectRatio = renderer.canvasSize.x / renderer.canvasSize.y;
|
const canvasAspectRatio = renderer.canvasSize.x / renderer.canvasSize.y;
|
||||||
if (canvasAspectRatio !== this.aspectRatio) {
|
if (canvasAspectRatio !== this.aspectRatio) {
|
||||||
this.aspectRatio = canvasAspectRatio;
|
this.aspectRatio = canvasAspectRatio;
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,17 @@ type FallingPoint = {
|
||||||
|
|
||||||
export class PlanetView extends PlanetBase implements ViewObject {
|
export class PlanetView extends PlanetBase implements ViewObject {
|
||||||
private shape: PlanetShape;
|
private shape: PlanetShape;
|
||||||
private ownershipProgess: HTMLElement;
|
private ownershipProgress: HTMLElement;
|
||||||
|
|
||||||
constructor(id: Id, vertices: Array<vec2>, ownership: number) {
|
constructor(id: Id, vertices: Array<vec2>, ownership: number) {
|
||||||
super(id, vertices);
|
super(id, vertices);
|
||||||
this.shape = new PlanetShape(vertices, ownership);
|
this.shape = new PlanetShape(vertices, ownership);
|
||||||
(this.shape as any).randomOffset = Random.getRandom();
|
(this.shape as any).randomOffset = Random.getRandom();
|
||||||
|
|
||||||
this.ownershipProgess = document.createElement('div');
|
this.ownershipProgress = document.createElement('div');
|
||||||
this.ownershipProgess.className = 'ownership';
|
this.ownershipProgress.className = 'ownership';
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateProperties(update: UpdateProperty[]): void {}
|
|
||||||
|
|
||||||
public step(deltaTimeInSeconds: number): void {
|
public step(deltaTimeInSeconds: number): void {
|
||||||
this.shape.randomOffset += deltaTimeInSeconds / 4;
|
this.shape.randomOffset += deltaTimeInSeconds / 4;
|
||||||
this.shape.colorMixQ = this.ownership;
|
this.shape.colorMixQ = this.ownership;
|
||||||
|
|
@ -56,20 +54,26 @@ export class PlanetView extends PlanetBase implements ViewObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public beforeDestroy(): void {
|
public beforeDestroy(): void {
|
||||||
this.ownershipProgess.parentElement?.removeChild(this.ownershipProgess);
|
this.ownershipProgress.parentElement?.removeChild(this.ownershipProgress);
|
||||||
this.generatedPointElements.forEach((p) =>
|
this.generatedPointElements.forEach((p) =>
|
||||||
p.element.parentElement?.removeChild(p.element),
|
p.element.parentElement?.removeChild(p.element),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateProperties(update: UpdateProperty[]): void {
|
||||||
|
update.forEach((u) => {
|
||||||
|
this.ownership = u.propertyValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public draw(
|
public draw(
|
||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
overlay: HTMLElement,
|
overlay: HTMLElement,
|
||||||
shouldChangeLayout: boolean,
|
shouldChangeLayout: boolean,
|
||||||
): void {
|
): void {
|
||||||
if (shouldChangeLayout) {
|
if (shouldChangeLayout) {
|
||||||
if (!this.ownershipProgess.parentElement) {
|
if (!this.ownershipProgress.parentElement) {
|
||||||
overlay.appendChild(this.ownershipProgess);
|
overlay.appendChild(this.ownershipProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
const screenPosition = renderer.worldToDisplayCoordinates(this.center);
|
const screenPosition = renderer.worldToDisplayCoordinates(this.center);
|
||||||
|
|
@ -94,8 +98,8 @@ export class PlanetView extends PlanetBase implements ViewObject {
|
||||||
(p) => p.timeToLive > 0,
|
(p) => p.timeToLive > 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.ownershipProgess.style.transform = `translateX(${screenPosition.x}px) translateY(${screenPosition.y}px) translateX(-50%) translateY(-50%)`;
|
this.ownershipProgress.style.transform = `translateX(${screenPosition.x}px) translateY(${screenPosition.y}px) translateX(-50%) translateY(-50%)`;
|
||||||
this.ownershipProgess.style.background = this.getGradient();
|
this.ownershipProgress.style.background = this.getGradient();
|
||||||
|
|
||||||
if (this.lastGeneratedPoint !== undefined) {
|
if (this.lastGeneratedPoint !== undefined) {
|
||||||
const element = document.createElement('div');
|
const element = document.createElement('div');
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ const TsConfigWebpackPlugin = require('ts-config-webpack-plugin');
|
||||||
const HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin');
|
const HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin');
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
const TerserJSPlugin = require('terser-webpack-plugin');
|
const TerserJSPlugin = require('terser-webpack-plugin');
|
||||||
|
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||||
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
|
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
|
||||||
const Sass = require('sass');
|
const Sass = require('sass');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = (env, argv) => ({
|
||||||
devServer: {
|
devServer: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
|
|
@ -18,9 +19,10 @@ module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
new CleanWebpackPlugin(),
|
new CleanWebpackPlugin(),
|
||||||
new MiniCssExtractPlugin(),
|
new MiniCssExtractPlugin(),
|
||||||
|
//new BundleAnalyzerPlugin(),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: './src/index.html',
|
template: './src/index.html',
|
||||||
//inlineSource: '.(css)$',
|
inlineSource: argv.mode === 'development' ? '' : '.(css)$',
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin),
|
new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin),
|
||||||
new HtmlWebpackInlineSVGPlugin({
|
new HtmlWebpackInlineSVGPlugin({
|
||||||
|
|
@ -31,7 +33,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new TsConfigWebpackPlugin(),
|
new TsConfigWebpackPlugin(),
|
||||||
],
|
],
|
||||||
optimization: {
|
optimization: {
|
||||||
|
|
@ -106,4 +107,4 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { Command } from '../commands/command';
|
|
||||||
import { Id } from '../communication/id';
|
import { Id } from '../communication/id';
|
||||||
import { serializable } from '../serialization/serializable';
|
import { serializable } from '../serialization/serializable';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,6 @@ export class PlanetBase extends GameObject {
|
||||||
vec2.scale(this.center, this.center, 1 / vertices.length);
|
vec2.scale(this.center, this.center, 1 / vertices.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setOwnership(value: number) {
|
|
||||||
this.ownership = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public generatedPoints(value: number) {}
|
public generatedPoints(value: number) {}
|
||||||
|
|
||||||
public static createPlanetVertices(
|
public static createPlanetVertices(
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,11 @@ const redPlanetColor = redColorDim;
|
||||||
|
|
||||||
export const settings = {
|
export const settings = {
|
||||||
lightCutoffDistance: 600,
|
lightCutoffDistance: 600,
|
||||||
maxVelocityX: 1000,
|
|
||||||
maxVelocityY: 1000,
|
|
||||||
radiusSteps: 500,
|
radiusSteps: 500,
|
||||||
spawnDespawnTime: 0.7,
|
spawnDespawnTime: 0.7,
|
||||||
worldRadius: 10000,
|
worldRadius: 10000,
|
||||||
objectsOnCircleLength: 0.002,
|
objectsOnCircleLength: 0.002,
|
||||||
|
updateMessageInterval: 1 / 25,
|
||||||
planetEdgeCount: 7,
|
planetEdgeCount: 7,
|
||||||
playerKillPoint: 10,
|
playerKillPoint: 10,
|
||||||
takeControlTimeInSeconds: 4,
|
takeControlTimeInSeconds: 4,
|
||||||
|
|
@ -29,9 +28,9 @@ export const settings = {
|
||||||
planetControlThreshold: 0.2,
|
planetControlThreshold: 0.2,
|
||||||
playerMaxHealth: 100,
|
playerMaxHealth: 100,
|
||||||
maxGravityStrength: 10000,
|
maxGravityStrength: 10000,
|
||||||
maxAcceleration: 60000,
|
maxAcceleration: 120000,
|
||||||
playerMaxStrength: 80,
|
playerMaxStrength: 80,
|
||||||
endGameDeltaScaling: 4,
|
endGameDeltaScaling: 2,
|
||||||
playerDiedTimeout: 5,
|
playerDiedTimeout: 5,
|
||||||
playerStrengthRegenerationPerSeconds: 80,
|
playerStrengthRegenerationPerSeconds: 80,
|
||||||
projectileMaxStrength: 40,
|
projectileMaxStrength: 40,
|
||||||
|
|
@ -47,58 +46,50 @@ export const settings = {
|
||||||
npcNames: [
|
npcNames: [
|
||||||
'Adam',
|
'Adam',
|
||||||
'Andrew',
|
'Andrew',
|
||||||
|
'Blaise',
|
||||||
'Clarence',
|
'Clarence',
|
||||||
|
'Dean',
|
||||||
|
'Dustin',
|
||||||
'Elliot',
|
'Elliot',
|
||||||
'Elmer',
|
|
||||||
'Ernie',
|
'Ernie',
|
||||||
'Eugene',
|
'Ethan',
|
||||||
'Fergus',
|
|
||||||
'Ferris',
|
|
||||||
'Frank',
|
'Frank',
|
||||||
'Frasier',
|
|
||||||
'Fred',
|
'Fred',
|
||||||
'George',
|
'George',
|
||||||
'Graham',
|
'Graham',
|
||||||
|
'Harold',
|
||||||
'Harvey',
|
'Harvey',
|
||||||
|
'Henry',
|
||||||
|
'Mingan',
|
||||||
|
'Irving',
|
||||||
'Irwin',
|
'Irwin',
|
||||||
|
'Jason',
|
||||||
|
'Jenssen',
|
||||||
|
'Josh',
|
||||||
|
'Ladislaus',
|
||||||
'Larry',
|
'Larry',
|
||||||
'Lester',
|
'Lester',
|
||||||
|
'Martin',
|
||||||
'Marvin',
|
'Marvin',
|
||||||
'Neil',
|
'Neil',
|
||||||
|
'Nick',
|
||||||
'Niles',
|
'Niles',
|
||||||
|
'Norm',
|
||||||
'Oliver',
|
'Oliver',
|
||||||
'Blaise',
|
'Orin',
|
||||||
'Opie',
|
'Pat',
|
||||||
|
'Perry',
|
||||||
|
'Ron',
|
||||||
'Ryan',
|
'Ryan',
|
||||||
|
'Sisyphus',
|
||||||
|
'Tim',
|
||||||
'Toby',
|
'Toby',
|
||||||
'Ulric',
|
|
||||||
'Ulysses',
|
'Ulysses',
|
||||||
'Uri',
|
'Uri',
|
||||||
'Waldo',
|
'Waldo',
|
||||||
'Wally',
|
'Wally',
|
||||||
'Walt',
|
'Walt',
|
||||||
'Wesley',
|
'Wesley',
|
||||||
'Yanni',
|
|
||||||
'Yogi',
|
|
||||||
'Yuri',
|
|
||||||
'Dean',
|
|
||||||
'Dustin',
|
|
||||||
'Ethan',
|
|
||||||
'Harold',
|
|
||||||
'Henry',
|
|
||||||
'Irving',
|
|
||||||
'Jason',
|
|
||||||
'Jenssen',
|
|
||||||
'Josh',
|
|
||||||
'Martin',
|
|
||||||
'Nick',
|
|
||||||
'Norm',
|
|
||||||
'Orin',
|
|
||||||
'Pat',
|
|
||||||
'Perry',
|
|
||||||
'Ron',
|
|
||||||
'Shawn',
|
|
||||||
'Tim',
|
|
||||||
'Will',
|
'Will',
|
||||||
'Wyatt',
|
'Wyatt',
|
||||||
],
|
],
|
||||||
|
|
@ -111,6 +102,6 @@ export const settings = {
|
||||||
},
|
},
|
||||||
palette: [declaColor, neutralColor, redColor],
|
palette: [declaColor, neutralColor, redColor],
|
||||||
paletteDim: [declaColorDim, neutralColor, redColorDim],
|
paletteDim: [declaColorDim, neutralColor, redColorDim],
|
||||||
targetPhysicsDeltaTimeInSeconds: 1 / 100,
|
targetPhysicsDeltaTimeInSeconds: 1 / 200,
|
||||||
inViewAreaSize: 1920 * 1080 * 4,
|
inViewAreaSize: 1920 * 1080 * 4,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue