vertecs
Version:
A typescript entity-component-system framework
169 lines (154 loc) • 4.31 kB
text/typescript
import {
BoxGeometry,
Mesh,
MeshStandardMaterial,
PerspectiveCamera,
PointLight,
SphereGeometry,
} from "three";
import { quat } from "ts-gl-matrix";
import {
OimoComponent,
OimoSystem,
ThreeCamera,
ThreeLightComponent,
ThreeObject3D,
Transform,
} from "../../src";
import { initializeBoilerplate } from "./Boilerplate";
const ecsManager = await initializeBoilerplate();
const floor = ecsManager.createEntity();
floor.addComponent(new Transform([0, -5, 0]));
floor.addComponent(
new ThreeObject3D(
new Mesh(
new BoxGeometry(50, 10, 50),
new MeshStandardMaterial({ color: 0x808080 })
)
)
);
floor.addComponent(
new OimoComponent({
size: [50, 10, 50],
density: 1,
restitution: 0.5,
})
);
const camera = ecsManager.createEntity({ name: "camera" });
camera.addComponent(new Transform([40, 20, 0]));
const threeCameraComponent = new ThreeCamera(
new PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 200),
ecsManager.createEntity(),
undefined,
undefined,
true
);
camera.addComponent(threeCameraComponent);
const light = ecsManager.createEntity();
light.addComponent(new Transform([0, 50, 0]));
light.addComponent(
new ThreeLightComponent(new PointLight(0xffffff, 1, 200, 0))
);
const addTower = (towerOptions: {
radius: number;
detail: number;
mass: number;
brickThickness?: number;
brickHeight?: number;
towerHeight: number;
position: [number, number, number];
}) => {
if (towerOptions.radius > 45) return;
const detail = towerOptions.detail ?? 10;
const mass = towerOptions.mass ?? 1;
let px;
let py;
let pz;
let angle;
let rad;
const radius = towerOptions.radius ?? 1;
const height = towerOptions.towerHeight ?? 1;
const sx = towerOptions.brickThickness ?? 1;
const sy = towerOptions.brickHeight ?? 1;
const sz = (radius * 5) / detail;
for (let j = 0; j < height; j++) {
for (let i = 0; i < detail; i++) {
rad = radius;
// eslint-disable-next-line no-bitwise
angle = ((Math.PI * 2) / detail) * (i + (j & 1) * 0.5);
px = towerOptions.position[0] + Math.cos(angle) * rad;
py = towerOptions.position[1] + sy + j * sy - sy * 0.5;
pz = towerOptions.position[2] - Math.sin(angle) * rad;
const brick = ecsManager.createEntity();
brick.addComponent(
new Transform(
[px, py, pz],
quat.fromEuler(quat.create(), 0, angle * (180 / Math.PI), 0)
)
);
brick.addComponent(
new ThreeObject3D(
new Mesh(
new BoxGeometry(sx, sy, sz),
new MeshStandardMaterial({ color: 0x808080 })
)
)
);
brick.addComponent(
new OimoComponent({
type: "box",
move: true,
size: [sx, sy, sz],
density: mass,
restitution: 0.1,
})
);
}
}
};
addTower({
radius: 9,
towerHeight: 20,
detail: 15,
mass: 0.4,
position: [5, 0, 5],
});
const platform = ecsManager.createEntity();
platform.addComponent(
new Transform([-30, 10, 0], quat.fromEuler(quat.create(), 0, 0, 60))
);
platform.addComponent(
new ThreeObject3D(
new Mesh(
new BoxGeometry(2, 40, 50),
new MeshStandardMaterial({ color: 0x808080 })
)
)
);
platform.addComponent(
new OimoComponent({
size: [2, 40, 50],
density: 1,
restitution: 0.2,
})
);
const ball = ecsManager.createEntity();
ball.addComponent(new Transform([-45, 25, 0]));
ball.addComponent(
new ThreeObject3D(
new Mesh(
new SphereGeometry(2, 64, 64),
new MeshStandardMaterial({ color: 0x808080 })
)
)
);
ball.addComponent(
new OimoComponent({
type: "sphere",
move: true,
size: [2, 2, 2],
density: 0.6,
})
);
await ecsManager.addSystem(new OimoSystem());
await ecsManager.start();