1
1
import { useKeyboardControls } from "@react-three/drei" ;
2
2
import { useFrame } from "@react-three/fiber" ;
3
- import { RigidBody , CapsuleCollider , useRapier } from "@react-three/rapier" ;
4
- import { useEffect , useRef , useMemo } from "react" ;
3
+ import {
4
+ RigidBody ,
5
+ CapsuleCollider ,
6
+ useRapier ,
7
+ RapierRigidBody ,
8
+ } from "@react-three/rapier" ;
9
+ import { useEffect , useRef , useMemo , type ReactNode } from "react" ;
5
10
import * as THREE from "three" ;
6
11
import { useControls } from "leva" ;
7
- import useFollowCam from "./hooks/useFollowCam" ;
8
- import useGame from "./stores/useGame" ;
12
+ import { useFollowCam } from "./hooks/useFollowCam" ;
13
+ import { useGame } from "./stores/useGame" ;
14
+ import type {
15
+ Collider ,
16
+ RayColliderToi ,
17
+ Vector ,
18
+ } from "@dimforge/rapier3d-compat" ;
9
19
10
- export { EcctrlAnimation } from "./EcctrlAnimation"
20
+ export { EcctrlAnimation } from "./EcctrlAnimation" ;
11
21
12
22
export default function Ecctrl ( {
13
23
children,
@@ -57,10 +67,9 @@ export default function Ecctrl({
57
67
autoBalanceDampingOnY = 0.02 ,
58
68
// Animation temporary setups
59
69
animated = false ,
60
- ...props
61
- } ) {
62
- const characterRef = useRef ( ) ;
63
- const characterModelRef = useRef ( ) ;
70
+ } : EcctrlProps ) {
71
+ const characterRef = useRef < RapierRigidBody > ( ) ;
72
+ const characterModelRef = useRef < THREE . Group > ( ) ;
64
73
65
74
// Animation change functions
66
75
const idleAnimation = ! animated ? null : useGame ( ( state ) => state . idle ) ;
@@ -345,7 +354,7 @@ export default function Ecctrl({
345
354
/**
346
355
* Initial light setup
347
356
*/
348
- let dirLight = null ;
357
+ let dirLight : THREE . DirectionalLight = null ;
349
358
350
359
/**
351
360
* Follow camera initial setups from props
@@ -384,28 +393,33 @@ export default function Ecctrl({
384
393
const characterMassForce = useMemo ( ( ) => new THREE . Vector3 ( ) , [ ] ) ;
385
394
const rayOrigin = useMemo ( ( ) => new THREE . Vector3 ( ) , [ ] ) ;
386
395
const rayCast = new rapier . Ray ( rayOrigin , rayDir ) ;
387
- let rayHit = null ;
396
+ let rayHit : RayColliderToi = null ;
388
397
389
398
/**Test shape ray */
390
399
// const shape = new rapier.Capsule(0.2,0.1)
391
400
392
401
/**
393
402
* Slope detection ray setup
394
403
*/
395
- let slopeAngle = null ;
396
- let actualSlopeNormal = null ;
397
- let actualSlopeAngle = null ;
404
+ let slopeAngle : number = null ;
405
+ let actualSlopeNormal : Vector = null ;
406
+ let actualSlopeAngle : number = null ;
398
407
const actualSlopeNormalVec = useMemo ( ( ) => new THREE . Vector3 ( ) , [ ] ) ;
399
408
const floorNormal = useMemo ( ( ) => new THREE . Vector3 ( 0 , 1 , 0 ) , [ ] ) ;
400
- const slopeRayOriginRef = useRef ( ) ;
409
+ const slopeRayOriginRef = useRef < THREE . Mesh > ( ) ;
401
410
const slopeRayorigin = useMemo ( ( ) => new THREE . Vector3 ( ) , [ ] ) ;
402
411
const slopeRayCast = new rapier . Ray ( slopeRayorigin , slopeRayDir ) ;
403
- let slopeRayHit = null ;
412
+ let slopeRayHit : RayColliderToi = null ;
404
413
405
414
/**
406
415
* Character moving function
407
416
*/
408
- const moveCharacter = ( delta , run , slopeAngle , movingObjectVelocity ) => {
417
+ const moveCharacter = (
418
+ _ : number ,
419
+ run : boolean ,
420
+ slopeAngle : number ,
421
+ movingObjectVelocity : THREE . Vector3
422
+ ) => {
409
423
/**
410
424
* Setup moving direction
411
425
*/
@@ -520,11 +534,15 @@ export default function Ecctrl({
520
534
}
521
535
522
536
// Move character at proper direction and impulse
523
- characterRef . current . applyImpulseAtPoint ( moveImpulse , {
524
- x : currentPos . x ,
525
- y : currentPos . y + moveImpulsePointY ,
526
- z : currentPos . z ,
527
- } ) ;
537
+ characterRef . current . applyImpulseAtPoint (
538
+ moveImpulse ,
539
+ {
540
+ x : currentPos . x ,
541
+ y : currentPos . y + moveImpulsePointY ,
542
+ z : currentPos . z ,
543
+ } ,
544
+ false
545
+ ) ;
528
546
} ;
529
547
530
548
/**
@@ -539,7 +557,7 @@ export default function Ecctrl({
539
557
- autoBalanceSpringK * characterRef . current . rotation ( ) . z -
540
558
characterRef . current . angvel ( ) . z * autoBalanceDampingC
541
559
) ;
542
- characterRef . current . applyTorqueImpulse ( dragAngForce ) ;
560
+ characterRef . current . applyTorqueImpulse ( dragAngForce , false ) ;
543
561
} ;
544
562
545
563
useEffect ( ( ) => {
@@ -549,7 +567,7 @@ export default function Ecctrl({
549
567
( item ) => {
550
568
return item . type === "DirectionalLight" ;
551
569
}
552
- ) ;
570
+ ) as THREE . DirectionalLight ;
553
571
}
554
572
555
573
// Action 1 key subscribe for special animation
@@ -605,14 +623,15 @@ export default function Ecctrl({
605
623
characterRef . current . setEnabledRotations (
606
624
autoBalance ? true : false ,
607
625
autoBalance ? true : false ,
608
- autoBalance ? true : false
626
+ autoBalance ? true : false ,
627
+ false
609
628
) ;
610
629
} , [ autoBalance ] ) ;
611
630
612
631
useFrame ( ( state , delta ) => {
613
632
// Character current position
614
633
if ( characterRef . current ) {
615
- currentPos . copy ( characterRef . current . translation ( ) ) ;
634
+ currentPos . copy ( characterRef . current . translation ( ) as THREE . Vector3 ) ;
616
635
}
617
636
618
637
/**
@@ -664,7 +683,7 @@ export default function Ecctrl({
664
683
665
684
// Character current velocity
666
685
if ( characterRef . current ) {
667
- currentVel . copy ( characterRef . current . linvel ( ) ) ;
686
+ currentVel . copy ( characterRef . current . linvel ( ) as THREE . Vector3 ) ;
668
687
}
669
688
670
689
// Jump impulse
@@ -680,7 +699,8 @@ export default function Ecctrl({
680
699
jumpDirection
681
700
. set ( 0 , ( run ? sprintJumpMult * jumpVel : jumpVel ) * slopJumpMult , 0 )
682
701
. projectOnVector ( actualSlopeNormalVec )
683
- . add ( jumpVelocityVec )
702
+ . add ( jumpVelocityVec ) ,
703
+ false
684
704
) ;
685
705
// Apply jump force downward to the standing platform
686
706
characterMassForce . y *= jumpForceToGroundMult ;
@@ -710,14 +730,15 @@ export default function Ecctrl({
710
730
/**
711
731
* Ray casting detect if on ground
712
732
*/
713
- rayOrigin . addVectors ( currentPos , rayOriginOffest ) ;
733
+ rayOrigin . addVectors ( currentPos , rayOriginOffest as THREE . Vector3 ) ;
714
734
rayHit = world . castRay (
715
735
rayCast ,
716
736
rayLength ,
717
737
false ,
718
738
null ,
719
739
null ,
720
- characterRef . current
740
+ // I have no idea
741
+ characterRef . current as unknown as Collider
721
742
) ;
722
743
/**Test shape ray */
723
744
// rayHit = world.castShape(
@@ -765,11 +786,15 @@ export default function Ecctrl({
765
786
// Calculate distance between character and moving object
766
787
distanceFromCharacterToObject
767
788
. copy ( currentPos )
768
- . sub ( rayHit . collider . parent ( ) . translation ( ) ) ;
789
+ . sub ( rayHit . collider . parent ( ) . translation ( ) as THREE . Vector3 ) ;
769
790
// Moving object linear velocity
770
- const movingObjectLinvel = rayHit . collider . parent ( ) . linvel ( ) ;
791
+ const movingObjectLinvel = rayHit . collider
792
+ . parent ( )
793
+ . linvel ( ) as THREE . Vector3 ;
771
794
// Moving object angular velocity
772
- const movingObjectAngvel = rayHit . collider . parent ( ) . angvel ( ) ;
795
+ const movingObjectAngvel = rayHit . collider
796
+ . parent ( )
797
+ . angvel ( ) as THREE . Vector3 ;
773
798
// Combine object linear velocity and angular velocity to movingObjectVelocity
774
799
movingObjectVelocity . set (
775
800
movingObjectLinvel . x +
@@ -823,14 +848,16 @@ export default function Ecctrl({
823
848
false ,
824
849
null ,
825
850
null ,
826
- characterRef . current
851
+ // Still no idea
852
+ characterRef . current as unknown as Collider
827
853
) ;
828
854
829
855
// Calculate slope angle
830
856
if ( slopeRayHit ) {
831
857
actualSlopeNormal = slopeRayHit . collider . castRayAndGetNormal (
832
858
slopeRayCast ,
833
- slopeRayLength
859
+ slopeRayLength ,
860
+ false
834
861
) ?. normal ;
835
862
if ( actualSlopeNormal ) {
836
863
actualSlopeNormalVec ?. set (
@@ -843,9 +870,12 @@ export default function Ecctrl({
843
870
}
844
871
if ( slopeRayHit && rayHit && slopeRayHit . toi < floatingDis + 0.5 ) {
845
872
if ( canJump ) {
846
- slopeAngle = Math . atan (
847
- ( rayHit . toi - slopeRayHit . toi ) / slopeRayOriginOffest
848
- ) . toFixed ( 2 ) ;
873
+ // Round the slope angle to 2 decimal places
874
+ slopeAngle = Number (
875
+ Math . atan (
876
+ ( rayHit . toi - slopeRayHit . toi ) / slopeRayOriginOffest
877
+ ) . toFixed ( 2 )
878
+ ) ;
849
879
} else {
850
880
slopeAngle = null ;
851
881
}
@@ -862,7 +892,8 @@ export default function Ecctrl({
862
892
springK * ( floatingDis - rayHit . toi ) -
863
893
characterRef . current . linvel ( ) . y * dampingC ;
864
894
characterRef . current . applyImpulse (
865
- springDirVec . set ( 0 , floatingForce , 0 )
895
+ springDirVec . set ( 0 , floatingForce , 0 ) ,
896
+ false
866
897
) ;
867
898
868
899
// Apply opposite force to standing object (gravity g in rapier is 0.11 ?_?)
@@ -884,7 +915,7 @@ export default function Ecctrl({
884
915
0 ,
885
916
- currentVel . z * dragDampingC
886
917
) ;
887
- characterRef . current . applyImpulse ( dragForce ) ;
918
+ characterRef . current . applyImpulse ( dragForce , false ) ;
888
919
}
889
920
// on a moving object
890
921
else {
@@ -893,7 +924,7 @@ export default function Ecctrl({
893
924
0 ,
894
925
( movingObjectVelocity . z - currentVel . z ) * dragDampingC * 2
895
926
) ;
896
- characterRef . current . applyImpulse ( dragForce ) ;
927
+ characterRef . current . applyImpulse ( dragForce , false ) ;
897
928
}
898
929
}
899
930
@@ -966,3 +997,53 @@ export default function Ecctrl({
966
997
</ RigidBody >
967
998
) ;
968
999
}
1000
+
1001
+ export type EcctrlProps = {
1002
+ children ?: ReactNode ;
1003
+ debug ?: boolean ;
1004
+ capsuleHalfHeight ?: number ;
1005
+ capsuleRadius ?: number ;
1006
+ floatHeight ?: number ;
1007
+ followLight ?: boolean ;
1008
+ // Follow camera setups
1009
+ camInitDis ?: number ;
1010
+ camMaxDis ?: number ;
1011
+ camMinDis ?: number ;
1012
+ // Base control setups
1013
+ maxVelLimit ?: number ;
1014
+ turnVelMultiplier ?: number ;
1015
+ turnSpeed ?: number ;
1016
+ sprintMult ?: number ;
1017
+ jumpVel ?: number ;
1018
+ jumpForceToGroundMult ?: number ;
1019
+ slopJumpMult ?: number ;
1020
+ sprintJumpMult ?: number ;
1021
+ airDragMultiplier ?: number ;
1022
+ dragDampingC ?: number ;
1023
+ accDeltaTime ?: number ;
1024
+ rejectVelMult ?: number ;
1025
+ moveImpulsePointY ?: number ;
1026
+ camFollowMult ?: number ;
1027
+ // Floating Ray setups
1028
+ rayOriginOffest ?: { x : number ; y : number ; z : number } ;
1029
+ rayHitForgiveness ?: number ;
1030
+ rayLength ?: number ;
1031
+ rayDir ?: { x : number ; y : number ; z : number } ;
1032
+ floatingDis ?: number ;
1033
+ springK ?: number ;
1034
+ dampingC ?: number ;
1035
+ // Slope Ray setups
1036
+ showSlopeRayOrigin ?: boolean ;
1037
+ slopeRayOriginOffest ?: number ;
1038
+ slopeRayLength ?: number ;
1039
+ slopeRayDir ?: { x : number ; y : number ; z : number } ;
1040
+ slopeUpExtraForce ?: number ;
1041
+ slopeDownExtraForce ?: number ;
1042
+ // AutoBalance Force setups
1043
+ autoBalance ?: boolean ;
1044
+ autoBalanceSpringK ?: number ;
1045
+ autoBalanceDampingC ?: number ;
1046
+ autoBalanceDampingOnY ?: number ;
1047
+ // Animation temporary setups
1048
+ animated ?: boolean ;
1049
+ } ;
0 commit comments