Skip to content

Commit 9b05ff9

Browse files
feat: new mode camera based movement
1 parent bc0c4cf commit 9b05ff9

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ecctrl",
3-
"version": "1.0.56",
3+
"version": "1.0.57",
44
"author": "Erdong Chen",
55
"license": "MIT",
66
"description": "A floating rigibody character controller for R3F",

src/Ecctrl.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
116116
const characterModelRef = useRef<THREE.Group>();
117117
const characterModelIndicator = useMemo(() => new THREE.Object3D(), [])
118118

119+
/**
120+
* Mode setup
121+
*/
122+
let isModePointToMove = false
123+
const setCameraBased = useGame((state) => state.setCameraBased);
124+
const getCameraBased = useGame((state) => state.getCameraBased);
125+
if (mode) {
126+
if (mode === "PointToMove") isModePointToMove = true
127+
if (mode === "CameraBasedMovement") setCameraBased(true)
128+
}
129+
119130
/**
120131
* Body collider setup
121132
*/
@@ -664,7 +675,13 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
664675
bodyFacingVecOnY.set(bodyFacingVec.x, 0, bodyFacingVec.z)
665676
bodyBalanceVecOnZ.set(bodyBalanceVec.x, bodyBalanceVec.y, 0)
666677

667-
characterModelIndicator.getWorldDirection(modelFacingVec)
678+
// Check if is camera based movement
679+
if (getCameraBased().isCameraBased) {
680+
modelEuler.y = pivot.rotation.y
681+
pivot.getWorldDirection(modelFacingVec)
682+
} else {
683+
characterModelIndicator.getWorldDirection(modelFacingVec)
684+
}
668685
const crossVecOnX = vectorY.clone().cross(bodyBalanceVecOnX);
669686
const crossVecOnY = modelFacingVec.clone().cross(bodyFacingVecOnY);
670687
const crossVecOnZ = vectorY.clone().cross(bodyBalanceVecOnZ);
@@ -682,7 +699,7 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
682699
);
683700

684701
// Apply balance torque impulse
685-
characterRef.current.applyTorqueImpulse(dragAngForce, mode === "PointToMove" ? true : false)
702+
characterRef.current.applyTorqueImpulse(dragAngForce, true)
686703
};
687704

688705
/**
@@ -950,8 +967,15 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
950967
modelQuat,
951968
delta * turnSpeed
952969
);
953-
// If autobalance is off, rotate character model
954-
if (!autoBalance) characterModelRef.current.quaternion.copy(characterModelIndicator.quaternion)
970+
971+
// If autobalance is off, rotate character model itself
972+
if (!autoBalance) {
973+
if (getCameraBased().isCameraBased) {
974+
characterModelRef.current.quaternion.copy(pivot.quaternion)
975+
} else {
976+
characterModelRef.current.quaternion.copy(characterModelIndicator.quaternion)
977+
}
978+
}
955979

956980
/**
957981
* Camera movement
@@ -1201,7 +1225,7 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
12011225
/**
12021226
* Point to move feature
12031227
*/
1204-
if (mode && mode === "PointToMove") pointToMove(delta, slopeAngle, movingObjectVelocity)
1228+
isModePointToMove && pointToMove(delta, slopeAngle, movingObjectVelocity)
12051229

12061230
/**
12071231
* Apply all the animations
@@ -1246,7 +1270,7 @@ const Ecctrl = forwardRef<RapierRigidBody, EcctrlProps>(({
12461270
args={[capsuleHalfHeight, capsuleRadius]}
12471271
/>
12481272
{/* Body collide sensor (only for point to move mode) */}
1249-
{mode === "PointToMove" &&
1273+
{isModePointToMove &&
12501274
<CylinderCollider
12511275
ref={bodySensorRef}
12521276
sensor

src/stores/useGame.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ export const useGame = /* @__PURE__ */ create(
1010
*/
1111
pointToMovePoint: null as THREE.Vector3,
1212

13+
/**
14+
* Check is camera based movement
15+
*/
16+
isCameraBased: false as boolean,
17+
1318
/**
1419
* Character animations state manegement
1520
*/
@@ -159,6 +164,21 @@ export const useGame = /* @__PURE__ */ create(
159164
pointToMovePoint: get().pointToMovePoint,
160165
};
161166
},
167+
168+
/**
169+
* Set/get camera based movement
170+
*/
171+
setCameraBased: (isCameraBased: boolean) => {
172+
set(() => {
173+
return { isCameraBased: isCameraBased };
174+
});
175+
},
176+
177+
getCameraBased: () => {
178+
return {
179+
isCameraBased: get().isCameraBased,
180+
};
181+
},
162182
};
163183
})
164184
);
@@ -180,6 +200,7 @@ export type AnimationSet = {
180200

181201
type State = {
182202
pointToMovePoint: THREE.Vector3;
203+
isCameraBased: boolean;
183204
curAnimation: string;
184205
animationSet: AnimationSet;
185206
initializeAnimationSet: (animationSet: AnimationSet) => void;
@@ -188,6 +209,10 @@ type State = {
188209
getPointToMovePoint: () => {
189210
pointToMovePoint: THREE.Vector3;
190211
}
212+
setCameraBased: (isCameraBased: boolean) => void;
213+
getCameraBased: () => {
214+
isCameraBased: boolean;
215+
}
191216
} & {
192217
[key in keyof AnimationSet]: () => void;
193218
};

0 commit comments

Comments
 (0)