@jaimebboyjt/tres-fps-controls
Version:
Easy to use First Person Controls for TresJS
257 lines (197 loc) • 8.21 kB
Markdown
# Tres FPS controls
> First person shooter controls to easily create 3D shooter experiences (or other first person experiences).
- 💡 Works out of the box
- ⚡️ Powered by [Tresjs](https://tresjs.org/), [VueJs](https://vuejs.org/) + [ThreeJs](https://threejs.org/)
- 🦾 Fully configurable
## Installation
```bash
pnpm i @jaimebboyjt/tres-fps-controls
```
## Demos

All the examples can be found in: [Examples](https://github.com/JaimeTorrealba/fps-controls/tree/main/playground/src/pages).
# How to use it
To get started you can simply import the main component and use it.
```html
<script setup>
import { TresCanvas } from "@tresjs/core";
import { fpsControls } from "@jaimebboyjt/tres-fps-controls";
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls />
</TresCanvas>
</template>
```
That's it. Now you're going to have a shooter controller. The WASD keys allow you to move and the mouse pointer changes where you look.
> [!NOTE]
> This package uses [PointerLockControls](https://cientos.tresjs.org/guide/controls/pointer-lock-controls.html) from [cientos](https://cientos.tresjs.org/).
## ControlsKey
We can provide a `controlsKeys` prop to change, add or remove some of the basic functionalities.
```js
export default {
props: {
controlsKeys: {
type: Array,
default: () => [
{ name: 'forward', key: 'w' },
{ name: 'backward', key: 's' },
{ name: 'left', key: 'a' },
{ name: 'right', key: 'd' },
// Optionals
{ name: 'run', key: 'Shift', speed: moveSpeed * 2 },
{ name: 'creep', key: 'ctrl', speed: moveSpeed * 0.25 },
// Mouse actions
{ name: 'leftClick', action: () => { } },
{ name: 'rightClick', action: () => { } },
{ name: 'middleClick', action: () => { } },
{ name: 'wheelActionUp', action: () => { } },
{ name: 'wheelActionDown', action: () => { } },
// Key actions
{
name: 'actions', actions: // You can have as many events as you want 🥳
[
{ name: 'action', key: 'e', action: () => {} },
{ name: 'action', key: 'q', action: () => {} },
{ name: 'action', key: 'r', action: () => {} },
{ name: 'action', key: 'f', action: () => {} },
],
},
],
},
}
}
```
> [!TIP]
> Under the hood we use [useMagicKeys](https://vueuse.org/core/useMagicKeys/#usemagickeys). Check out [all the possible keycodes](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values).
As you can see we can provide different actions, including an array of actions using the keyboard.
```html
<script setup>
import { TresCanvas } from "@tresjs/core";
import { fpsControls } from "@jaimebboyjt/tres-fps-controls";
const keyboardMap = [
{ name: "run", key: "q", speed: 0.5 },
{ name: "creep", key: "e" },
{ name: "leftClick", action: () => animationSword() },
{
name: "actions",
actions: [
{ name: "action2", key: "f", action: () => console.log("F press") },
{ name: "action4", key: "r", action: () => console.log("R press") },
],
},
{ name: "wheelActionUp", action: () => console.log("up") },
{ name: "wheelActionDown", action: () => console.log("down") },
];
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls :controlsKeys="keyboardMap" />
</TresCanvas>
</template>
```
### Other props
| Prop | Description | Type | Default |
| :-------------- | :---------------------------------------------------------------------------------------- | ----------------- | ----------- |
| **moveSpeed** | Move speed | Number | `0.1` |
| **camera** | The camera to control | Camera | `undefined` |
| **domElement** | The dom element to listen to | HTMLCanvasElement | `undefined` |
| **selector** | Accept an id element as string, if it is set, the new element will be used as the trigger | String | `undefined` |
## Add weapons (models)
Do you want to add a weapon? Like a pistol, that is always with your character? It couldn't be easier:
Just add your desired model as a slot (learn how to load models here). For example:
```html
...
<fpsControls>
<Suspense>
<GLTFModel path="/PixelArt Medieval Sword.glb" :scale="0.4"
:position="[-4.5, -3, -5]" // Don't forget set the z axis :rotation="[0, 1,
0]" />
</Suspense>
</fpsControls>
...
```
This will make your model update its position each time you move.
> [!IMPORTANT]
> Normally you would set up the z axis, so the model is in front of you camera.
### Expose methods
Do you still need more configurations?
We provide all the methods for you, **exposed** by the component, so you can use them as you like.
```js
const exposeMethods = {
root: PointerLockControlsRef,
models: wrapperRef,
moveMethods: {
forward: () => walkSystem.moveForward(),
backward: () => walkSystem.moveBackward(),
left: () => walkSystem.moveLeft(),
right: () => walkSystem.moveRight(),
run: () => walkSystem.applyRun(),
creep: () => walkSystem.applyCreep(),
stopCreep: () => walkSystem.stopCreep(),
stopRun: () => walkSystem.stopRun(),
stopSideward: () => walkSystem.stopSideward(),
stopForward: () => walkSystem.stopForward(),
}
}
```
For granular control each method comes with its `stop` method.
You can access all these methods using [Template ref](https://vuejs.org/guide/essentials/template-refs.html#template-refs), as you normally would do with your TresJs components.
### Events
We also provide some reactive events. Ej:
```html
<script>
import { fpsControls } from 'fpsControls'
const handleState = (e) => console.log(e)
const handleLock = (e) => console.log(e)
const onChange = (e) => console.log(e)
</script>
<template>
<TresCanvas window-size>
<TresPerspectiveCamera
:position="[0, 0, 3]"
:fov="45"
:aspect="1"
:near="0.1"
:far="1000"
/>
<fpsControls @state="handleState" @isLock="handleLock" @change="onChange" />
</TresCanvas>
</template>
```
| Event | Description |
| :--------- | :---------------------------------------------------------- |
| **state** | trigger when the state changes. |
| **isLock** | trigger whether the pointer is locked. |
| **change** | trigger when the character makes a move (moves the camera). |
Posible states:
```js
const states = {
idle: 'idle',
walking: 'walking',
running: 'running',
creeping: 'creeping',
}
```
## Gamepad
[Check example](/playground/src/pages/basics/GamepadDemo.vue) inside playground on how to use the a gamepad with this repo :D |
## Contributing
I appreciate your interest in this project! If you have any feedback, suggestions, or resources related to the controller, please feel free to share.
## License
[MIT](/LICENSE)
## Sponsors
If you like this package you can support my work [here](https://github.com/sponsors/JaimeTorrealba ☺️. A github star or just some words of appreciation are incredible.