Create a First Person Movement in React Three Fiber - Part 2
Tags: react, tutorial, reactthreefiber, threejs
Published: 2022-09-26 05:42:18

Continuing with the series, in this post we are going to see **the real code** for this project. As always, the entire project is available in my personal repo below:

{% embed https://github.com/jgcarrillo/react-fp-movement %}

## Physics 🧲

For this example we are going to use [Reac Three Cannon](https://github.com/pmndrs/use-cannon) a specific library to create **physics**. You can use [Rapier](https://github.com/pmndrs/react-three-rapier), another cool library, but is under development right now.

To set up physics you need to import the appropriate geometry such as **plane geometry, sphere geometry**, etc. Then you need to **establish  the physics options** like mass, position, etc.

In the code below you can see the **floor component** a 2D plane. We need that the plane has physics but no mass since in that case it would go into a downward loop.

```js
// Floor.js

import { usePlane } from '@react-three/cannon';

const Floor = (props) => {
  const [ref] = usePlane((index) => ({ type: 'Static', mass: 0, ...props }));

  return (
    <mesh receiveShadow rotation={props.rotation} ref={ref}>
      <planeGeometry args={[1000, 1000]} />
      <meshStandardMaterial color={props.color} />
    </mesh>
  );
};
```

From now, every of our components will have physics as they would otherwise go into an **infinite drop** and behave strangely.

## Important components 📚

We are not going to see all the code of the components but it's important to know **some key concepts**. The next component is `ThreeModel.js` which is the model of the three. To do this I have used a model from internet and [this utility](https://gltf.pmnd.rs/) to create a **React component from a gLTF**.

> glTF (derivative short form of Graphics Language Transmission Format or GL Transmission Format) is a standard file format for three-dimensional scenes and models. [Wikipedia](https://en.wikipedia.org/wiki/GlTF)

The point is that you need to set up the physics as following. The important thing to know is that you need to set the **size of the hit box** that corresponds to the model.

In the [following image from here](https://www.gamedeveloper.com/design/hitboxes-and-hurtboxes-in-unity) you can see the concept.

![Hit box of a character](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5v86mnfrptnpekzd978d.jpg)

So, with this code I have created a hit box with **the same size as the three**. I know it's difficult at first. We are receiving all these options **through props** to make the component more *reusable*.

```js
// Physics for ThreeModel.js
// Don't forget to put your models inside the public folder

const [ref] = useBox((index) => ({
  type: 'Static',
  mass: 1,
  args: props.args,
  position: props.position,

  ...props,
}));
```

Probably the **most tricky** component is the character because we need to define physics, movement and also the position of the camera. It has a lot of code but we are going to see the most interesting.

We use the **hook** `useThree` to access to the **state model** such as camera, renderer, scene, etc. Then, we need to define the **position of the world**. Finally, we set up the character movement.

```js
// BaseCharacter.js

// Access to the state model
const { camera } = useThree();

// Set the current World position
ref.current.getWorldPosition(camera.position);

// Set the direction of the character
direction.subVectors(frontVector, sideVector).normalize().multiplyScalar(SPEED).applyEuler(camera.rotation);
```

Another important component is the **Scene**. In this case I have create a *basic scene** one. The important thing to know is the use of **React children** [prop](https://reactjs.org/docs/legacy-context.html#parent-child-coupling) to reuse the scene.

Here, you need to notice that I'm using `<PointerLockControls />` a component of **Drei library** to use the mouse as the same way you would use in a FPS.

```js
import { Canvas } from '@react-three/fiber';
import { Loader, PointerLockControls } from '@react-three/drei';
import { Physics } from '@react-three/cannon';

import Lights from '../components/Lights.js';
import Floor from '../components/Floor.js';

const BasicScene = ({ children }) => {
  return (
    <div>
      <Canvas shadows camera={{ fov: 50 }}>
        <Lights />

        <Physics gravity={[0, -9.8, 0]}>
          {children}

          <Floor rotation={[Math.PI / -2, 0, 0]} color="white" />
        </Physics>

        <PointerLockControls />
      </Canvas>
      <Loader />
    </div>
  );
};

export default BasicScene;
```

Another importat thing is that the physics **only works** within `Physics` component.

The `helper.js` file contains the movement for different geometries. I'm not going to explain this because **I found it on internet in one of the R3F examples** and it's not difficult to set up.

## Creating the scene 🎭

So, that's it! The next step is to create the scene within the `App.js` component. It's also important to set up the **CSS styles** for the canvas.

```css
* {
  box-sizing: border-box;
}

html,
body,
canvas {
  width: 100%;
  max-height: 100vh;
  max-width: 100wh;
  height: 100%;
  margin: 0;
  padding: 0;
}
```

I hope you find it useful as I did. You can see the final project [here](https://react-fp-movement.netlify.app/). Feel free to reach me out and start creating your own projects. 💪💪