summaryrefslogtreecommitdiff
path: root/engine/entities
diff options
context:
space:
mode:
Diffstat (limited to 'engine/entities')
-rw-r--r--engine/entities/Entity.ts46
-rw-r--r--engine/entities/Floor.ts41
-rw-r--r--engine/entities/Player.ts67
-rw-r--r--engine/entities/index.ts7
-rw-r--r--engine/entities/names.ts4
5 files changed, 125 insertions, 40 deletions
diff --git a/engine/entities/Entity.ts b/engine/entities/Entity.ts
index ca8d314..63fb370 100644
--- a/engine/entities/Entity.ts
+++ b/engine/entities/Entity.ts
@@ -1,13 +1,17 @@
-import type { Component } from "../components";
+import { EntityNames, Floor, Player } from '.';
+import { type Component } from '../components';
-export abstract class Entity {
- private static ID = 0;
+const randomId = () =>
+ (performance.now() + Math.random() * 10_000_000).toString();
- public readonly id: number;
- public readonly components: Map<string, Component>;
+export abstract class Entity {
+ public id: string;
+ public components: Map<string, Component>;
+ public name: string;
- constructor() {
- this.id = Entity.ID++;
+ constructor(name: string, id: string = randomId()) {
+ this.name = name;
+ this.id = id;
this.components = new Map();
}
@@ -17,7 +21,7 @@ export abstract class Entity {
public getComponent<T extends Component>(name: string): T {
if (!this.hasComponent(name)) {
- throw new Error("Entity does not have component " + name);
+ throw new Error('Entity does not have component ' + name);
}
return this.components.get(name) as T;
}
@@ -29,4 +33,30 @@ export abstract class Entity {
public hasComponent(name: string): boolean {
return this.components.has(name);
}
+
+ public static from(entityName: string, id: string, args: any): Entity {
+ let entity: Entity;
+
+ switch (entityName) {
+ case EntityNames.Player:
+ const player = new Player();
+ player.setFrom(args);
+ entity = player;
+ break;
+ case EntityNames.Floor:
+ const floor = new Floor(args.floorWidth);
+ floor.setFrom(args);
+ entity = floor;
+ break;
+ default:
+ throw new Error('.from() Entity type not implemented: ' + entityName);
+ }
+
+ entity.id = id;
+ return entity;
+ }
+
+ public abstract setFrom(args: Record<string, any>): void;
+
+ public abstract serialize(): Record<string, any>;
}
diff --git a/engine/entities/Floor.ts b/engine/entities/Floor.ts
index 44587e6..b4f48e5 100644
--- a/engine/entities/Floor.ts
+++ b/engine/entities/Floor.ts
@@ -1,15 +1,19 @@
-import { IMAGES, SPRITE_SPECS, Sprites, type SpriteSpec } from "../config";
-import { BoundingBox, Sprite } from "../components";
-import { TopCollidable } from "../components/TopCollidable";
-import { Entity } from "../entities";
+import { IMAGES, SPRITE_SPECS, Sprites, type SpriteSpec } from '../config';
+import { BoundingBox, ComponentNames, Sprite } from '../components';
+import { TopCollidable } from '../components/TopCollidable';
+import { Entity, EntityNames } from '../entities';
export class Floor extends Entity {
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
- Sprites.FLOOR,
+ Sprites.FLOOR
) as SpriteSpec;
+ private width: number;
+
constructor(width: number) {
- super();
+ super(EntityNames.Floor);
+
+ this.width = width;
this.addComponent(
new Sprite(
@@ -17,17 +21,28 @@ export class Floor extends Entity {
{ x: 0, y: 0 },
{ width, height: Floor.spriteSpec.height },
Floor.spriteSpec.msPerFrame,
- Floor.spriteSpec.frames,
- ),
+ Floor.spriteSpec.frames
+ )
);
+ this.addComponent(new TopCollidable());
+ }
+
+ public serialize() {
+ return {
+ floorWidth: this.width,
+ boundingBox: this.getComponent<BoundingBox>(ComponentNames.BoundingBox)
+ };
+ }
+
+ public setFrom(args: any) {
+ const { boundingBox } = args;
this.addComponent(
new BoundingBox(
- { x: 300, y: 300 },
- { width, height: Floor.spriteSpec.height },
- ),
+ boundingBox.center,
+ boundingBox.dimension,
+ boundingBox.rotation
+ )
);
-
- this.addComponent(new TopCollidable());
}
}
diff --git a/engine/entities/Player.ts b/engine/entities/Player.ts
index 45d7500..4d91c6f 100644
--- a/engine/entities/Player.ts
+++ b/engine/entities/Player.ts
@@ -1,5 +1,5 @@
-import { Entity } from ".";
-import { IMAGES, SPRITE_SPECS, Sprites, type SpriteSpec } from "../config";
+import { Entity, EntityNames } from '.';
+import { IMAGES, SPRITE_SPECS, Sprites, type SpriteSpec } from '../config';
import {
Jump,
FacingDirection,
@@ -10,32 +10,38 @@ import {
WallBounded,
Forces,
Collide,
- Control,
Mass,
Moment,
-} from "../components";
-import { Direction } from "../interfaces";
+ ComponentNames,
+ Control
+} from '../components';
+import { Direction } from '../interfaces';
export class Player extends Entity {
private static MASS: number = 10;
- private static MOI: number = 1000;
+ private static MOI: number = 100;
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
- Sprites.COFFEE,
+ Sprites.COFFEE
) as SpriteSpec;
constructor() {
- super();
+ super(EntityNames.Player);
this.addComponent(
new BoundingBox(
- { x: 300, y: 100 },
+ {
+ x: 0,
+ y: 0
+ },
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
- 0,
- ),
+ 0
+ )
);
- this.addComponent(new Velocity({ dx: 0, dy: 0 }, 0));
+ this.addComponent(
+ new Velocity({ dCartesian: { dx: 0, dy: 0 }, dTheta: 0 })
+ );
this.addComponent(new Mass(Player.MASS));
this.addComponent(new Moment(Player.MOI));
@@ -43,7 +49,6 @@ export class Player extends Entity {
this.addComponent(new Gravity());
this.addComponent(new Jump());
- this.addComponent(new Control());
this.addComponent(new Collide());
this.addComponent(new WallBounded());
@@ -59,11 +64,41 @@ export class Player extends Entity {
{ x: 0, y: 0 },
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
Player.spriteSpec.msPerFrame,
- Player.spriteSpec.frames,
- ),
+ Player.spriteSpec.frames
+ )
);
this.addComponent(new FacingDirection(leftSprite, rightSprite));
- this.addComponent(leftSprite); // face Left by default
+ this.addComponent(leftSprite); // face left by default
+ }
+
+ public serialize(): Record<string, any> {
+ return {
+ control: this.getComponent<Control>(ComponentNames.Control),
+ boundingBox: this.getComponent<BoundingBox>(ComponentNames.BoundingBox),
+ velocity: this.getComponent<Velocity>(ComponentNames.Velocity),
+ forces: this.getComponent<Forces>(ComponentNames.Forces)
+ };
+ }
+
+ public setFrom(args: Record<string, any>) {
+ const { control, velocity, forces, boundingBox } = args;
+
+ let center = boundingBox.center;
+
+ const myCenter = this.getComponent<BoundingBox>(
+ ComponentNames.BoundingBox
+ ).center;
+ const distance = Math.sqrt(
+ Math.pow(center.y - myCenter.y, 2) + Math.pow(center.x - myCenter.x, 2)
+ );
+ if (distance < 30) center = myCenter;
+
+ [
+ Object.assign(new Control(control.controllableBy), control),
+ new Velocity(velocity.velocity),
+ new Forces(forces.forces),
+ new BoundingBox(center, boundingBox.dimension, boundingBox.rotation)
+ ].forEach((component) => this.addComponent(component));
}
}
diff --git a/engine/entities/index.ts b/engine/entities/index.ts
index a921512..8aee83c 100644
--- a/engine/entities/index.ts
+++ b/engine/entities/index.ts
@@ -1,3 +1,4 @@
-export * from "./Entity";
-export * from "./Floor";
-export * from "./Player";
+export * from './Entity';
+export * from './Floor';
+export * from './Player';
+export * from './names';
diff --git a/engine/entities/names.ts b/engine/entities/names.ts
new file mode 100644
index 0000000..cf65f9f
--- /dev/null
+++ b/engine/entities/names.ts
@@ -0,0 +1,4 @@
+export namespace EntityNames {
+ export const Player = 'Player';
+ export const Floor = 'Floor';
+}