From 57d70093422809506ca3918817f54d8812b0b3c8 Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Wed, 4 Nov 2020 22:05:21 +0100 Subject: [PATCH] Refactor --- backend/src/create-world.ts | 4 +- backend/src/game-server.ts | 8 +- backend/src/main.ts | 6 +- .../src/objects/capabilities/exerts-force.ts | 7 ++ .../{ => capabilities}/generates-points.ts | 0 .../capabilities}/reacts-to-collision.ts | 0 .../objects/capabilities/time-dependent.ts | 5 + ...cter-physical.ts => character-physical.ts} | 91 +++++++++++-------- backend/src/objects/circle-physical.ts | 27 +----- backend/src/objects/lamp-physical.ts | 6 -- backend/src/objects/planet-physical.ts | 8 +- backend/src/objects/projectile-physical.ts | 16 ++-- .../physics/containers/physical-container.ts | 10 +- .../physics/functions/force-at-position.ts | 3 +- backend/src/physics/functions/move-circle.ts | 11 +-- .../src/physics/physicals/physical-base.ts | 1 - .../src/physics/physicals/static-physical.ts | 3 - backend/src/players/npc.ts | 22 ++--- backend/src/players/player-base.ts | 10 +- backend/src/players/player.ts | 32 +------ frontend/src/index.html | 6 +- frontend/src/index.ts | 17 +++- .../src/scripts/commands/mouse-listener.ts | 10 +- frontend/src/scripts/game.ts | 52 +++++++++-- .../{ => helper}/handle-full-screen.ts | 2 +- frontend/src/scripts/join-form-handler.ts | 2 +- .../src/scripts/landing-page-background.ts | 1 - ...er-character-view.ts => character-view.ts} | 6 +- .../scripts/objects/game-object-container.ts | 6 +- frontend/src/scripts/start-animation.ts | 45 --------- shared/src/commands/types/create-player.ts | 4 +- shared/src/commands/types/game-end.ts | 2 +- .../types/update-other-player-directions.ts | 2 +- shared/src/helper/circle.ts | 4 - shared/src/main.ts | 3 +- ...er-character-base.ts => character-base.ts} | 11 ++- shared/src/objects/types/character-team.ts | 5 - shared/src/objects/types/projectile-base.ts | 2 +- shared/src/settings.ts | 3 +- 39 files changed, 203 insertions(+), 250 deletions(-) create mode 100644 backend/src/objects/capabilities/exerts-force.ts rename backend/src/objects/{ => capabilities}/generates-points.ts (100%) rename backend/src/{physics/functions => objects/capabilities}/reacts-to-collision.ts (100%) create mode 100644 backend/src/objects/capabilities/time-dependent.ts rename backend/src/objects/{player-character-physical.ts => character-physical.ts} (85%) rename frontend/src/scripts/{ => helper}/handle-full-screen.ts (95%) rename frontend/src/scripts/objects/{player-character-view.ts => character-view.ts} (97%) delete mode 100644 frontend/src/scripts/start-animation.ts rename shared/src/objects/types/{player-character-base.ts => character-base.ts} (85%) delete mode 100644 shared/src/objects/types/character-team.ts diff --git a/backend/src/create-world.ts b/backend/src/create-world.ts index 13d7d3e..1b846ba 100644 --- a/backend/src/create-world.ts +++ b/backend/src/create-world.ts @@ -67,8 +67,8 @@ export const createWorld = (objectContainer: PhysicalContainer, worldRadius: num } } } - console.log('Generated planet count', objects.length); - console.log('Generated light count', lights.length); + console.info('Generated planet count', objects.length); + console.info('Generated light count', lights.length); [...objects, ...lights].forEach((o) => objectContainer.addObject(o)); }; diff --git a/backend/src/game-server.ts b/backend/src/game-server.ts index 658294b..6c48f4f 100644 --- a/backend/src/game-server.ts +++ b/backend/src/game-server.ts @@ -69,7 +69,7 @@ export class GameServer { const commands: Array = deserialize(json); commands.forEach((c) => player.sendCommand(c)); } catch (e) { - console.log('Error while processing command', e); + console.error('Error while processing command', e); } }); @@ -169,16 +169,16 @@ export class GameServer { if (this.deltaTimes.length > framesBetweenDeltaTimeCalculation) { this.deltaTimes.sort((a, b) => a - b); - console.log( + console.info( `Median physics time: ${this.deltaTimes[ Math.floor(framesBetweenDeltaTimeCalculation / 2) ].toFixed(2)} ms`, ); - console.log( + console.info( 'Tail times: ', this.deltaTimes.slice(-20).map((v) => `${(v * 1000).toFixed(2)} ms`), ); - console.log( + console.info( `Memory used: ${(process.memoryUsage().rss / 1024 / 1024).toFixed(2)} MB`, ); this.deltaTimes = []; diff --git a/backend/src/main.ts b/backend/src/main.ts index 2b142ef..42fcffb 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -28,19 +28,19 @@ const gameServer = new GameServer(io, options); app.use( cors({ - origin: (origin, callback) => { + origin: (_, callback) => { callback(null, true); }, credentials: true, }), ); -app.get(serverInformationEndpoint, (req, res) => { +app.get(serverInformationEndpoint, (_, res) => { res.json(gameServer.serverInfo); }); server.listen(options.port, () => { - console.log(`server started at http://localhost:${options.port}`); + console.info(`Server started on port ${options.port}`); }); gameServer.start(); diff --git a/backend/src/objects/capabilities/exerts-force.ts b/backend/src/objects/capabilities/exerts-force.ts new file mode 100644 index 0000000..6e5c4ee --- /dev/null +++ b/backend/src/objects/capabilities/exerts-force.ts @@ -0,0 +1,7 @@ +import { vec2 } from 'gl-matrix'; + +export interface ExertsForce { + getForce(target: vec2): vec2; +} + +export const exertsForce = (a: any): a is ExertsForce => a && 'getForce' in a; diff --git a/backend/src/objects/generates-points.ts b/backend/src/objects/capabilities/generates-points.ts similarity index 100% rename from backend/src/objects/generates-points.ts rename to backend/src/objects/capabilities/generates-points.ts diff --git a/backend/src/physics/functions/reacts-to-collision.ts b/backend/src/objects/capabilities/reacts-to-collision.ts similarity index 100% rename from backend/src/physics/functions/reacts-to-collision.ts rename to backend/src/objects/capabilities/reacts-to-collision.ts diff --git a/backend/src/objects/capabilities/time-dependent.ts b/backend/src/objects/capabilities/time-dependent.ts new file mode 100644 index 0000000..6904d87 --- /dev/null +++ b/backend/src/objects/capabilities/time-dependent.ts @@ -0,0 +1,5 @@ +export interface TimeDependent { + step(deltaTimeInSeconds: number): void; +} + +export const timeDependent = (a: any): a is TimeDependent => a && 'step' in a; diff --git a/backend/src/objects/player-character-physical.ts b/backend/src/objects/character-physical.ts similarity index 85% rename from backend/src/objects/player-character-physical.ts rename to backend/src/objects/character-physical.ts index be5d67f..540230c 100644 --- a/backend/src/objects/player-character-physical.ts +++ b/backend/src/objects/character-physical.ts @@ -7,7 +7,7 @@ import { last, GameObject, Circle, - PlayerCharacterBase, + CharacterBase, CharacterTeam, PropertyUpdatesForObject, UpdateProperty, @@ -21,12 +21,14 @@ import { interpolateAngles } from '../helper/interpolate-angles'; import { forceAtPosition } from '../physics/functions/force-at-position'; import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle'; import { PlanetPhysical } from './planet-physical'; -import { ReactsToCollision } from '../physics/functions/reacts-to-collision'; +import { ReactsToCollision } from './capabilities/reacts-to-collision'; +import { TimeDependent } from './capabilities/time-dependent'; +import { GeneratesPoints } from './capabilities/generates-points'; -@serializesTo(PlayerCharacterBase) -export class PlayerCharacterPhysical - extends PlayerCharacterBase - implements DynamicPhysical, ReactsToCollision { +@serializesTo(CharacterBase) +export class CharacterPhysical + extends CharacterBase + implements DynamicPhysical, ReactsToCollision, TimeDependent, GeneratesPoints { public readonly canCollide = true; public readonly canMove = true; @@ -44,32 +46,32 @@ export class PlayerCharacterPhysical vec2.create(), vec2.add( vec2.create(), - PlayerCharacterPhysical.desiredHeadOffset, - PlayerCharacterPhysical.desiredLeftFootOffset, + CharacterPhysical.desiredHeadOffset, + CharacterPhysical.desiredLeftFootOffset, ), - PlayerCharacterPhysical.desiredRightFootOffset, + CharacterPhysical.desiredRightFootOffset, ), 1 / 3, ); private static readonly headOffset = vec2.subtract( vec2.create(), - PlayerCharacterPhysical.desiredHeadOffset, - PlayerCharacterPhysical.centerOfMass, + CharacterPhysical.desiredHeadOffset, + CharacterPhysical.centerOfMass, ); private static readonly leftFootOffset = vec2.subtract( vec2.create(), - PlayerCharacterPhysical.desiredLeftFootOffset, - PlayerCharacterPhysical.centerOfMass, + CharacterPhysical.desiredLeftFootOffset, + CharacterPhysical.centerOfMass, ); private static readonly rightFootOffset = vec2.subtract( vec2.create(), - PlayerCharacterPhysical.desiredRightFootOffset, - PlayerCharacterPhysical.centerOfMass, + CharacterPhysical.desiredRightFootOffset, + CharacterPhysical.centerOfMass, ); public static readonly boundRadius = - (PlayerCharacterPhysical.headRadius + PlayerCharacterPhysical.feetRadius * 2) * 2; + (CharacterPhysical.headRadius + CharacterPhysical.feetRadius * 2) * 2; private timeSinceDying = 0; private isDestroyed = false; @@ -102,20 +104,20 @@ export class PlayerCharacterPhysical ) { super(id(), name, killCount, deathCount, team, settings.playerMaxHealth); this.head = new CirclePhysical( - vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.headOffset), - PlayerCharacterPhysical.headRadius, + vec2.add(vec2.create(), startPosition, CharacterPhysical.headOffset), + CharacterPhysical.headRadius, this, container, ); this.leftFoot = new CirclePhysical( - vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.leftFootOffset), - PlayerCharacterPhysical.feetRadius, + vec2.add(vec2.create(), startPosition, CharacterPhysical.leftFootOffset), + CharacterPhysical.feetRadius, this, container, ); this.rightFoot = new CirclePhysical( - vec2.add(vec2.create(), startPosition, PlayerCharacterPhysical.rightFootOffset), - PlayerCharacterPhysical.feetRadius, + vec2.add(vec2.create(), startPosition, CharacterPhysical.rightFootOffset), + CharacterPhysical.feetRadius, this, container, ); @@ -125,12 +127,29 @@ export class PlayerCharacterPhysical this.bound = new CirclePhysical( vec2.create(), - PlayerCharacterPhysical.boundRadius, + CharacterPhysical.boundRadius, this, container, ); } + private hasGeneratedPoints = false; + public getPoints(): { decla: number; red: number } { + if (!this.isAlive && !this.hasGeneratedPoints) { + this.hasGeneratedPoints = true; + const decla = this.team === CharacterTeam.decla ? 0 : settings.playerKillPoint; + const red = this.team === CharacterTeam.red ? 0 : settings.playerKillPoint; + return { + decla, + red, + }; + } + return { + decla: 0, + red: 0, + }; + } + public get isAlive(): boolean { return !this.isDestroyed; } @@ -154,7 +173,7 @@ export class PlayerCharacterPhysical this.health -= other.strength; this.remoteCall('setHealth', this.health); if (this.health <= 0 && this.isAlive) { - this.kill(); + this.onDie(); other.originator.addKill(); } } @@ -231,8 +250,8 @@ export class PlayerCharacterPhysical } private animateScaling(q: number) { - this.head.radius = PlayerCharacterPhysical.headRadius * q; - this.leftFoot.radius = this.rightFoot.radius = PlayerCharacterPhysical.feetRadius * q; + this.head.radius = CharacterPhysical.headRadius * q; + this.leftFoot.radius = this.rightFoot.radius = CharacterPhysical.feetRadius * q; } public getPropertyUpdates(): PropertyUpdatesForObject { @@ -325,7 +344,7 @@ export class PlayerCharacterPhysical getBoundingBoxOfCircle( new Circle( this.center, - PlayerCharacterPhysical.boundRadius + settings.maxGravityDistance, + CharacterPhysical.boundRadius + settings.maxGravityDistance, ), ), ); @@ -407,25 +426,19 @@ export class PlayerCharacterPhysical this.springMove( this.leftFoot, center, - PlayerCharacterPhysical.leftFootOffset, + CharacterPhysical.leftFootOffset, deltaTime, 3000, ); this.springMove( this.rightFoot, center, - PlayerCharacterPhysical.rightFootOffset, + CharacterPhysical.rightFootOffset, deltaTime, 3000, ); - this.springMove( - this.head, - center, - PlayerCharacterPhysical.headOffset, - deltaTime, - 7000, - ); + this.springMove(this.head, center, CharacterPhysical.headOffset, deltaTime, 7000); } private springMove( @@ -462,7 +475,7 @@ export class PlayerCharacterPhysical } private stepBodyPart(part: CirclePhysical, deltaTime: number) { - const { hitObject } = part.step2(deltaTime); + const { hitObject } = part.stepManually(deltaTime); if (hitObject instanceof PlanetPhysical) { this.secondsSinceOnSurface = 0; this.currentPlanet = hitObject; @@ -477,9 +490,9 @@ export class PlayerCharacterPhysical ); } - public kill() { + public onDie() { this.isDestroyed = true; - this.remoteCall('kill'); + this.remoteCall('onDie'); } private destroy() { diff --git a/backend/src/objects/circle-physical.ts b/backend/src/objects/circle-physical.ts index 38b7647..2418b63 100644 --- a/backend/src/objects/circle-physical.ts +++ b/backend/src/objects/circle-physical.ts @@ -1,15 +1,11 @@ import { vec2 } from 'gl-matrix'; -import { Circle, GameObject, serializesTo, settings } from 'shared'; -import { PhysicalBase } from '../physics/physicals/physical-base'; +import { Circle, GameObject, serializesTo } from 'shared'; import { BoundingBox } from '../physics/bounding-boxes/bounding-box'; import { BoundingBoxBase } from '../physics/bounding-boxes/bounding-box-base'; import { moveCircle } from '../physics/functions/move-circle'; import { PhysicalContainer } from '../physics/containers/physical-container'; import { DynamicPhysical } from '../physics/physicals/dynamic-physical'; -import { - ReactsToCollision, - reactsToCollision, -} from '../physics/functions/reacts-to-collision'; +import { ReactsToCollision, reactsToCollision } from './capabilities/reacts-to-collision'; @serializesTo(Circle) export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollision { @@ -17,8 +13,9 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio readonly canMove = true; public velocity = vec2.create(); + public lastNormal = vec2.fromValues(0, 1); + private _boundingBox: BoundingBox; - public lastNormal = vec2.fromValues(1, 0); constructor( private _center: vec2, @@ -67,18 +64,6 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio return vec2.distance(target, this.center) - this.radius; } - public distanceBetween(target: Circle): number { - return vec2.distance(target.center, this.center) - this.radius - target.radius; - } - - public areIntersecting(other: PhysicalBase): boolean { - return other.distance(this.center) < this.radius; - } - - public isInside(other: PhysicalBase): boolean { - return other.distance(this.center) < -this.radius; - } - private recalculateBoundingBox() { this._boundingBox.xMin = this.center.x - this._radius; this._boundingBox.xMax = this.center.x + this._radius; @@ -94,9 +79,7 @@ export class CirclePhysical implements Circle, DynamicPhysical, ReactsToCollisio ); } - public step(_: number) {} - - public step2( + public stepManually( deltaTimeInSeconds: number, ): { hitObject: GameObject | undefined; velocity: vec2 } { let delta = vec2.scale(vec2.create(), this.velocity, deltaTimeInSeconds); diff --git a/backend/src/objects/lamp-physical.ts b/backend/src/objects/lamp-physical.ts index 43ed4a5..3746c01 100644 --- a/backend/src/objects/lamp-physical.ts +++ b/backend/src/objects/lamp-physical.ts @@ -32,12 +32,6 @@ export class LampPhysical extends LampBase implements StaticPhysical { return this; } - public getForce(_: vec2): vec2 { - return vec2.create(); - } - - public step(deltaTime: number): void {} - public distance(target: vec2): number { return vec2.distance(this.center, target); } diff --git a/backend/src/objects/planet-physical.ts b/backend/src/objects/planet-physical.ts index b882f66..8c4c589 100644 --- a/backend/src/objects/planet-physical.ts +++ b/backend/src/objects/planet-physical.ts @@ -4,8 +4,6 @@ import { clamp, clamp01, id, - rotate90Deg, - rotateMinus90Deg, serializesTo, settings, PlanetBase, @@ -14,12 +12,14 @@ import { import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box'; import { StaticPhysical } from '../physics/physicals/static-physical'; -import { GeneratesPoints } from './generates-points'; +import { ExertsForce } from './capabilities/exerts-force'; +import { GeneratesPoints } from './capabilities/generates-points'; +import { TimeDependent } from './capabilities/time-dependent'; @serializesTo(PlanetBase) export class PlanetPhysical extends PlanetBase - implements StaticPhysical, GeneratesPoints { + implements StaticPhysical, GeneratesPoints, ExertsForce, TimeDependent { public readonly canCollide = true; public readonly canMove = false; diff --git a/backend/src/objects/projectile-physical.ts b/backend/src/objects/projectile-physical.ts index 68692c5..ab88efe 100644 --- a/backend/src/objects/projectile-physical.ts +++ b/backend/src/objects/projectile-physical.ts @@ -13,15 +13,15 @@ import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-boundi import { CirclePhysical } from './circle-physical'; import { DynamicPhysical } from '../physics/physicals/dynamic-physical'; import { PhysicalContainer } from '../physics/containers/physical-container'; -import { PlanetPhysical } from './planet-physical'; -import { ReactsToCollision } from '../physics/functions/reacts-to-collision'; -import { PlayerCharacterPhysical } from './player-character-physical'; +import { ReactsToCollision } from './capabilities/reacts-to-collision'; +import { CharacterPhysical } from './character-physical'; import { moveCircle } from '../physics/functions/move-circle'; +import { TimeDependent } from './capabilities/time-dependent'; @serializesTo(ProjectileBase) export class ProjectilePhysical extends ProjectileBase - implements DynamicPhysical, ReactsToCollision { + implements DynamicPhysical, ReactsToCollision, TimeDependent { public readonly canCollide = true; public readonly canMove = true; @@ -37,7 +37,7 @@ export class ProjectilePhysical public strength: number, team: CharacterTeam, private velocity: vec2, - public readonly originator: PlayerCharacterPhysical, + public readonly originator: CharacterPhysical, readonly container: PhysicalContainer, ) { super(id(), center, radius, team, strength); @@ -60,7 +60,7 @@ export class ProjectilePhysical while (wasCollision) { const intersecting = this.container .findIntersecting(this.boundingBox) - .filter((g) => g instanceof PlayerCharacterPhysical && g.team === this.team); + .filter((g) => g instanceof CharacterPhysical && g.team === this.team); const { hitSurface } = moveCircle(this.object, delta, intersecting, true); wasCollision = hitSurface; } @@ -93,7 +93,7 @@ export class ProjectilePhysical public onCollision(other: GameObject) { if ( - !(other instanceof PlayerCharacterPhysical && other.team === this.team) && + !(other instanceof CharacterPhysical && other.team === this.team) && this.bounceCount++ === settings.projectileMaxBounceCount ) { this.destroy(); @@ -115,7 +115,7 @@ export class ProjectilePhysical } vec2.copy(this.object.velocity, this.velocity); - const { velocity } = this.object.step2(deltaTime); + const { velocity } = this.object.stepManually(deltaTime); vec2.copy(this.velocity, velocity); } } diff --git a/backend/src/physics/containers/physical-container.ts b/backend/src/physics/containers/physical-container.ts index f53e300..47f826a 100644 --- a/backend/src/physics/containers/physical-container.ts +++ b/backend/src/physics/containers/physical-container.ts @@ -1,12 +1,14 @@ import { BoundingBoxBase } from '../bounding-boxes/bounding-box-base'; - import { BoundingBoxList } from './bounding-box-list'; import { BoundingBoxTree } from './bounding-box-tree'; - import { Physical } from '../physicals/physical'; import { StaticPhysical } from '../physicals/static-physical'; import { DynamicPhysical } from '../physicals/dynamic-physical'; -import { GeneratesPoints, generatesPoints } from '../../objects/generates-points'; +import { + GeneratesPoints, + generatesPoints, +} from '../../objects/capabilities/generates-points'; +import { timeDependent } from '../../objects/capabilities/time-dependent'; export class PhysicalContainer { private isTreeInitialized = false; @@ -40,7 +42,7 @@ export class PhysicalContainer { } public stepObjects(deltaTime: number) { - this.objects.forEach((o) => o.step(deltaTime)); + this.objects.forEach((o) => timeDependent(o) && o.step(deltaTime)); } public resetRemoteCalls() { diff --git a/backend/src/physics/functions/force-at-position.ts b/backend/src/physics/functions/force-at-position.ts index 5eef3ab..4c6f311 100644 --- a/backend/src/physics/functions/force-at-position.ts +++ b/backend/src/physics/functions/force-at-position.ts @@ -1,9 +1,10 @@ import { vec2 } from 'gl-matrix'; +import { exertsForce } from '../../objects/capabilities/exerts-force'; import { Physical } from '../physicals/physical'; export const forceAtPosition = (position: vec2, objects: Array) => objects.reduce( (sum: vec2, o: Physical) => - !o.canMove ? vec2.add(sum, sum, o.getForce(position)) : sum, + exertsForce(o) ? vec2.add(sum, sum, o.getForce(position)) : sum, vec2.create(), ); diff --git a/backend/src/physics/functions/move-circle.ts b/backend/src/physics/functions/move-circle.ts index 2ee50d8..f9d32ca 100644 --- a/backend/src/physics/functions/move-circle.ts +++ b/backend/src/physics/functions/move-circle.ts @@ -1,7 +1,7 @@ import { vec2 } from 'gl-matrix'; import { Circle, GameObject, rotate90Deg } from 'shared'; import { CirclePhysical } from '../../objects/circle-physical'; -import { reactsToCollision } from './reacts-to-collision'; +import { reactsToCollision } from '../../objects/capabilities/reacts-to-collision'; import { evaluateSdf } from './evaluate-sdf'; import { Physical } from '../physicals/physical'; @@ -11,10 +11,8 @@ export const moveCircle = ( possibleIntersectors: Array, ignoreCollision = false, ): { - realDelta: vec2; hitSurface: boolean; normal?: vec2; - tangent?: vec2; hitObject?: GameObject; } => { const direction = vec2.clone(delta); @@ -78,16 +76,10 @@ export const moveCircle = ( ]); const normal = vec2.fromValues(dx, dy); vec2.normalize(normal, normal); - const rotatedNormal = rotate90Deg(normal); return { - realDelta: delta, hitSurface: true, normal, hitObject: intersecting?.gameObject, - tangent: - vec2.dot(rotatedNormal, delta) < 0 - ? vec2.scale(rotatedNormal, rotatedNormal, -1) - : rotatedNormal, }; } @@ -97,7 +89,6 @@ export const moveCircle = ( vec2.add(circle.center, circle.center, delta); return { - realDelta: delta, hitSurface: false, }; }; diff --git a/backend/src/physics/physicals/physical-base.ts b/backend/src/physics/physicals/physical-base.ts index ba0a753..3f923b6 100644 --- a/backend/src/physics/physicals/physical-base.ts +++ b/backend/src/physics/physicals/physical-base.ts @@ -9,5 +9,4 @@ export interface PhysicalBase { readonly gameObject: GameObject; distance(target: vec2): number; - step(deltaTime: number): void; } diff --git a/backend/src/physics/physicals/static-physical.ts b/backend/src/physics/physicals/static-physical.ts index e222397..eef168b 100644 --- a/backend/src/physics/physicals/static-physical.ts +++ b/backend/src/physics/physicals/static-physical.ts @@ -1,10 +1,7 @@ import { PhysicalBase } from './physical-base'; import { ImmutableBoundingBox } from '../bounding-boxes/immutable-bounding-box'; -import { vec2 } from 'gl-matrix'; export interface StaticPhysical extends PhysicalBase { readonly canMove: false; readonly boundingBox: ImmutableBoundingBox; - - getForce(target: vec2): vec2; } diff --git a/backend/src/players/npc.ts b/backend/src/players/npc.ts index 5151f9c..e9075c0 100644 --- a/backend/src/players/npc.ts +++ b/backend/src/players/npc.ts @@ -1,17 +1,17 @@ import { vec2 } from 'gl-matrix'; import { PlayerInformation, - CharacterTeam, settings, Circle, Random, MoveActionCommand, + CharacterTeam, } from 'shared'; import { PhysicalContainer } from '../physics/containers/physical-container'; import { PlayerContainer } from './player-container'; import { PlayerBase } from './player-base'; import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle'; -import { PlayerCharacterPhysical } from '../objects/player-character-physical'; +import { CharacterPhysical } from '../objects/character-physical'; import { PlanetPhysical } from '../objects/planet-physical'; import { Physical } from '../physics/physicals/physical'; @@ -98,22 +98,18 @@ export class NPC extends PlayerBase { private findNearCharactersSorted( nearObjects: Array, - ): Array<{ character: PlayerCharacterPhysical; distance: number }> { + ): Array<{ character: CharacterPhysical; distance: number }> { const characters = Array.from( new Set( nearObjects.filter( (o) => - o.gameObject instanceof PlayerCharacterPhysical && - o.gameObject !== this.character, + o.gameObject instanceof CharacterPhysical && o.gameObject !== this.character, ), ), ).map((c) => ({ character: c.gameObject, - distance: vec2.distance( - this.center, - (c.gameObject as PlayerCharacterPhysical).center, - ), - })) as Array<{ character: PlayerCharacterPhysical; distance: number }>; + distance: vec2.distance(this.center, (c.gameObject as CharacterPhysical).center), + })) as Array<{ character: CharacterPhysical; distance: number }>; characters.sort((a, b) => a.distance - b.distance); @@ -139,12 +135,10 @@ export class NPC extends PlayerBase { const nearObjects = this.objectContainer.findIntersecting(observableArea); const enemies = nearObjects.filter( - (o) => - o.gameObject instanceof PlayerCharacterPhysical && - o.gameObject.team !== this.team, + (o) => o.gameObject instanceof CharacterPhysical && o.gameObject.team !== this.team, ); if (enemies.length > 0) { - return (enemies[0].gameObject as PlayerCharacterPhysical).center; + return (enemies[0].gameObject as CharacterPhysical).center; } } diff --git a/backend/src/players/player-base.ts b/backend/src/players/player-base.ts index 10b9450..ff235cb 100644 --- a/backend/src/players/player-base.ts +++ b/backend/src/players/player-base.ts @@ -3,11 +3,11 @@ import { CommandReceiver, Circle, PlayerInformation, CharacterTeam } from 'share import { PhysicalContainer } from '../physics/containers/physical-container'; import { getBoundingBoxOfCircle } from '../physics/functions/get-bounding-box-of-circle'; import { isCircleIntersecting } from '../physics/functions/is-circle-intersecting'; -import { PlayerCharacterPhysical } from '../objects/player-character-physical'; +import { CharacterPhysical } from '../objects/character-physical'; import { PlayerContainer } from './player-container'; export abstract class PlayerBase extends CommandReceiver { - public character?: PlayerCharacterPhysical | null; + public character?: CharacterPhysical | null; public center: vec2 = vec2.create(); protected sumKills = 0; @@ -23,7 +23,7 @@ export abstract class PlayerBase extends CommandReceiver { } protected createCharacter(preferredCenter: vec2) { - this.character = new PlayerCharacterPhysical( + this.character = new CharacterPhysical( this.playerInfo.name.slice(0, 20), this.sumKills, this.sumDeaths, @@ -52,7 +52,7 @@ export abstract class PlayerBase extends CommandReceiver { const playerBoundingCircle = new Circle( playerPosition, - PlayerCharacterPhysical.boundRadius, + CharacterPhysical.boundRadius, ); const playerBoundingBox = getBoundingBoxOfCircle(playerBoundingCircle); @@ -69,6 +69,6 @@ export abstract class PlayerBase extends CommandReceiver { } public destroy() { - this.character?.kill(); + this.character?.onDie(); } } diff --git a/backend/src/players/player.ts b/backend/src/players/player.ts index 6ed519d..06123b8 100644 --- a/backend/src/players/player.ts +++ b/backend/src/players/player.ts @@ -9,7 +9,6 @@ import { TransportEvents, SetAspectRatioActionCommand, calculateViewArea, - SecondaryActionCommand, settings, PlayerInformation, CharacterTeam, @@ -26,18 +25,15 @@ import { } from 'shared'; import { BoundingBox } from '../physics/bounding-boxes/bounding-box'; import { PhysicalContainer } from '../physics/containers/physical-container'; -import { PlayerCharacterPhysical } from '../objects/player-character-physical'; +import { CharacterPhysical } from '../objects/character-physical'; import { PlayerContainer } from './player-container'; import { PlayerBase } from './player-base'; -import { DeltaTimeCalculator } from '../helper/delta-time-calculator'; export class Player extends PlayerBase { + // default, until the clients sends its real value private aspectRatio: number = 16 / 9; - private isActive = true; private objectsPreviouslyInViewArea: Array = []; - private pingDeltaTime = new DeltaTimeCalculator(); - private _latency?: number; protected commandExecutors: CommandExecutors = { [SetAspectRatioActionCommand.type]: (v: SetAspectRatioActionCommand) => @@ -57,31 +53,10 @@ export class Player extends PlayerBase { private readonly socket: SocketIO.Socket, ) { super(playerInfo, playerContainer, objectContainer, team); - this.createCharacter(); - - socket.on( - TransportEvents.Pong, - () => (this._latency = this.pingDeltaTime.getNextDeltaTimeInSeconds()), - ); - - this.measureLatency(); this.step(0); } - public measureLatency() { - this.pingDeltaTime.getNextDeltaTimeInSeconds(true); - this.socket.emit(TransportEvents.Ping); - - if (this.isActive) { - setTimeout(this.measureLatency.bind(this), 10000); - } - } - - public get latency(): number | undefined { - return this._latency; - } - protected createCharacter() { const preferredCenter = this.playerContainer.players.find( (p) => p.character?.isAlive && p.team === this.team, @@ -191,7 +166,7 @@ export class Player extends PlayerBase { const playersInViewArea = this.objectContainer .findIntersecting(bb) .map((o) => o.gameObject) - .filter((g) => g instanceof PlayerCharacterPhysical); + .filter((g) => g instanceof CharacterPhysical); const otherPlayers = this.playerContainer.players.filter( (p) => p.character?.isAlive && playersInViewArea.indexOf(p.character!) < 0, @@ -222,6 +197,5 @@ export class Player extends PlayerBase { public destroy() { super.destroy(); - this.isActive = false; } } diff --git a/frontend/src/index.html b/frontend/src/index.html index a5a0983..6e17324 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -48,11 +48,11 @@ minlength="1" maxlength="20" placeholder=" " - id="playerName" - name="playerName" + id="name" + name="name" type="text" /> - +
diff --git a/frontend/src/index.ts b/frontend/src/index.ts index 52661bb..ae09b97 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -3,7 +3,7 @@ import { LampBase, overrideDeserialization, PlanetBase, - PlayerCharacterBase, + CharacterBase, ProjectileBase, } from 'shared'; import { LampView } from './scripts/objects/lamp-view'; @@ -17,9 +17,9 @@ import '../static/favicons/favicon-32x32.png'; import '../static/favicons/favicon.ico'; import { LandingPageBackground } from './scripts/landing-page-background'; import { JoinFormHandler } from './scripts/join-form-handler'; -import { handleFullScreen } from './scripts/handle-full-screen'; +import { handleFullScreen } from './scripts/helper/handle-full-screen'; import { Game } from './scripts/game'; -import { PlayerCharacterView } from './scripts/objects/player-character-view'; +import { CharacterView } from './scripts/objects/character-view'; import { handleInsights } from './scripts/handle-insights'; import { getInsightsFromRenderer } from './scripts/get-insights-from-renderer'; import { Renderer } from 'sdf-2d'; @@ -32,12 +32,13 @@ import { VibrationHandler } from './scripts/vibration-handler'; glMatrix.setMatrixArrayType(Array); -overrideDeserialization(PlayerCharacterBase, PlayerCharacterView); +overrideDeserialization(CharacterBase, CharacterView); overrideDeserialization(PlanetBase, PlanetView); overrideDeserialization(LampBase, LampView); overrideDeserialization(ProjectileBase, ProjectileView); const landingUI = document.querySelector('#landing-ui') as HTMLElement; +const nameInput = document.querySelector('#name') as HTMLInputElement; const joinGameForm = document.querySelector('#join-game-form') as HTMLFormElement; const serverContainer = document.querySelector('#server-container') as HTMLElement; const canvas = document.querySelector('canvas') as HTMLCanvasElement; @@ -114,6 +115,11 @@ const main = async () => { try { let game: Game; + const storedUserName = localStorage?.getItem('userName'); + if (storedUserName) { + nameInput.value = JSON.parse(storedUserName); + } + const firstClickListener = () => { SoundHandler.initialize( () => { @@ -166,6 +172,9 @@ const main = async () => { hide(spinner); const playerDecision = await joinHandler.getPlayerDecision(); + + localStorage?.setItem('userName', JSON.stringify(playerDecision.name)); + if (!history.state) { history.pushState(true, ''); } diff --git a/frontend/src/scripts/commands/mouse-listener.ts b/frontend/src/scripts/commands/mouse-listener.ts index cf8b69e..4c73a9c 100644 --- a/frontend/src/scripts/commands/mouse-listener.ts +++ b/frontend/src/scripts/commands/mouse-listener.ts @@ -3,11 +3,11 @@ import { CommandGenerator, PrimaryActionCommand, SecondaryActionCommand } from ' import { Game } from '../game'; export class MouseListener extends CommandGenerator { - constructor(private readonly game: Game) { + constructor(private target: HTMLElement, private readonly game: Game) { super(); - addEventListener('mousedown', this.mouseDownListener); - addEventListener('contextmenu', this.contextMenuListener); + target.addEventListener('mousedown', this.mouseDownListener); + target.addEventListener('contextmenu', this.contextMenuListener); } private mouseDownListener = (event: MouseEvent) => { @@ -32,7 +32,7 @@ export class MouseListener extends CommandGenerator { } public destroy() { - removeEventListener('mousedown', this.mouseDownListener); - removeEventListener('contextmenu', this.contextMenuListener); + this.target.removeEventListener('mousedown', this.mouseDownListener); + this.target.removeEventListener('contextmenu', this.contextMenuListener); } } diff --git a/frontend/src/scripts/game.ts b/frontend/src/scripts/game.ts index 7ec4d00..3d80d94 100644 --- a/frontend/src/scripts/game.ts +++ b/frontend/src/scripts/game.ts @@ -1,5 +1,12 @@ import { vec2 } from 'gl-matrix'; -import { Renderer, renderNoise } from 'sdf-2d'; +import { + CircleLight, + FilteringOptions, + Renderer, + renderNoise, + runAnimation, + WrapOptions, +} from 'sdf-2d'; import { deserialize, TransportEvents, @@ -9,22 +16,23 @@ import { clamp, UpdateGameState, GameEndCommand, - CharacterTeam, ServerAnnouncement, GameStartCommand, CommandReceiver, CommandExecutors, Command, + settings, } from 'shared'; import io from 'socket.io-client'; import { KeyboardListener } from './commands/keyboard-listener'; import { MouseListener } from './commands/mouse-listener'; import { TouchListener } from './commands/touch-listener'; import { CommandSocket } from './commands/command-socket'; -import { startAnimation } from './start-animation'; import { PlayerDecision } from './join-form-handler'; import { GameObjectContainer } from './objects/game-object-container'; import parser from 'socket.io-msgpack-parser'; +import { BlobShape } from './shapes/blob-shape'; +import { PlanetShape } from './shapes/planet-shape'; export class Game extends CommandReceiver { public gameObjects = new GameObjectContainer(this); @@ -59,8 +67,8 @@ export class Game extends CommandReceiver { this.progressBar.appendChild(this.redPlanetCountElement); this.keyboardListener = new KeyboardListener(); - this.mouseListener = new MouseListener(this); - this.touchListener = new TouchListener(this.overlay, this.overlay, this); + this.mouseListener = new MouseListener(this.canvas, this); + this.touchListener = new TouchListener(this.canvas, this.overlay, this); } private initialize() { @@ -111,9 +119,7 @@ export class Game extends CommandReceiver { this.isBetweenGames = false; - this.socket.emit(TransportEvents.PlayerJoining, { - name: this.playerDecision.playerName, - } as PlayerInformation); + this.socket.emit(TransportEvents.PlayerJoining, this.playerDecision); } protected defaultCommandExecutor(c: Command) { @@ -200,7 +206,35 @@ export class Game extends CommandReceiver { this.initialize(); - await startAnimation(this.canvas, this.gameLoop.bind(this), noiseTexture); + await runAnimation( + this.canvas, + [ + PlanetShape.descriptor, + BlobShape.descriptor, + { + ...CircleLight.descriptor, + shaderCombinationSteps: [0, 1, 2, 4, 8, 16], + }, + ], + this.gameLoop.bind(this), + { + shadowTraceCount: 16, + paletteSize: settings.palette.length, + colorPalette: settings.palette, + enableHighDpiRendering: true, + lightCutoffDistance: settings.lightCutoffDistance, + textures: { + noiseTexture: { + source: noiseTexture, + overrides: { + maxFilter: FilteringOptions.LINEAR, + wrapS: WrapOptions.MIRRORED_REPEAT, + wrapT: WrapOptions.MIRRORED_REPEAT, + }, + }, + }, + }, + ); this.socket.close(); this.overlay.innerHTML = ''; this.keyboardListener.destroy(); diff --git a/frontend/src/scripts/handle-full-screen.ts b/frontend/src/scripts/helper/handle-full-screen.ts similarity index 95% rename from frontend/src/scripts/handle-full-screen.ts rename to frontend/src/scripts/helper/handle-full-screen.ts index 66b6122..e5f7873 100644 --- a/frontend/src/scripts/handle-full-screen.ts +++ b/frontend/src/scripts/helper/handle-full-screen.ts @@ -1,4 +1,4 @@ -import { SoundHandler, Sounds } from './sound-handler'; +import { SoundHandler, Sounds } from '../sound-handler'; export const handleFullScreen = ( minimizeButton: HTMLElement, diff --git a/frontend/src/scripts/join-form-handler.ts b/frontend/src/scripts/join-form-handler.ts index 0ac28b9..70874b9 100644 --- a/frontend/src/scripts/join-form-handler.ts +++ b/frontend/src/scripts/join-form-handler.ts @@ -5,7 +5,7 @@ import parser from 'socket.io-msgpack-parser'; import { SoundHandler, Sounds } from './sound-handler'; export type PlayerDecision = { - playerName: string; + name: string; server: string; }; diff --git a/frontend/src/scripts/landing-page-background.ts b/frontend/src/scripts/landing-page-background.ts index c211b4a..0e2be9a 100644 --- a/frontend/src/scripts/landing-page-background.ts +++ b/frontend/src/scripts/landing-page-background.ts @@ -1,7 +1,6 @@ import { vec2 } from 'gl-matrix'; import { CircleLight, - compile, FilteringOptions, hsl, NoisyPolygonFactory, diff --git a/frontend/src/scripts/objects/player-character-view.ts b/frontend/src/scripts/objects/character-view.ts similarity index 97% rename from frontend/src/scripts/objects/player-character-view.ts rename to frontend/src/scripts/objects/character-view.ts index f257f1e..5902969 100644 --- a/frontend/src/scripts/objects/player-character-view.ts +++ b/frontend/src/scripts/objects/character-view.ts @@ -3,7 +3,7 @@ import { Renderer } from 'sdf-2d'; import { Circle, Id, - PlayerCharacterBase, + CharacterBase, CharacterTeam, settings, UpdateProperty, @@ -14,7 +14,7 @@ import { SoundHandler, Sounds } from '../sound-handler'; import { VibrationHandler } from '../vibration-handler'; import { ViewObject } from './view-object'; -export class PlayerCharacterView extends PlayerCharacterBase implements ViewObject { +export class CharacterView extends CharacterBase implements ViewObject { private shape: BlobShape; private nameElement: HTMLElement = document.createElement('div'); private statsElement: HTMLElement = document.createElement('div'); @@ -81,7 +81,7 @@ export class PlayerCharacterView extends PlayerCharacterBase implements ViewObje } } - public kill() { + public onDie() { if (this.isMainCharacter) { VibrationHandler.vibrate(150); } diff --git a/frontend/src/scripts/objects/game-object-container.ts b/frontend/src/scripts/objects/game-object-container.ts index b4875c6..562aee3 100644 --- a/frontend/src/scripts/objects/game-object-container.ts +++ b/frontend/src/scripts/objects/game-object-container.ts @@ -11,12 +11,12 @@ import { } from 'shared'; import { Game } from '../game'; import { Camera } from './camera'; -import { PlayerCharacterView } from './player-character-view'; +import { CharacterView } from './character-view'; import { ViewObject } from './view-object'; export class GameObjectContainer extends CommandReceiver { protected objects: Map = new Map(); - public player!: PlayerCharacterView; + public player!: CharacterView; public camera!: Camera; protected commandExecutors: CommandExecutors = { @@ -25,7 +25,7 @@ export class GameObjectContainer extends CommandReceiver { this.deleteObject(this.camera.id); } - this.player = c.character as PlayerCharacterView; + this.player = c.character as CharacterView; this.player.isMainCharacter = true; this.camera = new Camera(this.game); diff --git a/frontend/src/scripts/start-animation.ts b/frontend/src/scripts/start-animation.ts deleted file mode 100644 index 2b50303..0000000 --- a/frontend/src/scripts/start-animation.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - CircleLight, - FilteringOptions, - Renderer, - runAnimation, - WrapOptions, -} from 'sdf-2d'; -import { settings } from 'shared'; -import { BlobShape } from './shapes/blob-shape'; -import { PlanetShape } from './shapes/planet-shape'; - -export const startAnimation = async ( - canvas: HTMLCanvasElement, - draw: (r: Renderer, current: number, delta: number) => boolean, - noiseTexture: TexImageSource, -): Promise => - await runAnimation( - canvas, - [ - PlanetShape.descriptor, - BlobShape.descriptor, - { - ...CircleLight.descriptor, - shaderCombinationSteps: [0, 1, 2, 4, 8, 16], - }, - ], - draw, - { - shadowTraceCount: 16, - paletteSize: settings.palette.length, - colorPalette: settings.palette, - enableHighDpiRendering: true, - lightCutoffDistance: settings.lightCutoffDistance, - textures: { - noiseTexture: { - source: noiseTexture, - overrides: { - maxFilter: FilteringOptions.LINEAR, - wrapS: WrapOptions.MIRRORED_REPEAT, - wrapT: WrapOptions.MIRRORED_REPEAT, - }, - }, - }, - }, - ); diff --git a/shared/src/commands/types/create-player.ts b/shared/src/commands/types/create-player.ts index bd3694c..35ff556 100644 --- a/shared/src/commands/types/create-player.ts +++ b/shared/src/commands/types/create-player.ts @@ -1,10 +1,10 @@ -import { PlayerCharacterBase } from '../../objects/types/player-character-base'; +import { CharacterBase } from '../../objects/types/character-base'; import { serializable } from '../../serialization/serializable'; import { Command } from '../command'; @serializable export class CreatePlayerCommand extends Command { - public constructor(public readonly character: PlayerCharacterBase) { + public constructor(public readonly character: CharacterBase) { super(); } diff --git a/shared/src/commands/types/game-end.ts b/shared/src/commands/types/game-end.ts index ba8c732..32bb84c 100644 --- a/shared/src/commands/types/game-end.ts +++ b/shared/src/commands/types/game-end.ts @@ -1,4 +1,4 @@ -import { CharacterTeam } from '../../objects/types/character-team'; +import { CharacterTeam } from '../../objects/types/character-base'; import { serializable } from '../../serialization/serializable'; import { Command } from '../command'; diff --git a/shared/src/commands/types/update-other-player-directions.ts b/shared/src/commands/types/update-other-player-directions.ts index 0afe481..a0d3223 100644 --- a/shared/src/commands/types/update-other-player-directions.ts +++ b/shared/src/commands/types/update-other-player-directions.ts @@ -1,6 +1,6 @@ import { vec2 } from 'gl-matrix'; import { Id } from '../../communication/id'; -import { CharacterTeam } from '../../objects/types/character-team'; +import { CharacterTeam } from '../../objects/types/character-base'; import { serializable } from '../../serialization/serializable'; import { Command } from '../command'; diff --git a/shared/src/helper/circle.ts b/shared/src/helper/circle.ts index 466bf8d..2663250 100644 --- a/shared/src/helper/circle.ts +++ b/shared/src/helper/circle.ts @@ -9,10 +9,6 @@ export class Circle { return vec2.distance(this.center, target) - this.radius; } - public distanceBetween(target: Circle): number { - return vec2.distance(target.center, this.center) - this.radius - target.radius; - } - public toArray(): Array { return [this.center, this.radius]; } diff --git a/shared/src/main.ts b/shared/src/main.ts index c525200..bc8cdec 100644 --- a/shared/src/main.ts +++ b/shared/src/main.ts @@ -40,8 +40,7 @@ export * from './serialization/serialize'; export * from './serialization/serializes-to'; export * from './serialization/serializable'; export * from './serialization/override-deserialization'; -export * from './objects/types/character-team'; -export * from './objects/types/player-character-base'; +export * from './objects/types/character-base'; export * from './objects/types/lamp-base'; export * from './objects/types/planet-base'; export * from './objects/types/projectile-base'; diff --git a/shared/src/objects/types/player-character-base.ts b/shared/src/objects/types/character-base.ts similarity index 85% rename from shared/src/objects/types/player-character-base.ts rename to shared/src/objects/types/character-base.ts index 0872bb3..c8dae73 100644 --- a/shared/src/objects/types/player-character-base.ts +++ b/shared/src/objects/types/character-base.ts @@ -2,10 +2,15 @@ import { Id } from '../../communication/id'; import { Circle } from '../../helper/circle'; import { serializable } from '../../serialization/serializable'; import { GameObject } from '../game-object'; -import { CharacterTeam } from './character-team'; + +export enum CharacterTeam { + decla = 'decla', + neutral = 'neutral', + red = 'red', +} @serializable -export class PlayerCharacterBase extends GameObject { +export class CharacterBase extends GameObject { constructor( id: Id, public name: string, @@ -26,7 +31,7 @@ export class PlayerCharacterBase extends GameObject { this.health = health; } - public kill() {} + public onDie() {} public setKillCount(killCount: number) { this.killCount = killCount; diff --git a/shared/src/objects/types/character-team.ts b/shared/src/objects/types/character-team.ts deleted file mode 100644 index 8550036..0000000 --- a/shared/src/objects/types/character-team.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum CharacterTeam { - decla = 'decla', - neutral = 'neutral', - red = 'red', -} diff --git a/shared/src/objects/types/projectile-base.ts b/shared/src/objects/types/projectile-base.ts index 07036c9..c334cb8 100644 --- a/shared/src/objects/types/projectile-base.ts +++ b/shared/src/objects/types/projectile-base.ts @@ -2,8 +2,8 @@ import { vec2 } from 'gl-matrix'; import { settings } from '../../settings'; import { serializable } from '../../serialization/serializable'; import { GameObject } from '../game-object'; -import { CharacterTeam } from './character-team'; import { Id } from '../../communication/id'; +import { CharacterTeam } from './character-base'; @serializable export class ProjectileBase extends GameObject { diff --git a/shared/src/settings.ts b/shared/src/settings.ts index efbf51d..e451ed3 100644 --- a/shared/src/settings.ts +++ b/shared/src/settings.ts @@ -1,5 +1,5 @@ import { rgb255 } from './helper/rgb255'; -import { CharacterTeam } from './objects/types/character-team'; +import { CharacterTeam } from './objects/types/character-base'; const declaColor = rgb255(64, 105, 165); const neutralColor = rgb255(82, 165, 64); @@ -19,6 +19,7 @@ export const settings = { worldRadius: 10000, objectsOnCircleLength: 0.002, planetEdgeCount: 7, + playerKillPoint: 10, takeControlTimeInSeconds: 4, loseControlTimeInSeconds: 24, planetPointGenerationInterval: 1.5,