Reputation: 99
I'm making a small game in React and right now I'm trying to traverse the 3 dimensional world that I just generated. I'm using React Three Fiber and some other utility libraries to assist in this. For my character I'm just using a sphere object from @react-three/cannon and for the linear movements I made hook to handle the key-press logic. For some reason whenever I load my application my key presses are registered, but the sphere object never moves. Why is this occurring?
App.jsx
import "./App.css";
import React from "react";
import { Canvas } from "@react-three/fiber";
import { Physics } from "@react-three/cannon";
import Lights from "./Components/Lights";
import { Camera } from "./Components/Camera";
import Ground from "./Components/Ground";
import CubeModel from "./Components/CubeModel";
import { Person } from "./Components/Person";
import { range } from "./helperMethods/range";
const matrix = [];
const matrixFactory = (
length: number,
width: number,
height: number,
scale = 2.5
) => {
if (length <= 0 || width <= 0 || height <= 0) {
throw new Error("Dimensions cannot be 0 or less");
}
let i = 0;
for (let x of range(0, length - 1)) {
for (let y of range(0, width - 1)) {
for (let z of range(0, height - 1)) {
let cartesianCoordinates = [x * scale, y * scale, z * scale];
matrix[i] = cartesianCoordinates;
i++;
}
}
}
};
function App() {
matrixFactory(4, 4, 6);
return (
<div className="App">
<Canvas>
<Lights />
<Camera />
<Physics gravity={[0, -30, 0]}>
<Ground position={[0, 0, 0]} />
<Person position={[-20, 3, 10]} />
<React.Suspense fallback={null}>
{matrix.map((value, idx) => (
<React.Fragment key={idx}>
<CubeModel
position={[value[0], value[1], value[2]]}
/>
</React.Fragment>
))}
</React.Suspense>
</Physics>
</Canvas>
</div>
);
}
export default App;
Person.jsx
import React from "react";
import { useSphere } from "@react-three/cannon";
import { useThree, useFrame } from "@react-three/fiber";
import { useKeyboardControls } from "../hooks/useKeyboardControls";
import { Vector3 } from "three";
const SPEED = 6;
export function Person(props) {
const { camera } = useThree();
const { moveForward, moveBackward, moveLeft, moveRight } =
useKeyboardControls();
const [ref, api] = useSphere(() => ({
mass: 1,
type: "Dynamic",
...props,
}));
const velocity = React.useRef([0, 0, 0]);
React.useEffect(() => {
api.velocity.subscribe((v) => (velocity.current = v));
}, [api.velocity]);
useFrame(() => {
camera.position.copy(ref.current.position);
const direction = new Vector3();
const frontVector = new Vector3(
0,
0,
Number(moveBackward) - Number(moveForward)
);
const sideVector = new Vector3(
Number(moveLeft) - Number(moveRight),
0,
0
);
direction
.subVectors(frontVector, sideVector)
.normalize()
.multiplyScalar(SPEED)
.applyEuler(camera.rotation);
api.velocity.set(direction.x, velocity.current[1], direction.z);
});
return (
<>
<mesh ref={ref} />
</>
);
}
useKeyboardControls.js
import React from "react"
function actionByKey(key) {
const keys = {
KeyW: 'moveForward',
KeyS: 'moveBackward',
KeyA: 'moveLeft',
KeyD: 'moveRight'
}
return keys[key]
}
export const useKeyboardControls = () => {
const [movement, setMovement] = React.useState({
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false
})
React.useEffect(() => {
const handleKeyDown = (e) => {
// Movement key
if (actionByKey(e.code)) {
setMovement((state) => ({...state, [actionByKey(e.code)]: true}))
}
}
const handleKeyUp = (e) => {
// Movement key
if (actionByKey(e.code)) {
setMovement((state) => ({...state, [actionByKey(e.code)]: false}))
}
}
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
return () => {
document.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('keyup', handleKeyUp);
}
}, [])
return movement
}
Upvotes: 2
Views: 3953
Reputation: 101
I know the answer is late but I think you should add "allowSleep: false" property to your useSphere under type:"Dynamic" for example
In fact it allows the sphere to never be set to "sleep" mode which basically result in the object not moving at all.
Good to know for future ppl coming here
Upvotes: 1