three-player-controller 0.2.5 → 0.2.52

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.mjs CHANGED
@@ -97,14 +97,8 @@ var PlayerController = class {
97
97
  this.DIR_UP = new THREE.Vector3(0, 1, 0);
98
98
  this._personToCam = new THREE.Vector3();
99
99
  this._originTmp = new THREE.Vector3();
100
- this._raycaster = new THREE.Raycaster(
101
- new THREE.Vector3(),
102
- new THREE.Vector3(0, -1, 0)
103
- );
104
- this._raycasterPersonToCam = new THREE.Raycaster(
105
- new THREE.Vector3(),
106
- new THREE.Vector3()
107
- );
100
+ this._raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, -1, 0));
101
+ this._raycasterPersonToCam = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3());
108
102
  // 键盘按下事件
109
103
  this._boundOnKeydown = async (e) => {
110
104
  if (e.ctrlKey && (e.code === "KeyW" || e.code === "KeyA" || e.code === "KeyS" || e.code === "KeyD")) {
@@ -154,8 +148,7 @@ var PlayerController = class {
154
148
  case "KeyF":
155
149
  this.isFlying = !this.isFlying;
156
150
  this.setAnimationByPressed();
157
- if (!this.isFlying && !this.playerIsOnGround)
158
- this.playPersonAnimationByName("jumping");
151
+ if (!this.isFlying && !this.playerIsOnGround) this.playPersonAnimationByName("jumping");
159
152
  break;
160
153
  }
161
154
  };
@@ -303,6 +296,7 @@ var PlayerController = class {
303
296
  this.jumpHeight = opts.playerModel.jumpHeight ? opts.playerModel.jumpHeight * s : 800 * s;
304
297
  this.originPlayerSpeed = opts.playerModel.speed ? opts.playerModel.speed * s : 400 * s;
305
298
  this.playerSpeed = this.originPlayerSpeed;
299
+ this.playerModel.rotateY = opts.playerModel.rotateY ? opts.playerModel.rotateY : 0;
306
300
  this._camCollisionLerp = 0.18;
307
301
  this._camEpsilon = 35 * s;
308
302
  this._minCamDistance = opts.minCamDistance ? opts.minCamDistance * s : 100 * s;
@@ -332,53 +326,32 @@ var PlayerController = class {
332
326
  this.isFirstPerson = !this.isFirstPerson;
333
327
  if (this.isFirstPerson) {
334
328
  this.player.attach(this.camera);
335
- this.camera.position.set(
336
- 0,
337
- 40 * this.playerModel.scale,
338
- 30 * this.playerModel.scale
339
- );
329
+ this.camera.position.set(0, 40 * this.playerModel.scale, 30 * this.playerModel.scale);
340
330
  this.camera.rotation.set(0, Math.PI, 0);
341
331
  this.setPointerLock();
342
332
  } else {
343
333
  this.scene.attach(this.camera);
344
334
  const worldPos = this.player.position.clone();
345
- const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(
346
- this.player.quaternion
347
- );
335
+ const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(this.player.quaternion);
348
336
  const angle = Math.atan2(dir.z, dir.x);
349
- const offset = new THREE.Vector3(
350
- Math.cos(angle) * 400 * this.playerModel.scale,
351
- 200 * this.playerModel.scale,
352
- Math.sin(angle) * 400 * this.playerModel.scale
353
- );
337
+ const offset = new THREE.Vector3(Math.cos(angle) * 400 * this.playerModel.scale, 200 * this.playerModel.scale, Math.sin(angle) * 400 * this.playerModel.scale);
354
338
  this.camera.position.copy(worldPos).add(offset);
355
339
  this.controls.target.copy(worldPos);
356
340
  this.setPointerLock();
357
341
  }
358
342
  }
359
343
  setPointerLock() {
360
- if ((this.thirdMouseMode == 0 || this.thirdMouseMode == 1) && !this.isFirstPerson || this.isFirstPerson)
361
- document.body.requestPointerLock();
344
+ if ((this.thirdMouseMode == 0 || this.thirdMouseMode == 1) && !this.isFirstPerson || this.isFirstPerson) document.body.requestPointerLock();
362
345
  }
363
346
  // 摄像机/控制器设置
364
347
  setCameraPos() {
365
348
  if (this.isFirstPerson) {
366
- this.camera.position.set(
367
- 0,
368
- 40 * this.playerModel.scale,
369
- 30 * this.playerModel.scale
370
- );
349
+ this.camera.position.set(0, 40 * this.playerModel.scale, 30 * this.playerModel.scale);
371
350
  } else {
372
351
  const worldPos = this.player.position.clone();
373
- const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(
374
- this.player.quaternion
375
- );
352
+ const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(this.player.quaternion);
376
353
  const angle = Math.atan2(dir.z, dir.x);
377
- const offset = new THREE.Vector3(
378
- Math.cos(angle) * 400 * this.playerModel.scale,
379
- -100 * this.playerModel.scale,
380
- Math.sin(angle) * 400 * this.playerModel.scale
381
- );
354
+ const offset = new THREE.Vector3(Math.cos(angle) * 400 * this.playerModel.scale, -100 * this.playerModel.scale, Math.sin(angle) * 400 * this.playerModel.scale);
382
355
  this.camera.position.copy(worldPos).add(offset);
383
356
  }
384
357
  this.camera.updateProjectionMatrix();
@@ -410,9 +383,7 @@ var PlayerController = class {
410
383
  // 初始化加载器
411
384
  async initLoader() {
412
385
  const dracoLoader = new DRACOLoader();
413
- dracoLoader.setDecoderPath(
414
- "https://unpkg.com/three@0.180.0/examples/jsm/libs/draco/gltf/"
415
- );
386
+ dracoLoader.setDecoderPath("https://unpkg.com/three@0.180.0/examples/jsm/libs/draco/gltf/");
416
387
  dracoLoader.setDecoderConfig({ type: "js" });
417
388
  this.loader.setDRACOLoader(dracoLoader);
418
389
  }
@@ -440,18 +411,9 @@ var PlayerController = class {
440
411
  const regs = [
441
412
  [this.playerModel.idleAnim, "idle"],
442
413
  [this.playerModel.walkAnim, "walking"],
443
- [
444
- this.playerModel.leftWalkAnim || this.playerModel.walkAnim,
445
- "left_walking"
446
- ],
447
- [
448
- this.playerModel.rightWalkAnim || this.playerModel.walkAnim,
449
- "right_walking"
450
- ],
451
- [
452
- this.playerModel.backwardAnim || this.playerModel.walkAnim,
453
- "walking_backward"
454
- ],
414
+ [this.playerModel.leftWalkAnim || this.playerModel.walkAnim, "left_walking"],
415
+ [this.playerModel.rightWalkAnim || this.playerModel.walkAnim, "right_walking"],
416
+ [this.playerModel.backwardAnim || this.playerModel.walkAnim, "walking_backward"],
455
417
  [this.playerModel.jumpAnim, "jumping"],
456
418
  [this.playerModel.runAnim, "running"],
457
419
  [this.playerModel.flyIdleAnim || this.playerModel.idleAnim, "flyidle"],
@@ -540,29 +502,22 @@ var PlayerController = class {
540
502
  material.depthWrite = false;
541
503
  const r = this.playerRadius * this.playerModel.scale;
542
504
  const h = this.playerHeight * this.playerModel.scale;
543
- this.player = new THREE.Mesh(
544
- new RoundedBoxGeometry(r * 2, h, r * 2, 1, 75),
545
- material
546
- );
505
+ this.player = new THREE.Mesh(new RoundedBoxGeometry(r * 2, h, r * 2, 1, 75), material);
547
506
  this.player.geometry.translate(0, -h * 0.25, 0);
548
507
  this.player.capsuleInfo = {
549
508
  radius: r,
550
- segment: new THREE.Line3(
551
- new THREE.Vector3(),
552
- new THREE.Vector3(0, -h * 0.5, 0)
553
- )
509
+ segment: new THREE.Line3(new THREE.Vector3(), new THREE.Vector3(0, -h * 0.5, 0))
554
510
  };
555
511
  this.player.name = "capsule";
556
512
  this.scene.add(this.player);
557
513
  this.reset();
514
+ this.player.rotateY(this.playerModel.rotateY ?? 0);
558
515
  }
559
516
  // 获取法线与Y轴的夹角
560
517
  getAngleWithYAxis(normal) {
561
518
  const yAxis = { x: 0, y: 1, z: 0 };
562
519
  const dotProduct = normal.x * yAxis.x + normal.y * yAxis.y + normal.z * yAxis.z;
563
- const normalMagnitude = Math.sqrt(
564
- normal.x * normal.x + normal.y * normal.y + normal.z * normal.z
565
- );
520
+ const normalMagnitude = Math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
566
521
  const yAxisMagnitude = 1;
567
522
  const cosTheta = dotProduct / (normalMagnitude * yAxisMagnitude);
568
523
  return Math.acos(cosTheta);
@@ -571,8 +526,7 @@ var PlayerController = class {
571
526
  async update(delta = clock.getDelta()) {
572
527
  if (!this.isupdate || !this.player || !this.collider) return;
573
528
  delta = Math.min(delta, 1 / 30);
574
- if (!this.isFlying)
575
- this.player.position.addScaledVector(this.playerVelocity, delta);
529
+ if (!this.isFlying) this.player.position.addScaledVector(this.playerVelocity, delta);
576
530
  this.updateMixers(delta);
577
531
  this.camera.getWorldDirection(this.camDir);
578
532
  let angle = Math.atan2(this.camDir.z, this.camDir.x) + Math.PI / 2;
@@ -598,21 +552,11 @@ var PlayerController = class {
598
552
  this.playerSpeed = this.shiftPressed ? this.originPlayerSpeed * 2 : this.originPlayerSpeed;
599
553
  }
600
554
  this.moveDir.normalize().applyAxisAngle(this.upVector, angle);
601
- this.player.position.addScaledVector(
602
- this.moveDir,
603
- this.playerSpeed * delta
604
- );
555
+ this.player.position.addScaledVector(this.moveDir, this.playerSpeed * delta);
605
556
  let playerDistanceFromGround = Infinity;
606
- this._originTmp.set(
607
- this.player.position.x,
608
- this.player.position.y,
609
- this.player.position.z
610
- );
557
+ this._originTmp.set(this.player.position.x, this.player.position.y, this.player.position.z);
611
558
  this._raycaster.ray.origin.copy(this._originTmp);
612
- const intersects = this._raycaster.intersectObject(
613
- this.collider,
614
- false
615
- );
559
+ const intersects = this._raycaster.intersectObject(this.collider, false);
616
560
  if (intersects.length > 0) {
617
561
  playerDistanceFromGround = this.player.position.y - intersects[0].point.y;
618
562
  const normal = intersects[0].normal;
@@ -640,11 +584,7 @@ var PlayerController = class {
640
584
  this.playerIsOnGround = true;
641
585
  } else if (playerDistanceFromGround < minH) {
642
586
  this.playerVelocity.set(0, 0, 0);
643
- this.player.position.set(
644
- this.player.position.x,
645
- intersects[0].point.y + h,
646
- this.player.position.z
647
- );
587
+ this.player.position.set(this.player.position.x, intersects[0].point.y + h, this.player.position.z);
648
588
  this.playerIsOnGround = true;
649
589
  }
650
590
  }
@@ -667,11 +607,7 @@ var PlayerController = class {
667
607
  intersectsTriangle: (tri) => {
668
608
  const triPoint = this.tempVector;
669
609
  const capsulePoint = this.tempVector2;
670
- const distance = tri.closestPointToSegment(
671
- this.tempSegment,
672
- triPoint,
673
- capsulePoint
674
- );
610
+ const distance = tri.closestPointToSegment(this.tempSegment, triPoint, capsulePoint);
675
611
  if (distance < capsuleInfo.radius) {
676
612
  const depth = capsuleInfo.radius - distance;
677
613
  const direction = capsulePoint.sub(triPoint).normalize();
@@ -681,10 +617,7 @@ var PlayerController = class {
681
617
  }
682
618
  });
683
619
  const newPosition = this.tempVector.copy(this.tempSegment.start).applyMatrix4(this.collider.matrixWorld);
684
- const deltaVector = this.tempVector2.subVectors(
685
- newPosition,
686
- this.player.position
687
- );
620
+ const deltaVector = this.tempVector2.subVectors(newPosition, this.player.position);
688
621
  const offset = Math.max(0, deltaVector.length() - 1e-5);
689
622
  deltaVector.normalize().multiplyScalar(offset);
690
623
  this.player.position.add(deltaVector);
@@ -739,24 +672,15 @@ var PlayerController = class {
739
672
  const desiredDist = this._personToCam.length();
740
673
  this._raycasterPersonToCam.set(origin, direction);
741
674
  this._raycasterPersonToCam.far = desiredDist;
742
- const intersects2 = this._raycasterPersonToCam.intersectObject(
743
- this.collider,
744
- false
745
- );
675
+ const intersects2 = this._raycasterPersonToCam.intersectObject(this.collider, false);
746
676
  if (intersects2.length > 0) {
747
677
  const hit = intersects2[0];
748
- const safeDist = Math.max(
749
- hit.distance - this._camEpsilon,
750
- this._minCamDistance
751
- );
678
+ const safeDist = Math.max(hit.distance - this._camEpsilon, this._minCamDistance);
752
679
  const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
753
680
  this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
754
681
  } else {
755
682
  this._raycasterPersonToCam.far = this._maxCamDistance;
756
- const intersectsMaxDis = this._raycasterPersonToCam.intersectObject(
757
- this.collider,
758
- false
759
- );
683
+ const intersectsMaxDis = this._raycasterPersonToCam.intersectObject(this.collider, false);
760
684
  let safeDist = this._maxCamDistance;
761
685
  if (intersectsMaxDis.length) {
762
686
  const hitMax = intersectsMaxDis[0];
@@ -767,34 +691,15 @@ var PlayerController = class {
767
691
  }
768
692
  }
769
693
  if (this.player.position.y < this.boundingBoxMinY - 1) {
770
- this._originTmp.set(
771
- this.player.position.x,
772
- 1e4,
773
- this.player.position.z
774
- );
694
+ this._originTmp.set(this.player.position.x, 1e4, this.player.position.z);
775
695
  this._raycaster.ray.origin.copy(this._originTmp);
776
- const intersects2 = this._raycaster.intersectObject(
777
- this.collider,
778
- false
779
- );
696
+ const intersects2 = this._raycaster.intersectObject(this.collider, false);
780
697
  if (intersects2.length > 0) {
781
698
  console.log("\u73A9\u5BB6\u4E3Abug\u610F\u5916\u6389\u843D");
782
- this.reset(
783
- new THREE.Vector3(
784
- this.player.position.x,
785
- intersects2[0].point.y + 5,
786
- this.player.position.z
787
- )
788
- );
699
+ this.reset(new THREE.Vector3(this.player.position.x, intersects2[0].point.y + 5, this.player.position.z));
789
700
  } else {
790
701
  console.log("\u73A9\u5BB6\u6B63\u5E38\u6389\u843D");
791
- this.reset(
792
- new THREE.Vector3(
793
- this.player.position.x,
794
- this.player.position.y + 15,
795
- this.player.position.z
796
- )
797
- );
702
+ this.reset(new THREE.Vector3(this.player.position.x, this.player.position.y + 15, this.player.position.z));
798
703
  }
799
704
  }
800
705
  }
@@ -846,6 +751,9 @@ var PlayerController = class {
846
751
  window.removeEventListener("mousemove", this._mouseMove);
847
752
  window.removeEventListener("click", this._mouseClick);
848
753
  }
754
+ getPosition() {
755
+ return this.player.position;
756
+ }
849
757
  // 更新模型动画
850
758
  updateMixers(delta) {
851
759
  if (this.personMixer) this.personMixer.update(delta);
@@ -899,8 +807,7 @@ var PlayerController = class {
899
807
  attrMap.set(name, { itemSize, arrayCtor: ctor, examples: 1 });
900
808
  } else {
901
809
  const m = attrMap.get(name);
902
- if (m.itemSize !== itemSize || m.arrayCtor !== ctor)
903
- attrConflict.add(name);
810
+ if (m.itemSize !== itemSize || m.arrayCtor !== ctor) attrConflict.add(name);
904
811
  else m.examples++;
905
812
  }
906
813
  }
@@ -921,10 +828,7 @@ var PlayerController = class {
921
828
  const meta = attrMap.get(name);
922
829
  const len = count * meta.itemSize;
923
830
  const array = new meta.arrayCtor(len);
924
- g.setAttribute(
925
- name,
926
- new THREE.BufferAttribute(array, meta.itemSize)
927
- );
831
+ g.setAttribute(name, new THREE.BufferAttribute(array, meta.itemSize));
928
832
  }
929
833
  }
930
834
  }
@@ -969,11 +873,7 @@ var PlayerController = class {
969
873
  const yaw = -dx * speed * this.mouseSensity;
970
874
  const pitch = -dy * speed * this.mouseSensity;
971
875
  this.player.rotateY(yaw);
972
- this.camera.rotation.x = THREE.MathUtils.clamp(
973
- this.camera.rotation.x + pitch,
974
- -1.1,
975
- 1.4
976
- );
876
+ this.camera.rotation.x = THREE.MathUtils.clamp(this.camera.rotation.x + pitch, -1.1, 1.4);
977
877
  } else {
978
878
  const sensitivity = this.mouseSensity;
979
879
  const deltaX = -dx * speed * sensitivity;
@@ -989,11 +889,7 @@ var PlayerController = class {
989
889
  const newX = distance * Math.sin(phi) * Math.sin(theta);
990
890
  const newY = distance * Math.cos(phi);
991
891
  const newZ = distance * Math.sin(phi) * Math.cos(theta);
992
- this.camera.position.set(
993
- target.x + newX,
994
- target.y + newY,
995
- target.z + newZ
996
- );
892
+ this.camera.position.set(target.x + newX, target.y + newY, target.z + newZ);
997
893
  this.camera.lookAt(target);
998
894
  }
999
895
  }
@@ -1032,8 +928,7 @@ var PlayerController = class {
1032
928
  if (input.toggleFly) {
1033
929
  this.isFlying = !this.isFlying;
1034
930
  this.setAnimationByPressed();
1035
- if (!this.isFlying && !this.playerIsOnGround)
1036
- this.playPersonAnimationByName("jumping");
931
+ if (!this.isFlying && !this.playerIsOnGround) this.playPersonAnimationByName("jumping");
1037
932
  }
1038
933
  }
1039
934
  // 初始化移动端摇杆控制
@@ -1059,17 +954,15 @@ var PlayerController = class {
1059
954
  userSelect: "none"
1060
955
  });
1061
956
  container.appendChild(this.joystickZoneEl);
1062
- ["touchstart", "touchmove", "touchend", "touchcancel"].forEach(
1063
- (evtName) => {
1064
- this.joystickZoneEl?.addEventListener(
1065
- evtName,
1066
- (e) => {
1067
- e.preventDefault();
1068
- },
1069
- { passive: false }
1070
- );
1071
- }
1072
- );
957
+ ["touchstart", "touchmove", "touchend", "touchcancel"].forEach((evtName) => {
958
+ this.joystickZoneEl?.addEventListener(
959
+ evtName,
960
+ (e) => {
961
+ e.preventDefault();
962
+ },
963
+ { passive: false }
964
+ );
965
+ });
1073
966
  this.joystickManager = nipple.create({
1074
967
  zone: this.joystickZoneEl,
1075
968
  mode: "static",
@@ -1119,17 +1012,15 @@ var PlayerController = class {
1119
1012
  userSelect: "none"
1120
1013
  });
1121
1014
  container.appendChild(this.lookAreaEl);
1122
- ["touchstart", "touchmove", "touchend", "touchcancel"].forEach(
1123
- (evtName) => {
1124
- this.lookAreaEl?.addEventListener(
1125
- evtName,
1126
- (e) => {
1127
- e.preventDefault();
1128
- },
1129
- { passive: false }
1130
- );
1131
- }
1132
- );
1015
+ ["touchstart", "touchmove", "touchend", "touchcancel"].forEach((evtName) => {
1016
+ this.lookAreaEl?.addEventListener(
1017
+ evtName,
1018
+ (e) => {
1019
+ e.preventDefault();
1020
+ },
1021
+ { passive: false }
1022
+ );
1023
+ });
1133
1024
  this.lookAreaEl.addEventListener("pointerdown", this.onPointerDown, {
1134
1025
  passive: false
1135
1026
  });
@@ -1272,7 +1163,8 @@ function playerController() {
1272
1163
  reset: (pos) => c.reset(pos),
1273
1164
  update: (dt) => c.update(dt),
1274
1165
  destroy: () => c.destroy(),
1275
- setInput: (i) => c.setInput(i)
1166
+ setInput: (i) => c.setInput(i),
1167
+ getposition: () => c.getPosition()
1276
1168
  };
1277
1169
  }
1278
1170
  function onAllEvent() {