three-player-controller 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -109,7 +109,17 @@ declare function playerController(): {
109
109
  update: (dt?: number) => Promise<void>;
110
110
  destroy: () => void;
111
111
  reset: (pos?: THREE.Vector3) => void;
112
- setInput: (i: any) => void;
112
+ setInput: (i: Parameters<(input: Partial<{
113
+ moveX: 1 | 0 | -1;
114
+ moveY: 1 | 0 | -1;
115
+ lookDeltaX: number;
116
+ lookDeltaY: number;
117
+ jump: boolean;
118
+ shift: boolean;
119
+ toggleView: boolean;
120
+ toggleFly: boolean;
121
+ toggleVehicle: boolean;
122
+ }>) => void>[0]) => void;
113
123
  changeView: () => void;
114
124
  getPosition: () => THREE.Vector3;
115
125
  getCenterScreenRaycastHit: () => THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | undefined;
package/dist/index.d.ts CHANGED
@@ -109,7 +109,17 @@ declare function playerController(): {
109
109
  update: (dt?: number) => Promise<void>;
110
110
  destroy: () => void;
111
111
  reset: (pos?: THREE.Vector3) => void;
112
- setInput: (i: any) => void;
112
+ setInput: (i: Parameters<(input: Partial<{
113
+ moveX: 1 | 0 | -1;
114
+ moveY: 1 | 0 | -1;
115
+ lookDeltaX: number;
116
+ lookDeltaY: number;
117
+ jump: boolean;
118
+ shift: boolean;
119
+ toggleView: boolean;
120
+ toggleFly: boolean;
121
+ toggleVehicle: boolean;
122
+ }>) => void>[0]) => void;
113
123
  changeView: () => void;
114
124
  getPosition: () => THREE.Vector3;
115
125
  getCenterScreenRaycastHit: () => THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | undefined;
package/dist/index.js CHANGED
@@ -1038,7 +1038,7 @@ var PlayerController = class {
1038
1038
  }
1039
1039
  const w = window.innerWidth;
1040
1040
  const h = window.innerHeight;
1041
- this.camera.setViewOffset(w, h, -w * -0.15, 0, w, h);
1041
+ this.camera.setViewOffset(w, h, w * 0.15, 0, w, h);
1042
1042
  }
1043
1043
  // 初始化加载器
1044
1044
  async initLoader() {
@@ -1119,7 +1119,7 @@ var PlayerController = class {
1119
1119
  this.personActions.get("idle")?.setEffectiveWeight(1);
1120
1120
  this.personActions.get("idle")?.play();
1121
1121
  this.actionState = this.personActions.get("idle");
1122
- this.personMixer.addEventListener("finished", (ev) => {
1122
+ this.personMixerFinishedCb = (ev) => {
1123
1123
  const done = ev.action;
1124
1124
  if (done === this.personActions?.get("jumping")) {
1125
1125
  if (this.fwdPressed) {
@@ -1137,7 +1137,8 @@ var PlayerController = class {
1137
1137
  this.playPersonAnimationByName("idle");
1138
1138
  }
1139
1139
  if (done === this.personActions?.get("enterCar")) this.onEnterCarAnimFinished();
1140
- });
1140
+ };
1141
+ this.personMixer.addEventListener("finished", this.personMixerFinishedCb);
1141
1142
  this.personMixer.update(0);
1142
1143
  this.person.updateMatrixWorld(true);
1143
1144
  const { size } = this.getBbox(this.person);
@@ -1192,6 +1193,10 @@ var PlayerController = class {
1192
1193
  this.personHead = null;
1193
1194
  }
1194
1195
  if (this.personMixer) {
1196
+ if (this.personMixerFinishedCb) {
1197
+ this.personMixer.removeEventListener("finished", this.personMixerFinishedCb);
1198
+ this.personMixerFinishedCb = void 0;
1199
+ }
1195
1200
  this.personMixer.stopAllAction();
1196
1201
  this.personMixer.uncacheRoot(this.personMixer.getRoot());
1197
1202
  this.personMixer = void 0;
@@ -1646,7 +1651,7 @@ var PlayerController = class {
1646
1651
  return;
1647
1652
  }
1648
1653
  merged.boundsTree = new import_three_mesh_bvh.MeshBVH(merged, { maxDepth: 100 });
1649
- this.collider = new THREE4.Mesh(merged, new THREE4.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true }));
1654
+ this.collider = new THREE4.Mesh(merged, new THREE4.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true, side: THREE4.DoubleSide }));
1650
1655
  if (this.displayCollider) this.scene.add(this.collider);
1651
1656
  if (this.displayVisualizer) {
1652
1657
  if (this.visualizer) this.scene.remove(this.visualizer);
@@ -1684,7 +1689,7 @@ var PlayerController = class {
1684
1689
  return;
1685
1690
  }
1686
1691
  merged.boundsTree = new import_three_mesh_bvh.MeshBVH(merged);
1687
- this.dynamicCollider = new THREE4.Mesh(merged, new THREE4.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true }));
1692
+ this.dynamicCollider = new THREE4.Mesh(merged, new THREE4.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true, side: THREE4.DoubleSide }));
1688
1693
  if (this.displayCollider) this.scene.add(this.dynamicCollider);
