From 1691676fefe31cfbf2f4ec7fc48cb4a7e3a256b2 Mon Sep 17 00:00:00 2001 From: Zhiquan Yeo Date: Thu, 2 Jul 2020 11:49:30 -0400 Subject: [PATCH] Initial Zone implementation --- src/demos/demo1.ts | 10 +++ src/engine/Sim3D.ts | 6 ++ src/engine/handles/ZoneHandle.ts | 16 +++++ src/engine/objects/ObjectFactories.ts | 2 + src/engine/objects/Zone.ts | 98 +++++++++++++++++++++++++++ src/engine/specs/CoreSpecs.ts | 12 +++- 6 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/engine/handles/ZoneHandle.ts create mode 100644 src/engine/objects/Zone.ts diff --git a/src/demos/demo1.ts b/src/demos/demo1.ts index 3cfbff9..e60c9e7 100644 --- a/src/demos/demo1.ts +++ b/src/demos/demo1.ts @@ -221,6 +221,16 @@ function main() { }; const robot = simulator.addRobot(spec); + simulator.addZone({ + type: "zone", + initialPosition: { x: 0, y: 0 }, + baseColor: 0xff0000, + opacity: 0.4, + xLength: 2, + zLength: 1, + zoneId: "test-zone", + }); + enum RobotMode { LOOKING, RUN_AWAY, diff --git a/src/engine/Sim3D.ts b/src/engine/Sim3D.ts index 2f22b80..285d506 100644 --- a/src/engine/Sim3D.ts +++ b/src/engine/Sim3D.ts @@ -13,6 +13,7 @@ import { IWallSpec, IConeSpec, ICylinderSpec, + IZoneSpec, } from "./specs/CoreSpecs"; import { ObjectFactories } from "./objects/ObjectFactories"; import { BallHandle } from "./handles/BallHandle"; @@ -31,6 +32,7 @@ import { DEFAULT_WALL_THICKNESS, DEFAULT_WALL_HEIGHT } from "./objects/SimWall"; import { ObjectHandle } from "./handles/ObjectHandle"; import { CameraModeSpec, CameraMode } from "./specs/CameraSpecs"; import { CameraManager } from "./CameraManager"; +import { ZoneHandle } from "./handles/ZoneHandle"; interface ISimObjectContainer { type: string; @@ -271,6 +273,10 @@ export class Sim3D { this.handleRegistry.invalidateHandle(handle.ref.guid); } + addZone(spec: IZoneSpec): ZoneHandle { + return this.addGameObject(spec, ZoneHandle); + } + isDebugMode(): boolean { return this.debugMesh.visible; } diff --git a/src/engine/handles/ZoneHandle.ts b/src/engine/handles/ZoneHandle.ts new file mode 100644 index 0000000..0090259 --- /dev/null +++ b/src/engine/handles/ZoneHandle.ts @@ -0,0 +1,16 @@ +import { ObjectHandle } from "./ObjectHandle"; +import { Zone } from "../objects/Zone"; + +export class ZoneHandle extends ObjectHandle { + setColor(color: number): void { + this._rootObject.setColor(color); + } + + setOpacity(opacity: number): void { + this._rootObject.setOpacity(opacity); + } + + getZoneId(): string { + return this._rootObject.getZoneId(); + } +} diff --git a/src/engine/objects/ObjectFactories.ts b/src/engine/objects/ObjectFactories.ts index 2f40255..5fe47f3 100644 --- a/src/engine/objects/ObjectFactories.ts +++ b/src/engine/objects/ObjectFactories.ts @@ -8,6 +8,7 @@ import { makeSimWall } from "./SimWall"; import { makeSimPyramid } from "./SimPyramid"; import { makeSimCone } from "./SimCone"; import { makeSimCylinder } from "./SimCylinder"; +import { makeZone } from "./Zone"; export class ObjectFactories { private _factories: Map SimObject>; @@ -28,6 +29,7 @@ export class ObjectFactories { this.registerFactory("pyramid", makeSimPyramid); this.registerFactory("cone", makeSimCone); this.registerFactory("cylinder", makeSimCylinder); + this.registerFactory("zone", makeZone); } private registerFactory( diff --git a/src/engine/objects/Zone.ts b/src/engine/objects/Zone.ts new file mode 100644 index 0000000..a963e9b --- /dev/null +++ b/src/engine/objects/Zone.ts @@ -0,0 +1,98 @@ +import * as THREE from "three"; +import { BodyDef, FixtureDef, Vec2, Box } from "planck-js"; +import { IZoneSpec } from "../specs/CoreSpecs"; +import { SimObject } from "./SimObject"; +import { Vector2d } from "../SimTypes"; + +/** + * Factory method for creating a Zone + * @param spec + */ +export function makeZone(spec: IZoneSpec): Zone { + return new Zone(spec); +} + +export class Zone extends SimObject { + private _bodySpecs: BodyDef; + private _fixtureSpecs: FixtureDef; + + private _zoneId: string; + + constructor(spec: IZoneSpec) { + super("Zone"); + + this._zoneId = spec.zoneId; + + const initialPosition: Vector2d = { x: 0, y: 0 }; + + const materialSpecs: THREE.MeshBasicMaterialParameters = { + side: THREE.DoubleSide, + transparent: true, + }; + + if (spec.baseColor !== undefined) { + materialSpecs.color = spec.baseColor; + } + + if (spec.opacity !== undefined) { + materialSpecs.opacity = spec.opacity; + } + + if (spec.initialPosition) { + initialPosition.x = spec.initialPosition.x; + initialPosition.y = spec.initialPosition.y; + } + + const zoneGeom = new THREE.PlaneGeometry(spec.xLength, spec.zLength); + const zoneMaterial = new THREE.MeshBasicMaterial(materialSpecs); + const zoneMesh = new THREE.Mesh(zoneGeom, zoneMaterial); + + zoneMesh.position.y = 0; + zoneMesh.position.x = initialPosition.x; + zoneMesh.position.z = initialPosition.y; + + // Rotate along the x axis + zoneMesh.rotation.x = Math.PI / 2; + + this._mesh = zoneMesh; + + // Set up the physics body + this._bodySpecs = { + type: "static", + position: new Vec2(initialPosition.x, initialPosition.y), + angle: 0, + }; + + this._fixtureSpecs = { + shape: new Box(spec.xLength / 2, spec.zLength / 2), + isSensor: true, + }; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + update(ms: number): void { + const bodyCenter = this._body.getWorldCenter(); + this._mesh.position.x = bodyCenter.x; + this._mesh.position.z = bodyCenter.y; + } + + getBodySpecs(): BodyDef { + return this._bodySpecs; + } + + getFixtureDef(): FixtureDef { + return this._fixtureSpecs; + } + + setColor(color: number): void { + (this._mesh.material).color.set(color); + } + + setOpacity(opacity: number): void { + (this._mesh.material).opacity = opacity; + } + + getZoneId(): string { + return this._zoneId; + } +} diff --git a/src/engine/specs/CoreSpecs.ts b/src/engine/specs/CoreSpecs.ts index 37d6d5e..7f0c982 100644 --- a/src/engine/specs/CoreSpecs.ts +++ b/src/engine/specs/CoreSpecs.ts @@ -11,7 +11,8 @@ export type SimObjectSpec = | IWallSpec | IPyramidSpec | IConeSpec - | ICylinderSpec; + | ICylinderSpec + | IZoneSpec; export interface IPhysicsProperties { linearDamping?: number; @@ -105,3 +106,12 @@ export interface ICustomMeshSpec { rotation?: Vector3d; scale?: Vector3d; } + +// Zone +export interface IZoneSpec extends IBaseSimObjectSpec { + type: "zone"; + zoneId: string; + xLength: number; + zLength: number; + opacity?: number; +}