-Add UI (Health bars, Resources UI, HUD Interface, Weapon U, Zoombie Invasion progress Indicator)

-Refactor code structure for improved readability and maintainability
This commit is contained in:
24Play-Mykyta-Slobodianiuk
2026-06-08 18:33:28 +03:00
parent d6fc6be717
commit 78d85c3799
31 changed files with 6308 additions and 624 deletions
+37 -94
View File
@@ -1,11 +1,10 @@
import {
Delegate,
Physics_internal,
UpdateController,
} from "@24tools/playable_template";
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,
@@ -13,117 +12,61 @@ export enum PhysicsLayer {
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;
private pair: PhysicsObjPair | null = null;
constructor(
threeObj: Object3D,
trigger: boolean,
object: Object3D,
isTrigger: boolean,
mass: number,
col_group: PhysicsLayer,
col_mask: PhysicsLayer,
player_sphere: number = 0.3
collisionGroup: PhysicsLayer,
collisionMask: PhysicsLayer,
sphereRadius = 0.3,
) {
let isPlayer = col_group === PhysicsLayer.Player;
const isPlayer = collisionGroup === PhysicsLayer.Player;
let oldQuaternion = threeObj.quaternion.clone();
let nullQuaternion = new Quaternion();
threeObj.quaternion.copy(nullQuaternion);
let bbox = new Box3().setFromObject(threeObj);
let size = new Vector3();
bbox.getSize(size);
// if you need custom size
// if (col_group === PhysicsLayer.wall) {
// size.x = size.z = 1;
// size.y = 1;
// }
threeObj.quaternion.copy(oldQuaternion);
// 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: trigger,
mass: mass,
//shape: shape,
isTrigger,
mass,
shape: isPlayer
? new Sphere(player_sphere)
? new Sphere(sphereRadius)
: new Box(new Vec3(size.x / 2, size.y / 2, size.z / 2)),
collisionFilterGroup: col_group,
collisionFilterMask: col_mask,
collisionFilterGroup: collisionGroup,
collisionFilterMask: collisionMask,
});
let worldPos = threeObj.getWorldPosition(new Vector3());
const worldPos = object.getWorldPosition(new Vector3());
this.body.position.set(worldPos.x, worldPos.y, worldPos.z);
this.body.quaternion.setFromEuler(
threeObj.rotation.x,
threeObj.rotation.y,
threeObj.rotation.z,
"XYZ"
object.rotation.x,
object.rotation.y,
object.rotation.z,
"XYZ",
);
// if you need sync three obj and physics body
// if (isEnemy) {
// let pair = new PhysicsObjPair(threeObj, this.body);
// PhysicsC_Instance.addPhysicsPair(pair);
// this.pair = pair;
// }
Physics_internal.physicsWorld &&
Physics_internal.physicsWorld.addBody(this.body);
return this;
Physics_internal.physicsWorld?.addBody(this.body);
}
disablePhysicsPair() {
if (this.pair) {
this.pair.destroyed = true;
}
}
getPhysicsBody() {
/** 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() {
if (!Physics_internal.physicsWorld) return;
Physics_internal.physicsWorld.removeBody(this.body);
(this.body as any) = null;
}
}
export class PhysicsObjPair {
threeObj: Object3D;
physicsObj: Body;
destroyed: boolean;
delegateId: null | Delegate<number>;
constructor(threeObj: Object3D, physicsObj: Body) {
this.threeObj = threeObj;
this.physicsObj = physicsObj;
this.destroyed = false;
this.delegateId = UpdateController.Instance.onUpdate.addDelegate(() => {
this.update();
});
}
update() {
if (this.destroyed) return;
if (this.threeObj && this.physicsObj) {
// @ts-ignore
this.threeObj.position.copy(this.physicsObj.position);
// @ts-ignore
this.threeObj.quaternion.copy(this.physicsObj.quaternion);
}
Physics_internal.physicsWorld?.removeBody(this.body);
}
}