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/README.md +28 -21
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +98 -76
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -76
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
100
|
-
if (!this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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 :
|
|
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 * (
|
|
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.
|
|
449
|
-
this.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
this.
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this.
|
|
456
|
-
}
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
this.
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
this.
|
|
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
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
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 = "") {
|