78d85c3799
-Add UI (Health bars, Resources UI, HUD Interface, Weapon U, Zoombie Invasion progress Indicator) -Refactor code structure for improved readability and maintainability
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { Physics_internal } from "@24tools/playable_template";
|
|
import { Box3, Object3D, Vector3 } from "three";
|
|
import { Body, Box, Quaternion, Sphere, Vec3 } from "cannon-es";
|
|
|
|
// Collision layers. Each body has a `group` (what it IS) and a `mask` (what it
|
|
// COLLIDES WITH); two bodies interact only if each one's group is in the other's
|
|
// mask. Values are bit flags so masks can be OR-combined (e.g. Wall | Trigger).
|
|
export enum PhysicsLayer {
|
|
Player = 1,
|
|
Wall = 2,
|
|
Trigger = 4,
|
|
Enemy = 8,
|
|
}
|
|
|
|
/**
|
|
* Wraps a three.js object in a cannon-es rigid body. The shape is derived from
|
|
* the object: the player gets a Sphere (rolls smoothly along walls/floor),
|
|
* everything else gets a Box sized to the object's bounding box.
|
|
*/
|
|
export class PhysicsBody {
|
|
private body: Body;
|
|
|
|
constructor(
|
|
object: Object3D,
|
|
isTrigger: boolean,
|
|
mass: number,
|
|
collisionGroup: PhysicsLayer,
|
|
collisionMask: PhysicsLayer,
|
|
sphereRadius = 0.3,
|
|
) {
|
|
const isPlayer = collisionGroup === PhysicsLayer.Player;
|
|
|
|
// Measure the bounding box with rotation temporarily zeroed, so the box
|
|
// half-extents match the object's un-rotated size; the body's own
|
|
// quaternion (set below) then applies the real orientation.
|
|
const savedRotation = object.quaternion.clone();
|
|
object.quaternion.copy(new Quaternion());
|
|
const size = new Box3().setFromObject(object).getSize(new Vector3());
|
|
object.quaternion.copy(savedRotation);
|
|
|
|
this.body = new Body({
|
|
isTrigger,
|
|
mass,
|
|
shape: isPlayer
|
|
? new Sphere(sphereRadius)
|
|
: new Box(new Vec3(size.x / 2, size.y / 2, size.z / 2)),
|
|
collisionFilterGroup: collisionGroup,
|
|
collisionFilterMask: collisionMask,
|
|
});
|
|
|
|
const worldPos = object.getWorldPosition(new Vector3());
|
|
this.body.position.set(worldPos.x, worldPos.y, worldPos.z);
|
|
this.body.quaternion.setFromEuler(
|
|
object.rotation.x,
|
|
object.rotation.y,
|
|
object.rotation.z,
|
|
"XYZ",
|
|
);
|
|
|
|
Physics_internal.physicsWorld?.addBody(this.body);
|
|
}
|
|
|
|
/** The underlying cannon body (for direct velocity/position control). */
|
|
getPhysicsBody(): Body {
|
|
return this.body;
|
|
}
|
|
|
|
/** Remove the body from the physics world (e.g. when a crate breaks). */
|
|
destroy() {
|
|
Physics_internal.physicsWorld?.removeBody(this.body);
|
|
}
|
|
}
|