-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplate.ts
81 lines (70 loc) · 2.83 KB
/
plate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import { defineSystem, EcsPlugin, on, startup, EcsComponent, EcsEvent, EntityId } from 'bim-ecs';
import { Config } from './config';
import { BoxGeometry } from './box-geometry';
import { pointerMoveEvent } from './inputs';
import { Name } from './common';
import { BallCollisionTrigger } from './ball-collision-trigger';
import { Velocity } from './velocity';
export const platePlugin: EcsPlugin = (world) => {
world.registerSystem(initializePlateSystem);
world.registerSystem(updatePlateSystem);
world.registerSystem(handlePlateCollisionSystem);
};
// Events
export const plateCollisionEvent = Symbol('plateCollisionEvent') as EcsEvent<{ obstacle: EntityId; ball: EntityId }>;
export class Plate extends EcsComponent {}
export const initializePlateSystem = defineSystem(
'Init plate',
({ entities, container }) => {
const config = container.resolve(Config);
entities.spawn(
new Plate(),
new Name('plate'),
new BoxGeometry({
x: config.width * 0.5,
y: config.height - config.plateHeight * 0.5,
height: config.plateHeight,
width: config.plateWidth,
}),
new BallCollisionTrigger(plateCollisionEvent),
);
},
startup,
);
export const updatePlateSystem = defineSystem(
'Update plate',
({ entities, container }, { payload }) => {
const plate = entities.query(() => [Plate, BoxGeometry]).next().value;
if (plate !== undefined) {
const config = container.resolve(Config);
const components = entities.componentsOf(plate);
const boxGeometry = components.get(BoxGeometry)! as BoxGeometry; // TODO: infer type
const limitLeft = boxGeometry.value.width * 0.5;
const limitRight = config.width - limitLeft;
boxGeometry.value = {
...boxGeometry.value,
x: Math.min(limitRight, Math.max(limitLeft, payload.scenePosition.x)),
};
}
},
on(pointerMoveEvent),
);
export const handlePlateCollisionSystem = defineSystem(
'Handle plate collision',
({ entities, container }, { payload: { ball, obstacle: plate } }) => {
const plateGeometry = entities.componentsOf(plate).get(BoxGeometry)?.value;
const ballComponents = entities.componentsOf(ball);
const ballGeometry = ballComponents.get(BoxGeometry)?.value;
const ballVelocity = ballComponents.get(Velocity)?.value;
if (plateGeometry && ballGeometry && ballVelocity) {
const config = container.resolve(Config);
// Calculate horizontal distance between centers
const distanceFromCenter = ballGeometry.x - plateGeometry.x;
// Normalize distance based on plate width
const normalizedDistance = (2 * distanceFromCenter) / plateGeometry.width;
// Updating velocity accordingly
ballVelocity.x += normalizedDistance * config.plateBallDeviationSensitivity; // Adjust deviationFactor as needed
}
},
on(plateCollisionEvent),
);