three-player-controller 0.1.7 → 0.1.9

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
@@ -26,6 +26,7 @@ var PlayerController = class {
26
26
  // 状态开关
27
27
  this.playerIsOnGround = false;
28
28
  this.isupdate = true;
29
+ this.isFlying = false;
29
30
  // 输入状态
30
31
  this.fwdPressed = false;
31
32
  this.bkdPressed = false;
@@ -34,8 +35,6 @@ var PlayerController = class {
34
35
  this.spacePressed = false;
35
36
  this.ctPressed = false;
36
37
  this.shiftPressed = false;
37
- this.sustainSpacePressed = false;
38
- this.spaceLongPressTimer = null;
39
38
  // 第三人称
40
39
  this._camCollisionLerp = 0.18;
41
40
  // 平滑系数
@@ -45,6 +44,7 @@ var PlayerController = class {
45
44
  // 摄像机最小距离
46
45
  this._maxCamDistance = 4.4;
47
46
  // 摄像机最大距离
47
+ this.orginMaxCamDistance = 4.4;
48
48
  // 物理/运动
49
49
  this.playerVelocity = new THREE.Vector3();
50
50
  // 玩家速度向量
@@ -65,6 +65,7 @@ var PlayerController = class {
65
65
  this.DIR_BKD = new THREE.Vector3(0, 0, 1);
66
66
  this.DIR_LFT = new THREE.Vector3(-1, 0, 0);
67
67
  this.DIR_RGT = new THREE.Vector3(1, 0, 0);
68
+ this.DIR_UP = new THREE.Vector3(0, 1, 0);
68
69
  this._personToCam = new THREE.Vector3();
69
70
  this._originTmp = new THREE.Vector3();
70
71
  this._raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, -1, 0));
@@ -96,12 +97,11 @@ var PlayerController = class {
96
97
  this.setAnimationByPressed();
97
98
  break;
98
99
  case "Space":
99
- if (!this.spacePressed) this.spacePressed = true;
100
- if (!this.spaceLongPressTimer) {
101
- this.spaceLongPressTimer = setTimeout(() => {
102
- this.sustainSpacePressed = true;
103
- }, 2e3);
104
- }
100
+ this.spacePressed = true;
101
+ if (!this.playerIsOnGround || this.isFlying) return;
102
+ this.playPersonAnimationByName("jumping");
103
+ this.playerVelocity.y = this.jumpHeight;
104
+ this.playerIsOnGround = false;
105
105
  break;
106
106
  case "ControlLeft":
107
107
  this.ctPressed = true;
@@ -109,6 +109,15 @@ var PlayerController = class {
109
109
  case "KeyV":
110
110
  this.changeView();
111
111
  break;
112
+ case "KeyF":
113
+ this.isFlying = !this.isFlying;
114
+ this._maxCamDistance = this.isFlying ? this.orginMaxCamDistance * 2 : this.orginMaxCamDistance;
115
+ if (!this.isFlying && !this.playerIsOnGround) {
116
+ this.playPersonAnimationByName("jumping");
117
+ } else {
118
+ this.setAnimationByPressed();
119
+ }
120
+ break;
112
121
  }
113
122
  };
114
123
  // 键盘抬起事件
@@ -135,12 +144,7 @@ var PlayerController = class {
135
144
  this.setAnimationByPressed();
136
145
  break;
137
146
  case "Space":
138
- if (this.spaceLongPressTimer) {
139
- clearTimeout(this.spaceLongPressTimer);
140
- this.spaceLongPressTimer = null;
141
- }
142
147
  this.spacePressed = false;
143
- this.sustainSpacePressed = false;
144
148
  break;
145
149
  case "ControlLeft":
146
150
  this.ctPressed = false;
@@ -149,6 +153,16 @@ var PlayerController = class {
149
153
  };
150
154
  // 根据按键设置人物动画
151
155
  this.setAnimationByPressed = () => {
156
+ this._maxCamDistance = this.orginMaxCamDistance;
157
+ if (this.isFlying) {
158
+ if (!this.fwdPressed) {
159
+ this.playPersonAnimationByName("flyidle");
160
+ return;
161
+ }
162
+ this.playPersonAnimationByName("flying");
163
+ this._maxCamDistance = this.orginMaxCamDistance * 2;
164
+ return;
165
+ }
152
166
  if (this.playerIsOnGround) {
153
167
  if (!this.fwdPressed && !this.bkdPressed && !this.lftPressed && !this.rgtPressed) {
154
168
  this.playPersonAnimationByName("idle");
@@ -228,13 +242,13 @@ var PlayerController = class {
228
242
  const s = this.playerModel.scale;
229
243
  this.visualizeDepth = 0 * s;
230
244
  this.gravity = opts.playerModel.gravity ? opts.playerModel.gravity * s : -2400 * s;
231
- this.jumpHeight = opts.playerModel.jumpHeight ? opts.playerModel.jumpHeight * s : 300 * s;
232
- this.highJumpHeight = opts.playerModel.highJumpHeight ? opts.playerModel.highJumpHeight * s : 1e3 * s;
245
+ this.jumpHeight = opts.playerModel.jumpHeight ? opts.playerModel.jumpHeight * s : 800 * s;
233
246
  this.playerSpeed = opts.playerModel.speed ? opts.playerModel.speed * s : 400 * s;
234
247
  this._camCollisionLerp = 0.18;
235
248
  this._camEpsilon = 35 * s;
236
- this._minCamDistance = 100 * s;
237
- this._maxCamDistance = 440 * s;
249
+ this._minCamDistance = opts.minCamDistance ? opts.minCamDistance * s : 100 * s;
250
+ this._maxCamDistance = opts.maxCamDistance ? opts.maxCamDistance * s : 440 * s;
251
+ this.orginMaxCamDistance = this._maxCamDistance;
238
252
  await this.createBVH();
239
253
  this.createPlayer();
240
254
  await this.loadPersonGLB();
@@ -281,10 +295,11 @@ var PlayerController = class {
281
295
  // 设置控制器
282
296
  setControls() {
283
297
  this.controls.enabled = false;
284
- this.controls.maxPolarAngle = Math.PI * (230 / 360);
298
+ this.controls.maxPolarAngle = Math.PI * (300 / 360);
285
299
  }
286
300
  // 重置控制器
287
301
  resetControls() {
302
+ if (!this.controls) return;
288
303
  this.controls.enabled = true;
289
304
  this.controls.enablePan = true;
290
305
  this.controls.maxPolarAngle = Math.PI / 2;
@@ -315,6 +330,7 @@ var PlayerController = class {
315
330
  this.person.traverse((child) => {
316
331
  if (child.isMesh) {
317
332
  child.castShadow = true;
333
+ child.receiveShadow = true;
318
334
  }
319
335
  });
320
336
  this.player.add(this.person);
@@ -330,7 +346,9 @@ var PlayerController = class {
330
346
  [this.playerModel.rightWalkAnim || this.playerModel.walkAnim, "right_walking"],
331
347
  [this.playerModel.backwardAnim || this.playerModel.walkAnim, "walking_backward"],
332
348
  [this.playerModel.jumpAnim, "jumping"],
333
- [this.playerModel.runAnim, "running"]
349
+ [this.playerModel.runAnim, "running"],
350
+ [this.playerModel.flyIdleAnim || this.playerModel.idleAnim, "flyidle"],
351
+ [this.playerModel.flyAnim || this.playerModel.idleAnim, "flying"]
334
352
  ];
335
353
  for (const [key, clipName] of regs) {
336
354
  const clip = findClip(key);
@@ -356,6 +374,8 @@ var PlayerController = class {
356
374
  this.backwardAction = this.personActions.get("walking_backward");
357
375
  this.jumpAction = this.personActions.get("jumping");
358
376
  this.runAction = this.personActions.get("running");
377
+ this.flyidleAction = this.personActions.get("flyidle");
378
+ this.flyAction = this.personActions.get("flying");
359
379
  this.idleAction.setEffectiveWeight(1);
360
380
  this.idleAction.play();
361
381
  this.actionState = this.idleAction;
@@ -423,6 +443,7 @@ var PlayerController = class {
423
443
  this.scene.add(this.player);
424
444
  this.reset();
425
445
  }
446
+ // 获取法线与Y轴的夹角
426
447
  getAngleWithYAxis(normal) {
427
448
  const yAxis = { x: 0, y: 1, z: 0 };
428
449
  const dotProduct = normal.x * yAxis.x + normal.y * yAxis.y + normal.z * yAxis.z;
@@ -433,10 +454,10 @@ var PlayerController = class {
433
454
  }
434
455
  // 每帧更新
435
456
  async update(delta = clock.getDelta()) {
436
- if (!this.isupdate || !this.player) return;
457
+ if (!this.isupdate || !this.player || !this.collider) return;
437
458
  delta = Math.min(delta, 1 / 30);
459
+ if (!this.isFlying) this.player.position.addScaledVector(this.playerVelocity, delta);
438
460
  this.updateMixers(delta);
439
- if (!this.collider) return;
440
461
  this.camera.getWorldDirection(this.camDir);
441
462
  let angle = Math.atan2(this.camDir.z, this.camDir.x) + Math.PI / 2;
442
463
  angle = 2 * Math.PI - angle;
@@ -445,31 +466,23 @@ var PlayerController = class {
445
466
  if (this.bkdPressed) this.moveDir.add(this.DIR_BKD);
446
467
  if (this.lftPressed) this.moveDir.add(this.DIR_LFT);
447
468
  if (this.rgtPressed) this.moveDir.add(this.DIR_RGT);
448
- if (this.spacePressed && this.playerIsOnGround) {
449
- this.playPersonAnimationByName("jumping");
450
- setTimeout(() => {
451
- this.playerVelocity.y = this.jumpHeight;
452
- this.playerIsOnGround = false;
453
- this.spacePressed = false;
454
- this.player.position.addScaledVector(this.playerVelocity, delta);
455
- this.player.updateMatrixWorld();
456
- }, 200);
457
- }
458
- if (this.sustainSpacePressed && this.playerIsOnGround) {
459
- this.playPersonAnimationByName("jumping");
460
- setTimeout(() => {
461
- this.playerVelocity.y = this.highJumpHeight;
462
- this.playerIsOnGround = false;
463
- this.spacePressed = false;
464
- this.player.position.addScaledVector(this.playerVelocity, delta);
465
- this.player.updateMatrixWorld();
466
- }, 200);
469
+ if (this.isFlying) {
470
+ if (this.fwdPressed) {
471
+ this.moveDir.y = this.camDir.y;
472
+ } else {
473
+ this.moveDir.y = 0;
474
+ }
475
+ if (this.spacePressed) {
476
+ this.moveDir.add(this.DIR_UP);
477
+ }
467
478
  }
468
- this.playerSpeed = this.shiftPressed ? 900 * this.playerModel.scale : 400 * this.playerModel.scale;
469
- if (this.moveDir.lengthSq() > 1e-6) {
470
- this.moveDir.normalize().applyAxisAngle(this.upVector, angle);
471
- this.player.position.addScaledVector(this.moveDir, this.playerSpeed * delta);
479
+ if (this.isFlying && this.fwdPressed) {
480
+ this.playerSpeed = this.shiftPressed ? 4e3 * this.playerModel.scale : 3e3 * this.playerModel.scale;
481
+ } else {
482
+ this.playerSpeed = this.shiftPressed ? 900 * this.playerModel.scale : 400 * this.playerModel.scale;
472
483
  }
484
+ this.moveDir.normalize().applyAxisAngle(this.upVector, angle);
485
+ this.player.position.addScaledVector(this.moveDir, this.playerSpeed * delta);
473
486
  let playerDistanceFromGround = Infinity;
474
487
  this._originTmp.set(this.player.position.x, this.player.position.y, this.player.position.z);
475
488
  this._raycaster.ray.origin.copy(this._originTmp);
@@ -481,26 +494,30 @@ var PlayerController = class {
481
494
  const maxH = this.playerHeight * this.playerModel.scale * 0.9;
482
495
  const h = this.playerHeight * this.playerModel.scale * 0.75;
483
496
  const minH = this.playerHeight * this.playerModel.scale * 0.7;
484
- if (playerDistanceFromGround > maxH) {
485
- this.playerVelocity.y += delta * this.gravity;
486
- this.player.position.addScaledVector(this.playerVelocity, delta);
487
- this.playerIsOnGround = false;
488
- } else if (playerDistanceFromGround > h && playerDistanceFromGround < maxH) {
489
- if (angle2 >= 0 && angle2 < 5) {
490
- this.player.position.y = intersects[0].point.y + h;
497
+ console.log(angle2, playerDistanceFromGround, maxH, h, minH);
498
+ if (this.isFlying) {
499
+ } else {
500
+ if (playerDistanceFromGround > maxH) {
501
+ this.playerVelocity.y += delta * this.gravity;
502
+ this.player.position.addScaledVector(this.playerVelocity, delta);
503
+ this.playerIsOnGround = false;
504
+ } else if (playerDistanceFromGround > h && playerDistanceFromGround < maxH) {
505
+ if (angle2 >= 0 && angle2 < 5) {
506
+ this.playerVelocity.y += delta * this.gravity;
507
+ this.player.position.addScaledVector(this.playerVelocity, delta);
508
+ this.playerIsOnGround = true;
509
+ } else {
510
+ this.playerVelocity.set(0, 0, 0);
511
+ this.playerIsOnGround = true;
512
+ }
513
+ } else if (playerDistanceFromGround > minH && playerDistanceFromGround < h) {
491
514
  this.playerVelocity.set(0, 0, 0);
492
515
  this.playerIsOnGround = true;
493
- } else {
516
+ } else if (playerDistanceFromGround < minH) {
494
517
  this.playerVelocity.set(0, 0, 0);
518
+ this.player.position.set(this.player.position.x, intersects[0].point.y + h, this.player.position.z);
495
519
  this.playerIsOnGround = true;
496
520
  }
497
- } else if (playerDistanceFromGround > minH && playerDistanceFromGround < h) {
498
- this.playerVelocity.set(0, 0, 0);
499
- this.playerIsOnGround = true;
500
- } else if (playerDistanceFromGround < minH) {
501
- this.playerVelocity.set(0, 0, 0);
502
- this.player.position.set(this.player.position.x, intersects[0].point.y + h, this.player.position.z);
503
- this.playerIsOnGround = true;
504
521
  }
505
522
  }
506
523
  this.player.updateMatrixWorld();
@@ -532,13 +549,10 @@ var PlayerController = class {
532
549
  });
533
550
  const newPosition = this.tempVector.copy(this.tempSegment.start).applyMatrix4(this.collider.matrixWorld);
534
551
  const deltaVector = this.tempVector2.subVectors(newPosition, this.player.position);
535
- const len = deltaVector.length();
536
- const offset = Math.max(0, len - 1e-5);
537
- if (offset > 0 && len > 0) {
538
- const n = deltaVector.multiplyScalar(1 / len);
539
- this.player.position.addScaledVector(n, offset);
540
- }
541
- if (!this.isFirstPerson && this.moveDir.lengthSq() > 0) {
552
+ const offset = Math.max(0, deltaVector.length() - 1e-5);
553
+ deltaVector.normalize().multiplyScalar(offset);
554
+ this.player.position.add(deltaVector);
555
+ if (!this.isFirstPerson && this.moveDir.lengthSq() > 0 && !this.isFlying) {
542
556
  this.camDir.y = 0;
543
557
  this.camDir.normalize();
544
558
  this.camDir.negate();
@@ -550,6 +564,18 @@ var PlayerController = class {
550
564
  const alpha = Math.min(1, this.rotationSpeed * delta);
551
565
  this.player.quaternion.slerp(this.targetQuat, alpha);
552
566
  }
567
+ if (this.isFlying) {
568
+ this.camDir.y = 0;
569
+ this.camDir.normalize();
570
+ this.camDir.negate();
571
+ this.moveDir.normalize();
572
+ this.moveDir.negate();
573
+ const lookTarget = this.player.position.clone().add(this.fwdPressed ? this.moveDir : this.camDir);
574
+ this.targetMat.lookAt(this.player.position, lookTarget, this.player.up);
575
+ this.targetQuat.setFromRotationMatrix(this.targetMat);
576
+ const alpha = Math.min(1, this.rotationSpeed * delta);
577
+ this.player.quaternion.slerp(this.targetQuat, alpha);
578
+ }
553
579
  if (!this.isFirstPerson) {
554
580
  const lookTarget = this.player.position.clone();
555
581
  lookTarget.y += 30 * this.playerModel.scale;
@@ -570,18 +596,15 @@ var PlayerController = class {
570
596
  const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
571
597
  this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
572
598
  } else {
573
- const dis = this.player.position.distanceTo(this.camera.position);
574
599
  this._raycasterPersonToCam.far = this._maxCamDistance;
575
600
  const intersectsMaxDis = this._raycasterPersonToCam.intersectObject(this.collider, false);
576
- if (dis < this._maxCamDistance) {
577
- let safeDist = this._maxCamDistance;
578
- if (intersectsMaxDis.length) {
579
- const hitMax = intersectsMaxDis[0];
580
- safeDist = hitMax.distance - this._camEpsilon;
581
- }
582
- const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
583
- this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
601
+ let safeDist = this._maxCamDistance;
602
+ if (intersectsMaxDis.length) {
603
+ const hitMax = intersectsMaxDis[0];
604
+ safeDist = hitMax.distance - this._camEpsilon;
584
605
  }
606
+ const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
607
+ this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
585
608
  }
586
609
  }
587
610
  if (this.player.position.y < this.boundingBoxMinY - 1) {
@@ -647,7 +670,6 @@ var PlayerController = class {
647
670
  // 更新模型动画
648
671
  updateMixers(delta) {
649
672
  if (this.personMixer) this.personMixer.update(delta);
650
- if (this.droneMixer) this.droneMixer.update(delta);
651
673
  }
652
674
  // BVH构建
653
675
  async createBVH(meshUrl = "") {