1689
1694
  }
1690
1695
  // ==================== 控制器过渡 ====================
@@ -1919,16 +1924,17 @@ var PlayerController = class {
1919
1924
  if (!this.spacePressed) {
1920
1925
  this.playerVelocity.set(0, 0, 0);
1921
1926
  this.playerIsOnGround = true;
1922
- this.player.position.y = hits[0].point.y + h;
1927
+ this.player.position.y = THREE4.MathUtils.lerp(this.player.position.y, hits[0].point.y + h, Math.min(1, 15 * delta));
1923
1928
  }
1924
1929
  } else if (dist >= minH) {
1925
1930
  this.playerVelocity.set(0, 0, 0);
1926
1931
  this.playerIsOnGround = true;
1927
1932
  this.player.position.y = hits[0].point.y + h;
1928
1933
  } else {
1934
+ const targetY = hits[0].point.y + h;
1929
1935
  this.playerVelocity.set(0, 0, 0);
1930
- this.player.position.y = hits[0].point.y + h;
1931
1936
  this.playerIsOnGround = true;
1937
+ this.player.position.y = THREE4.MathUtils.lerp(this.player.position.y, targetY, Math.min(1, 15 * delta));
1932
1938
  }
1933
1939
  }
1934
1940
  this.player.updateMatrixWorld();
@@ -1949,7 +1955,14 @@ var PlayerController = class {
1949
1955
  const distance = tri.closestPointToSegment(this.tempSegment, this.tempVector, this.tempVector2);
1950
1956
  if (distance < capsuleInfo.radius) {
1951
1957
  const normal = tri.getNormal(new THREE4.Vector3());
1952
- if (normal.y > 0.5 && !this.isFlying) return;
1958
+ if (!this.isFlying && Math.abs(normal.y) > 0.5) return;
1959
+ if (!this.isFlying && Math.abs(normal.y) <= 0.5) {
1960
+ const e = this.collider.matrixWorld.elements;
1961
+ const contactWorldY = e[1] * this.tempVector.x + e[5] * this.tempVector.y + e[9] * this.tempVector.z + e[13];
1962
+ const s = this.playerModel.scale;
1963
+ const feetY = this.player.position.y - this.playerCapsuleHeight * s * 0.75;
1964
+ if (contactWorldY < feetY + this.playerCapsuleHeight * s * 0.25) return;
1965
+ }
1953
1966
  const dir = this.tempVector2.sub(this.tempVector).normalize();
1954
1967
  const depth = capsuleInfo.radius - distance;
1955
1968
  this.tempSegment.start.addScaledVector(dir, depth);
@@ -2044,13 +2057,14 @@ var PlayerController = class {
2044
2057
  }
2045
2058
  // 屏幕中心射线
2046
2059
  getCenterScreenRaycastHit() {
2060
+ if (!this.collider) return void 0;
2047
2061
  this.camera.updateMatrixWorld();
2048
2062
  this.centerRay.setFromCamera(this.centerMouse, this.camera);
2049
2063
  return this.centerRay.intersectObject(this.collider, false)[0];
2050
2064
  }
2051
2065
  // 获取当前人物动画名称
2052
2066
  getCurrentPersonAnimationName() {
2053
- return this.actionState._clip.name;
2067
+ return this.actionState?.getClip()?.name ?? null;
2054
2068
  }
2055
2069
  // 更新动画混合器
2056
2070
  updateMixers(delta) {
@@ -2217,6 +2231,7 @@ var PlayerController = class {
2217
2231
  for (const v of this.vehicles) {
2218
2232
  this.scene.remove(v.vehicleGroup);
2219
2233
  v.pathPlanner?.dispose();
2234
+ v.vehicleController?.destroy?.();
2220
2235
  }
2221
2236
  this.vehicles = [];
2222
2237
  this.activeVehicle = null;