Update gameplay
This commit is contained in:
parent
49c410d8ff
commit
23fa7646d6
10 changed files with 165 additions and 33 deletions
|
|
@ -17,10 +17,11 @@ import {
|
||||||
Circle,
|
Circle,
|
||||||
PlayerInformation,
|
PlayerInformation,
|
||||||
CharacterTeam,
|
CharacterTeam,
|
||||||
UpdatePlanetOwnershipCommand,
|
UpdateGameState,
|
||||||
GameObject,
|
GameObject,
|
||||||
Command,
|
Command,
|
||||||
UpdateObjectMessage,
|
UpdateObjectMessage,
|
||||||
|
OtherPlayerDirection,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
import { getTimeInMilliseconds } from '../helper/get-time-in-milliseconds';
|
import { getTimeInMilliseconds } from '../helper/get-time-in-milliseconds';
|
||||||
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
||||||
|
|
@ -189,10 +190,42 @@ export class Player extends CommandReceiver {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.sendToPlayer(
|
this.sendToPlayer(
|
||||||
new UpdatePlanetOwnershipCommand(
|
new UpdateGameState(
|
||||||
PlanetPhysical.declaPlanetCount,
|
PlanetPhysical.declaPlanetCount,
|
||||||
PlanetPhysical.redPlanetCount,
|
PlanetPhysical.redPlanetCount,
|
||||||
PlanetPhysical.neutralPlanetCount,
|
PlanetPhysical.neutralPlanetCount,
|
||||||
|
this.getOtherPlayers(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getOtherPlayers(): Array<OtherPlayerDirection> {
|
||||||
|
if (!this.character) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewArea = calculateViewArea(this.center, this.aspectRatio, 0.9);
|
||||||
|
const bb = new BoundingBox();
|
||||||
|
bb.topLeft = viewArea.topLeft;
|
||||||
|
bb.size = viewArea.size;
|
||||||
|
|
||||||
|
const playersInViewArea = this.objects
|
||||||
|
.findIntersecting(bb)
|
||||||
|
.map((o) => o.gameObject)
|
||||||
|
.filter((g) => g instanceof PlayerCharacterPhysical);
|
||||||
|
|
||||||
|
const otherPlayers = this.players.filter(
|
||||||
|
(p) => playersInViewArea.indexOf(p.character!) < 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
return otherPlayers.map(
|
||||||
|
(p) =>
|
||||||
|
new OtherPlayerDirection(
|
||||||
|
vec2.normalize(
|
||||||
|
vec2.create(),
|
||||||
|
vec2.subtract(vec2.create(), p.center, this.character!.center),
|
||||||
|
),
|
||||||
|
p.team,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,24 @@ body {
|
||||||
|
|
||||||
@include square(50px);
|
@include square(50px);
|
||||||
border-radius: 1000px;
|
border-radius: 1000px;
|
||||||
mask: url('../static/mask.svg');
|
mask-image: url('../static/mask.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-player-arrow {
|
||||||
|
@include square($large-icon);
|
||||||
|
@media (max-width: $breakpoint) {
|
||||||
|
@include square($small-icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
mask-image: url('../static/chevron.svg');
|
||||||
|
mask-size: contain;
|
||||||
|
|
||||||
|
&.decla {
|
||||||
|
background-color: $bright-decla;
|
||||||
|
}
|
||||||
|
&.red {
|
||||||
|
background-color: $bright-red;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.planet-progress {
|
.planet-progress {
|
||||||
|
|
@ -165,8 +182,10 @@ body {
|
||||||
height: $height;
|
height: $height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
border-radius: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
div:nth-child(1) {
|
div:nth-child(1) {
|
||||||
border-radius: 100px 0 0 100px;
|
|
||||||
background: $bright-decla;
|
background: $bright-decla;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,7 +194,6 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
div:nth-child(3) {
|
div:nth-child(3) {
|
||||||
border-radius: 0 100px 100px 0;
|
|
||||||
background: $bright-red;
|
background: $bright-red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ import {
|
||||||
SetAspectRatioActionCommand,
|
SetAspectRatioActionCommand,
|
||||||
PlayerInformation,
|
PlayerInformation,
|
||||||
PlayerDiedCommand,
|
PlayerDiedCommand,
|
||||||
UpdatePlanetOwnershipCommand,
|
UpdateGameState,
|
||||||
|
clamp,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
import io from 'socket.io-client';
|
import io from 'socket.io-client';
|
||||||
import { KeyboardListener } from './commands/generators/keyboard-listener';
|
import { KeyboardListener } from './commands/generators/keyboard-listener';
|
||||||
|
|
@ -54,6 +55,7 @@ export class Game {
|
||||||
progressBar.appendChild(this.redPlanetCountElement);
|
progressBar.appendChild(this.redPlanetCountElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private arrowElements: Array<HTMLElement> = [];
|
||||||
private async setupCommunication(serverUrl: string): Promise<void> {
|
private async setupCommunication(serverUrl: string): Promise<void> {
|
||||||
this.socket = io(serverUrl, {
|
this.socket = io(serverUrl, {
|
||||||
reconnectionDelayMax: 10000,
|
reconnectionDelayMax: 10000,
|
||||||
|
|
@ -74,7 +76,7 @@ export class Game {
|
||||||
navigator.vibrate(150);
|
navigator.vibrate(150);
|
||||||
}
|
}
|
||||||
this.overlay.appendChild(this.announcmentText);
|
this.overlay.appendChild(this.announcmentText);
|
||||||
} else if (command instanceof UpdatePlanetOwnershipCommand) {
|
} else if (command instanceof UpdateGameState) {
|
||||||
const all = command.declaCount + command.redCount + command.neutralCount;
|
const all = command.declaCount + command.redCount + command.neutralCount;
|
||||||
this.declaPlanetCountElement.style.width = (command.declaCount / all) * 100 + '%';
|
this.declaPlanetCountElement.style.width = (command.declaCount / all) * 100 + '%';
|
||||||
this.neutralPlanetCountElement.style.width =
|
this.neutralPlanetCountElement.style.width =
|
||||||
|
|
@ -90,6 +92,53 @@ export class Game {
|
||||||
this.overlay.appendChild(this.announcmentText);
|
this.overlay.appendChild(this.announcmentText);
|
||||||
this.announcmentText.innerText = 'Red team won 🎉';
|
this.announcmentText.innerText = 'Red team won 🎉';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.arrowElements
|
||||||
|
.splice(command.otherPlayerDirections.length, this.arrowElements.length)
|
||||||
|
.forEach((e) => e.parentElement?.removeChild(e));
|
||||||
|
|
||||||
|
for (
|
||||||
|
let i = this.arrowElements.length;
|
||||||
|
i < command.otherPlayerDirections.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
const element = document.createElement('div');
|
||||||
|
this.arrowElements.push(element);
|
||||||
|
this.overlay.appendChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arrowElements.forEach((e, i) => {
|
||||||
|
const direction = command.otherPlayerDirections[i].direction;
|
||||||
|
const team = command.otherPlayerDirections[i].team;
|
||||||
|
const angle = Math.atan2(direction.y, direction.x);
|
||||||
|
e.className = 'other-player-arrow ' + team;
|
||||||
|
|
||||||
|
const { width, height } = this.overlay.getBoundingClientRect();
|
||||||
|
const aspectRatio = width / height;
|
||||||
|
const directionRatio = direction.x / direction.y;
|
||||||
|
|
||||||
|
let deltaX: number, deltaY: number;
|
||||||
|
if (aspectRatio < Math.abs(directionRatio)) {
|
||||||
|
deltaX = (width / 2) * Math.sign(direction.x);
|
||||||
|
deltaY = deltaX / directionRatio;
|
||||||
|
} else {
|
||||||
|
deltaY = (height / 2) * Math.sign(direction.y);
|
||||||
|
deltaX = deltaY * directionRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
const delta = vec2.fromValues(deltaX, deltaY);
|
||||||
|
const center = vec2.fromValues(width / 2, height / 2);
|
||||||
|
const p = vec2.add(center, center, delta);
|
||||||
|
const arrowPadding = 16;
|
||||||
|
vec2.set(
|
||||||
|
p,
|
||||||
|
clamp(p.x, arrowPadding, width - 3 * arrowPadding),
|
||||||
|
clamp(height - p.y, arrowPadding, height - 3 * arrowPadding),
|
||||||
|
);
|
||||||
|
e.style.transform = `translateX(${p.x}px) translateY(${p.y}px) rotate(${
|
||||||
|
-angle + Math.PI / 2
|
||||||
|
}rad) translateX(-50%) translateY(-50%)`;
|
||||||
|
});
|
||||||
} else this.gameObjects.sendCommand(command);
|
} else this.gameObjects.sendCommand(command);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,18 @@ export class PlanetView extends PlanetBase implements ViewObject {
|
||||||
private getGradient(): string {
|
private getGradient(): string {
|
||||||
const sideDecla = this.ownership < 0.5;
|
const sideDecla = this.ownership < 0.5;
|
||||||
const sidePercent = (Math.abs(this.ownership - 0.5) / 0.5) * 100;
|
const sidePercent = (Math.abs(this.ownership - 0.5) / 0.5) * 100;
|
||||||
const color = sideDecla ? 'var(--bright-decla)' : 'var(--bright-red)';
|
return sideDecla
|
||||||
return `conic-gradient(
|
? `conic-gradient(
|
||||||
${color} ${sidePercent}%,
|
var(--bright-decla) ${sidePercent}%,
|
||||||
${color} ${sidePercent}%,
|
var(--bright-decla) ${sidePercent}%,
|
||||||
var(--bright-neutral) ${sidePercent}%,
|
var(--bright-neutral) ${sidePercent}%,
|
||||||
var(--bright-neutral) 100%
|
var(--bright-neutral) 100%
|
||||||
|
)`
|
||||||
|
: `conic-gradient(
|
||||||
|
var(--bright-neutral) 0%,
|
||||||
|
var(--bright-neutral) ${100 - sidePercent}%,
|
||||||
|
var(--bright-red) ${100 - sidePercent}%,
|
||||||
|
var(--bright-red) 100%
|
||||||
)`;
|
)`;
|
||||||
}
|
}
|
||||||
public beforeDestroy(): void {
|
public beforeDestroy(): void {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ export class BlobShape extends Drawable {
|
||||||
|
|
||||||
float blobSmoothMin(float a, float b)
|
float blobSmoothMin(float a, float b)
|
||||||
{
|
{
|
||||||
const float k = 300.0;
|
const highp float k = 300.0;
|
||||||
float res = exp2(-k * a) + exp2(-k * b);
|
highp float res = exp2(-k * a) + exp2(-k * b);
|
||||||
return -log2(res) / k;
|
return -log2(res) / k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,9 @@ export class PlanetShape extends PolygonFactory(settings.planetEdgeCount, 0) {
|
||||||
vec2 center = planetCenters[j];
|
vec2 center = planetCenters[j];
|
||||||
float l = planetLengths[j];
|
float l = planetLengths[j];
|
||||||
float randomOffset = planetRandoms[j];
|
float randomOffset = planetRandoms[j];
|
||||||
vec2 targetTangent = normalize(target - center);
|
vec2 targetCenterDelta = target - center;
|
||||||
|
float targetDistance = length(targetCenterDelta);
|
||||||
|
vec2 targetTangent = targetCenterDelta / clamp(targetDistance, 0.01, 1000.0);
|
||||||
vec2 noisyTarget = target - (
|
vec2 noisyTarget = target - (
|
||||||
targetTangent * planetTerrain(vec2(
|
targetTangent * planetTerrain(vec2(
|
||||||
l * abs(atan(targetTangent.y, targetTangent.x)),
|
l * abs(atan(targetTangent.y, targetTangent.x)),
|
||||||
|
|
|
||||||
4
frontend/static/chevron.svg
Normal file
4
frontend/static/chevron.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 24 24" stroke-width="1.5" stroke="#03A9F4" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||||
|
<polyline points="6 15 12 9 18 15" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 279 B |
37
shared/src/commands/types/update-game-state.ts
Normal file
37
shared/src/commands/types/update-game-state.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { CharacterTeam } from '../../objects/types/character-team';
|
||||||
|
import { serializable } from '../../transport/serialization/serializable';
|
||||||
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable
|
||||||
|
export class OtherPlayerDirection {
|
||||||
|
public constructor(
|
||||||
|
public readonly direction: vec2,
|
||||||
|
public readonly team: CharacterTeam,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
return [this.direction, this.team];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@serializable
|
||||||
|
export class UpdateGameState extends Command {
|
||||||
|
public constructor(
|
||||||
|
public readonly declaCount: number,
|
||||||
|
public readonly redCount: number,
|
||||||
|
public readonly neutralCount: number,
|
||||||
|
public readonly otherPlayerDirections: Array<OtherPlayerDirection>,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
return [
|
||||||
|
this.declaCount,
|
||||||
|
this.redCount,
|
||||||
|
this.neutralCount,
|
||||||
|
this.otherPlayerDirections,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import { serializable } from '../../transport/serialization/serializable';
|
|
||||||
import { Command } from '../command';
|
|
||||||
|
|
||||||
@serializable
|
|
||||||
export class UpdatePlanetOwnershipCommand extends Command {
|
|
||||||
public constructor(
|
|
||||||
public readonly declaCount: number,
|
|
||||||
public readonly redCount: number,
|
|
||||||
public readonly neutralCount: number,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public toArray(): Array<any> {
|
|
||||||
return [this.declaCount, this.redCount, this.neutralCount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,9 +7,10 @@ export * from './commands/types/move-action';
|
||||||
export * from './commands/types/primary-action';
|
export * from './commands/types/primary-action';
|
||||||
export * from './commands/types/player-died';
|
export * from './commands/types/player-died';
|
||||||
export * from './commands/types/update-objects';
|
export * from './commands/types/update-objects';
|
||||||
export * from './commands/types/update-planet-ownership';
|
export * from './commands/types/update-game-state';
|
||||||
export * from './commands/types/secondary-action';
|
export * from './commands/types/secondary-action';
|
||||||
export * from './commands/command-receiver';
|
export * from './commands/command-receiver';
|
||||||
|
export * from './commands/types/update-game-state';
|
||||||
export * from './commands/command-executors';
|
export * from './commands/command-executors';
|
||||||
export * from './commands/command-generator';
|
export * from './commands/command-generator';
|
||||||
export * from './commands/broadcast-commands';
|
export * from './commands/broadcast-commands';
|
||||||
|
|
@ -45,7 +46,6 @@ export * from './objects/types/player-character-base';
|
||||||
export * from './objects/types/lamp-base';
|
export * from './objects/types/lamp-base';
|
||||||
export * from './objects/types/planet-base';
|
export * from './objects/types/planet-base';
|
||||||
export * from './objects/types/projectile-base';
|
export * from './objects/types/projectile-base';
|
||||||
export * from './objects/update-message';
|
|
||||||
export * from './objects/update-object-message';
|
export * from './objects/update-object-message';
|
||||||
export * from './settings';
|
export * from './settings';
|
||||||
export * from './transport/transport-events';
|
export * from './transport/transport-events';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue