Improve gameplay
This commit is contained in:
parent
e02a5b264c
commit
7c76b16d13
53 changed files with 1084 additions and 404 deletions
|
|
@ -14,13 +14,11 @@ export class Camera extends GameObject implements ViewObject {
|
|||
super(null);
|
||||
}
|
||||
|
||||
public update(updates: Array<UpdateMessage>) {
|
||||
throw new Error();
|
||||
}
|
||||
public beforeDestroy(): void {}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {}
|
||||
|
||||
public draw(renderer: Renderer) {
|
||||
public draw(renderer: Renderer, overlay: HTMLElement) {
|
||||
const canvasAspectRatio = renderer.canvasSize.x / renderer.canvasSize.y;
|
||||
if (canvasAspectRatio !== this.aspectRatio) {
|
||||
this.aspectRatio = canvasAspectRatio;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Renderer } from 'sdf-2d';
|
||||
import { CharacterBase, Circle, Id, UpdateMessage } from 'shared';
|
||||
import { CharacterBase, CharacterTeam, Circle, Id, UpdateMessage } from 'shared';
|
||||
|
||||
import { BlobShape } from '../shapes/blob-shape';
|
||||
import { ViewObject } from './view-object';
|
||||
|
|
@ -11,25 +11,25 @@ export class CharacterView extends CharacterBase implements ViewObject {
|
|||
constructor(
|
||||
id: Id,
|
||||
colorIndex: number,
|
||||
team: CharacterTeam,
|
||||
health: number,
|
||||
head?: Circle,
|
||||
leftFoot?: Circle,
|
||||
rightFoot?: Circle,
|
||||
) {
|
||||
super(id, colorIndex, head, leftFoot, rightFoot);
|
||||
super(id, colorIndex, team, health, head, leftFoot, rightFoot);
|
||||
this.shape = new BlobShape(colorIndex);
|
||||
}
|
||||
|
||||
public update(updates: Array<UpdateMessage>) {
|
||||
updates.forEach((u) => ((this as any)[u.key] = u.value));
|
||||
}
|
||||
|
||||
public get position(): vec2 {
|
||||
return this.head!.center;
|
||||
}
|
||||
|
||||
public beforeDestroy(): void {}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {}
|
||||
|
||||
public draw(renderer: Renderer): void {
|
||||
public draw(renderer: Renderer, overlay: HTMLElement): void {
|
||||
this.shape.setCircles([this.head!, this.leftFoot!, this.rightFoot!]);
|
||||
renderer.addDrawable(this.shape);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export class GameObjectContainer extends CommandReceiver {
|
|||
protected commandExecutors: CommandExecutors = {
|
||||
[CreatePlayerCommand.type]: (c: CreatePlayerCommand) => {
|
||||
this.player = c.character as PlayerCharacterView;
|
||||
console.log(c.character);
|
||||
this.camera = new Camera(this.game);
|
||||
this.addObject(this.player);
|
||||
this.addObject(this.camera);
|
||||
|
|
@ -31,7 +32,7 @@ export class GameObjectContainer extends CommandReceiver {
|
|||
c.objects.forEach((o) => this.addObject(o as ViewObject)),
|
||||
|
||||
[DeleteObjectsCommand.type]: (c: DeleteObjectsCommand) =>
|
||||
c.ids.forEach((id: Id) => this.objects.delete(id)),
|
||||
c.ids.forEach((id: Id) => this.deleteObject(id)),
|
||||
|
||||
[UpdateObjectsCommand.type]: (c: UpdateObjectsCommand) => {
|
||||
c.updates.forEach((u) => this.objects.get(u.id)?.update(u.updates));
|
||||
|
|
@ -50,11 +51,17 @@ export class GameObjectContainer extends CommandReceiver {
|
|||
this.objects.forEach((o) => o.step(delta));
|
||||
}
|
||||
|
||||
public drawObjects(renderer: Renderer) {
|
||||
this.objects.forEach((o) => o.draw(renderer));
|
||||
public drawObjects(renderer: Renderer, overlay: HTMLElement) {
|
||||
this.objects.forEach((o) => o.draw(renderer, overlay));
|
||||
}
|
||||
|
||||
private addObject(object: ViewObject) {
|
||||
this.objects.set(object.id, object);
|
||||
}
|
||||
|
||||
private deleteObject(id: Id) {
|
||||
const object = this.objects.get(id);
|
||||
object?.beforeDestroy();
|
||||
this.objects.delete(id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,11 @@ export class LampView extends LampBase implements ViewObject {
|
|||
this.light = new CircleLight(center, color, lightness);
|
||||
}
|
||||
|
||||
public update(message: Array<UpdateMessage>): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {}
|
||||
|
||||
public draw(renderer: Renderer): void {
|
||||
public beforeDestroy(): void {}
|
||||
|
||||
public draw(renderer: Renderer, overlay: HTMLElement): void {
|
||||
renderer.addDrawable(this.light);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,62 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Drawable, Renderer } from 'sdf-2d';
|
||||
import { CommandExecutors, Id, Random, PlanetBase, UpdateMessage } from 'shared';
|
||||
import {
|
||||
CommandExecutors,
|
||||
Id,
|
||||
Random,
|
||||
PlanetBase,
|
||||
UpdateMessage,
|
||||
settings,
|
||||
} from 'shared';
|
||||
import { RenderCommand } from '../commands/types/render';
|
||||
import { Polygon } from '../shapes/polygon';
|
||||
import { PlanetShape } from '../shapes/planet-shape';
|
||||
import { ViewObject } from './view-object';
|
||||
|
||||
export class PlanetView extends PlanetBase implements ViewObject {
|
||||
private shape: Drawable;
|
||||
private shape: PlanetShape;
|
||||
private ownershipProgess: HTMLElement;
|
||||
|
||||
protected commandExecutors: CommandExecutors = {
|
||||
[RenderCommand.type]: (c: RenderCommand) => c.renderer.addDrawable(this.shape),
|
||||
};
|
||||
|
||||
constructor(id: Id, vertices: Array<vec2>) {
|
||||
constructor(id: Id, vertices: Array<vec2>, ownership: number) {
|
||||
super(id, vertices);
|
||||
this.shape = new Polygon(vertices);
|
||||
this.shape = new PlanetShape(vertices, ownership);
|
||||
(this.shape as any).randomOffset = Random.getRandom();
|
||||
}
|
||||
|
||||
public update(message: Array<UpdateMessage>): void {
|
||||
throw new Error('Method not implemented.');
|
||||
this.ownershipProgess = document.createElement('div');
|
||||
this.ownershipProgess.className = 'ownership';
|
||||
}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {
|
||||
(this.shape as any).randomOffset += deltaTimeInMilliseconds / 4000;
|
||||
this.shape.randomOffset += deltaTimeInMilliseconds / 4000;
|
||||
this.shape.colorMixQ = this.ownership;
|
||||
let teamName = 'Neutral';
|
||||
if (this.ownership < 0.5 - settings.planetControlThreshold) {
|
||||
teamName = 'Decla';
|
||||
} else if (this.ownership > 0.5 + settings.planetControlThreshold) {
|
||||
teamName = 'Red';
|
||||
}
|
||||
|
||||
this.ownershipProgess.innerText = `${teamName} ${Math.round(
|
||||
(Math.abs(this.ownership - 0.5) / 0.5) * 100,
|
||||
)}%`;
|
||||
}
|
||||
|
||||
public draw(renderer: Renderer): void {
|
||||
public beforeDestroy(): void {
|
||||
this.ownershipProgess.parentElement?.removeChild(this.ownershipProgess);
|
||||
}
|
||||
|
||||
public draw(renderer: Renderer, overlay: HTMLElement): void {
|
||||
if (!this.ownershipProgess.parentElement) {
|
||||
overlay.appendChild(this.ownershipProgess);
|
||||
}
|
||||
|
||||
const screenPosition = renderer.worldToDisplayCoordinates(this.center);
|
||||
this.ownershipProgess.style.left = screenPosition.x + 'px';
|
||||
this.ownershipProgess.style.top = screenPosition.y + 'px';
|
||||
|
||||
renderer.addDrawable(this.shape);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +1,84 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Renderer } from 'sdf-2d';
|
||||
import { Circle, Id, PlayerCharacterBase, UpdateMessage } from 'shared';
|
||||
import { Circle, Id, PlayerCharacterBase, UpdateMessage, CharacterTeam } from 'shared';
|
||||
|
||||
import { BlobShape } from '../shapes/blob-shape';
|
||||
import { ViewObject } from './view-object';
|
||||
|
||||
export class PlayerCharacterView extends PlayerCharacterBase implements ViewObject {
|
||||
private shape: BlobShape;
|
||||
private nameElement: HTMLElement;
|
||||
private healthElement: HTMLElement;
|
||||
private timeSinceLastNameElementUpdate = 0;
|
||||
|
||||
constructor(
|
||||
id: Id,
|
||||
name: string,
|
||||
colorIndex: number,
|
||||
team: CharacterTeam,
|
||||
health: number,
|
||||
head?: Circle,
|
||||
leftFoot?: Circle,
|
||||
rightFoot?: Circle,
|
||||
) {
|
||||
super(id, name, colorIndex, head, leftFoot, rightFoot);
|
||||
super(id, name, colorIndex, team, health, head, leftFoot, rightFoot);
|
||||
this.shape = new BlobShape(colorIndex);
|
||||
}
|
||||
|
||||
public update(updates: Array<UpdateMessage>) {
|
||||
updates.forEach((u) => ((this as any)[u.key] = u.value));
|
||||
console.log(this.id, 'created');
|
||||
|
||||
this.nameElement = document.createElement('div');
|
||||
this.nameElement.className = 'player-tag';
|
||||
this.nameElement.innerText = this.name;
|
||||
this.healthElement = document.createElement('div');
|
||||
this.nameElement.appendChild(this.healthElement);
|
||||
}
|
||||
|
||||
public get position(): vec2 {
|
||||
return this.head!.center;
|
||||
}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {}
|
||||
public step(deltaTimeInMilliseconds: number): void {
|
||||
this.timeSinceLastNameElementUpdate += deltaTimeInMilliseconds;
|
||||
this.healthElement.style.width = this.health + '%';
|
||||
}
|
||||
|
||||
public beforeDestroy(): void {
|
||||
console.log(this.id, 'destroyes');
|
||||
this.nameElement.parentElement?.removeChild(this.nameElement);
|
||||
}
|
||||
|
||||
private elementAdded = false;
|
||||
public draw(renderer: Renderer, overlay: HTMLElement): void {
|
||||
if (!this.elementAdded) {
|
||||
this.elementAdded = true;
|
||||
console.log(this.id, 'add', this.nameElement, this.nameElement.parentElement);
|
||||
overlay.appendChild(this.nameElement);
|
||||
}
|
||||
|
||||
if (this.timeSinceLastNameElementUpdate > 0.15) {
|
||||
const screenPosition = renderer.worldToDisplayCoordinates(
|
||||
this.calculateTextPosition(),
|
||||
);
|
||||
this.nameElement.style.left = screenPosition.x + 'px';
|
||||
this.nameElement.style.top = screenPosition.y + 'px';
|
||||
this.timeSinceLastNameElementUpdate = 0;
|
||||
}
|
||||
|
||||
public draw(renderer: Renderer): void {
|
||||
this.shape.setCircles([this.head!, this.leftFoot!, this.rightFoot!]);
|
||||
renderer.addDrawable(this.shape);
|
||||
}
|
||||
|
||||
private calculateTextPosition(): vec2 {
|
||||
const footAverage = vec2.add(
|
||||
vec2.create(),
|
||||
this.leftFoot!.center,
|
||||
this.rightFoot!.center,
|
||||
);
|
||||
vec2.scale(footAverage, footAverage, 0.5);
|
||||
|
||||
const headFeetDelta = vec2.subtract(footAverage, this.head!.center, footAverage);
|
||||
vec2.normalize(headFeetDelta, headFeetDelta);
|
||||
const textOffset = vec2.scale(headFeetDelta, headFeetDelta, this.head!.radius + 50);
|
||||
return vec2.add(textOffset, this.head!.center, textOffset);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,33 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { CircleLight, Renderer } from 'sdf-2d';
|
||||
import { Id, ProjectileBase, rgb, UpdateMessage } from 'shared';
|
||||
import { CircleLight, ColorfulCircle, Renderer } from 'sdf-2d';
|
||||
import { Id, ProjectileBase, settings, UpdateMessage } from 'shared';
|
||||
import { ViewObject } from './view-object';
|
||||
import { Circle } from '../shapes/circle';
|
||||
|
||||
export class ProjectileView extends ProjectileBase implements ViewObject {
|
||||
private circle: InstanceType<typeof Circle>;
|
||||
private circle: ColorfulCircle;
|
||||
private light: CircleLight;
|
||||
|
||||
constructor(id: Id, center: vec2, radius: number) {
|
||||
super(id, center, radius);
|
||||
this.circle = new Circle(center, radius / 2);
|
||||
this.light = new CircleLight(center, rgb(1, 0.5, 0), 0.15);
|
||||
}
|
||||
|
||||
update(updates: Array<UpdateMessage>): void {
|
||||
updates.forEach((u) => ((this as any)[u.key] = u.value));
|
||||
constructor(
|
||||
id: Id,
|
||||
center: vec2,
|
||||
radius: number,
|
||||
colorIndex: number,
|
||||
strength: number,
|
||||
) {
|
||||
super(id, center, radius, colorIndex, strength);
|
||||
this.circle = new ColorfulCircle(center, radius / 2, colorIndex);
|
||||
this.light = new CircleLight(center, settings.palette[colorIndex], 0);
|
||||
}
|
||||
|
||||
public step(deltaTimeInMilliseconds: number): void {
|
||||
this.circle.center = this.center;
|
||||
this.light.center = this.center;
|
||||
this.light.intensity = (0.15 * this.strength) / settings.projectileMaxStrength;
|
||||
}
|
||||
|
||||
public draw(renderer: Renderer): void {
|
||||
public beforeDestroy(): void {}
|
||||
|
||||
public draw(renderer: Renderer, overlay: HTMLElement): void {
|
||||
renderer.addDrawable(this.circle);
|
||||
renderer.addDrawable(this.light);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Renderer } from 'sdf-2d';
|
|||
import { GameObject, UpdateMessage } from 'shared';
|
||||
|
||||
export interface ViewObject extends GameObject {
|
||||
update(updates: Array<UpdateMessage>): void;
|
||||
step(deltaTimeInMilliseconds: number): void;
|
||||
draw(renderer: Renderer): void;
|
||||
draw(renderer: Renderer, overlay: HTMLElement): void;
|
||||
beforeDestroy(): void;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue